C# 重启计算机的问题

C# 程序重启计算机的方法很多,网上也有不少这方面的文章,不过很多网上提供的方法在某些情况下无法获取重启计算机的权限导致重启失败。本文对这些方法做一些简单的讨论。

网上介绍最多的两种方法分别是:

System.Diagnostics.Process.Start("shutdown",@"/r");

    [DllImport("user32.dll")]

    staticexternbool ExitWindowsEx(ExitWindowsuFlags, ShutdownReason dwReason);

 

    [STAThread]

     staticvoid Main(string[] args)

     {

           ExitWindowsEx(ExitWindows.LogOff, ShutdownReason.MajorOther &ShutdownReason.MinorOther);

            //这个语句将实现计算机注销操作  

     }

这两种方法在通常情况下工作是没有问题的,但在某些特殊情况下,比如桌面被其它用户锁定时就无法重启计算机。本人在实际工作中遇到过当当前屏幕被远程控制软件锁定后,我做的后台守护进程试图重启计算机,结果用上述两种方法都无法成功。分析原因,应该是远程控制软件用另外的帐号锁定了屏幕(通常应该是windows service 或者 networkservice),这时守护进程用当前帐号重启计算机就因为没有权限而失败。

要解决这个问题,我们必须要给进程赋予足够的权限才行,于是我在调用 ExitWindowsEx 前运行了如下代码来赋予当前进程关闭计算机权限

 

 

  //give current processSeShutdownPrivilege

  TokPriv1Luid tp;

 

  IntPtr hproc =GetCurrentProcess();

 

  IntPtr htok = IntPtr.Zero;

 

  if (!OpenProcessToken(hproc,TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok))

  {

       throw new Exception("Open Process Tokenfail");

  }

  tp.Count = 1;

  tp.Luid = 0;

        tp.Attr =SE_PRIVILEGE_ENABLED;

        if (!LookupPrivilegeValue(null,SE_SHUTDOWN_NAME, ref tp.Luid))

         {

       throw new Exception("LookupPrivilege Value fail");

   }

if (!AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero,IntPtr.Zero))

   {

      throw new Exception("Adjust TokenPrivileges fail");

   }

上面代码为当前进程赋予了关闭计算机的权限。这里需要注意的是上述代码要执行成功同样需要足够的权限,通常当前进程需要以拥有至少是系统管理员权限的账户运行。如果没有足够权限,需要用程序模拟系统管理员权限,模拟其它帐号权限的问题不在本文讨论范围内。

加上如上代码后,在其他用户锁定机器后,重启计算机成功。

下面给出完整代码

using System;

using System.Collections.Generic;

using System.Text;

using System.Runtime.InteropServices;

using System.Threading;

 

public class ExitWindows

{

    #region win32 api

   [StructLayout(LayoutKind.Sequential, Pack = 1)]

 

    private struct TokPriv1Luid

    {

 

        public int Count;

 

        public long Luid;

 

        public int Attr;

 

    }

 

    [DllImport("kernel32.dll",ExactSpelling = true)]

    private static extern IntPtrGetCurrentProcess();

 

    [DllImport("advapi32.dll",ExactSpelling = true, SetLastError = true)]

    private static extern boolOpenProcessToken(IntPtr h, int acc, ref IntPtr phtok);

 

    [DllImport("advapi32.dll",SetLastError = true)]

    private static extern boolLookupPrivilegeValue(string host, string name, ref long pluid);

 

    [DllImport("advapi32.dll",ExactSpelling = true, SetLastError = true)]

    private static extern boolAdjustTokenPrivileges(IntPtr htok, bool disall,

        ref TokPriv1Luid newst, intlen, IntPtr prev, IntPtr relen);

 

    [DllImport("user32.dll",ExactSpelling = true, SetLastError = true)]

    private static extern boolExitWindowsEx(int flg, int rea);

 

    #endregion

 

    private const intSE_PRIVILEGE_ENABLED = 0x00000002;

 

    private const int TOKEN_QUERY =0x00000008;

 

    private const intTOKEN_ADJUST_PRIVILEGES = 0x00000020;

 

    private const stringSE_SHUTDOWN_NAME = "SeShutdownPrivilege";

 

    #region Exit Windows Flags

    private const int EWX_LOGOFF =0x00000000;

 

    private const int EWX_SHUTDOWN =0x00000001;

 

    private const int EWX_REBOOT =0x00000002;

 

    private const int EWX_FORCE =0x00000004;

 

    private const int EWX_POWEROFF =0x00000008;

 

    private const intEWX_FORCEIFHUNG = 0x00000010;

 

    #endregion

   

    public static void DoExitWin(intflg)

    {

 

        //give current processSeShutdownPrivilege

        TokPriv1Luid tp;

 

        IntPtr hproc =GetCurrentProcess();

 

        IntPtr htok = IntPtr.Zero;

 

        if (!OpenProcessToken(hproc,TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok))

        {

            throw new Exception("OpenProcess Token fail");

        }

 

        tp.Count = 1;

 

        tp.Luid = 0;

 

        tp.Attr =SE_PRIVILEGE_ENABLED;

 

        if (!LookupPrivilegeValue(null,SE_SHUTDOWN_NAME, ref tp.Luid))

        {

            throw new Exception("LookupPrivilege Value fail");

        }

 

        if(!AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero))

        {

            throw new Exception("AdjustToken Privileges fail");

        }

 

        //Exit windows

        if (!ExitWindowsEx(flg, 0))

        {

            throw new Exception("ExitWindows fail");

        }

    }

 

    /// <summary>

    /// Reboot computer

    /// </summary>

    /// <paramname="force">force reboot</param>

    public static void Reboot(boolforce)

    {

        if (force)

        {

            DoExitWin(EWX_REBOOT |EWX_FORCE);

        }

        else

        {

            DoExitWin(EWX_REBOOT |EWX_FORCEIFHUNG);

        }

    }

 

    /// <summary>

    /// Reboot computer force ifhung

    /// </summary>

    public static void Reboot()

    {

        Reboot(false);

    }

 

    /// <summary>

    /// Shut down computer

    /// </summary>

    /// <paramname="force">force shut down</param>

    public static void Shutdown(boolforce)

    {

        if (force)

        {

            DoExitWin(EWX_SHUTDOWN |EWX_FORCE);

        }

        else

        {

            DoExitWin(EWX_SHUTDOWN |EWX_FORCEIFHUNG);

        }

    }

 

    /// <summary>

    /// Shut down computer force ifhung

    /// </summary>

    public static void Shutdown()

    {

        Shutdown(false);

    }

 

    /// <summary>

    /// Log off

    /// </summary>

    /// <paramname="force">force logoff</param>

    public static void Logoff(boolforce)

    {

        if (force)

        {

            DoExitWin(EWX_LOGOFF |EWX_FORCE);

        }

        else

        {

            DoExitWin(EWX_LOGOFF |EWX_FORCEIFHUNG);

        }

    }

 

    /// <summary>

    /// logoff computer force ifhung

    /// </summary>

   public static void Logoff()

    {

        Logoff(false);

    }

}

 

 
 

猜你喜欢

转载自blog.csdn.net/qiaoxinyu1989/article/details/51958876