C# 程序重启计算机的方法很多,网上也有不少这方面的文章,不过很多网上提供的方法在某些情况下无法获取重启计算机的权限导致重启失败。本文对这些方法做一些简单的讨论。
作者:eaglet
网上介绍最多的两种方法分别是:
1 |
System.Diagnostics.Process.Start(<span class="str">"shutdown"</span>,<span class="str">@"/r"</span>); |
和
1 2 3 4 5 6 7 8 9 |
[DllImport(<span class="str">"user32.dll"</span>)] <span class="kwrd">static</span> <span class="kwrd">extern</span> <span class="kwrd">bool</span> ExitWindowsEx(ExitWindows uFlags, ShutdownReason dwReason); [STAThread] <span class="kwrd">static</span> <span class="kwrd">void</span> Main(<span class="kwrd">string</span>[] args) { ExitWindowsEx(ExitWindows.LogOff, ShutdownReason.MajorOther & ShutdownReason.MinorOther); <span class="rem">//这个语句将实现计算机注销操作 </span> } |
这两种方法在通常情况下工作是没有问题的,但在某些特殊情况下,比如桌面被其它用户锁定时就无法重启计算机。本人在实际工作中遇到过当当前屏幕被远程控制软件锁定后,我做的后台守护进程试图重启计算机,结果用上述两种方法都无法成功。分析原因,应该是远程控制软件用另外的帐号锁定了屏幕(通常应该是windows service 或者 network service),这时守护进程用当前帐号重启计算机就因为没有权限而失败。
要解决这个问题,我们必须要给进程赋予足够的权限才行,于是我在调用 ExitWindowsEx 前运行了如下代码来赋予当前进程关闭计算机权限
1 |
1 |
<span class="rem">//give current process SeShutdownPrivilege</span> |
1 |
TokPriv1Luid tp; |
1 |
1 |
IntPtr hproc = GetCurrentProcess(); |
1 |
1 |
IntPtr htok = IntPtr.Zero; |
1 |
1 |
<span class="kwrd">if</span> (!OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, <span class="kwrd">ref</span> htok)) |
1 |
{ |
1 |
<span class="kwrd">throw</span> <span class="kwrd">new</span> Exception(<span class="str">"Open Process Token fail"</span>); |
1 |
} |
1 |
1 |
tp.Count = 1; |
1 |
1 |
tp.Luid = 0; |
1 |
1 |
tp.Attr = SE_PRIVILEGE_ENABLED; |
1 |
1 |
<span class="kwrd">if</span> (!LookupPrivilegeValue(<span class="kwrd">null</span>, SE_SHUTDOWN_NAME, <span class="kwrd">ref</span> tp.Luid)) |
1 |
{ |
1 |
<span class="kwrd">throw</span> <span class="kwrd">new</span> Exception(<span class="str">"Lookup Privilege Value fail"</span>); |
1 |
} |
1 |
1 |
<span class="kwrd">if</span> (!AdjustTokenPrivileges(htok, <span class="kwrd">false</span>, <span class="kwrd">ref</span> tp, 0, IntPtr.Zero, IntPtr.Zero)) |
1 |
{ |
1 |
<span class="kwrd">throw</span> <span class="kwrd">new</span> Exception(<span class="str">"Adjust Token Privileges fail"</span>); |
1 |
} |
上面代码为当前进程赋予了关闭计算机的权限。这里需要注意的是上述代码要执行成功同样需要足够的权限,通常当前进程需要以拥有至少是系统管理员权限的账户运行。如果没有足够权限,需要用程序模拟系统管理员权限,模拟其它帐号权限的问题不在本文讨论范围内。
加上如上代码后,在其他用户锁定机器后,重启计算机成功。
下面给出完整代码
1 2 |
<span class="kwrd"> using</span> System; |
1 |
<span class="kwrd">using</span> System.Collections.Generic; |
1 |
<span class="kwrd">using</span> System.Text; |
1 |
<span class="kwrd">using</span> System.Runtime.InteropServices; |
1 |
<span class="kwrd">using</span> System.Threading; |
1 |
1 |
<span class="kwrd">public</span> <span class="kwrd">class</span> ExitWindows |
1 |
{ |
1 |
<span class="preproc">#region</span> win32 api |
1 |
[StructLayout(LayoutKind.Sequential, Pack = 1)] |
1 |
1 |
<span class="kwrd">private</span> <span class="kwrd">struct</span> TokPriv1Luid |
1 |
{ |
1 |
1 |
<span class="kwrd">public</span> <span class="kwrd">int</span> Count; |
1 |
1 |
<span class="kwrd">public</span> <span class="kwrd">long</span> Luid; |
1 |
1 |
<span class="kwrd">public</span> <span class="kwrd">int</span> Attr; |
1 |
1 |
} |
1 |
1 |
[DllImport(<span class="str">"kernel32.dll"</span>, ExactSpelling = <span class="kwrd">true</span>)] |
1 |
<span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">extern</span> IntPtr GetCurrentProcess(); |
1 |
1 |
[DllImport(<span class="str">"advapi32.dll"</span>, ExactSpelling = <span class="kwrd">true</span>, SetLastError = <span class="kwrd">true</span>)] |
1 |
<span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">extern</span> <span class="kwrd">bool</span> OpenProcessToken(IntPtr h, <span class="kwrd">int</span> acc, <span class="kwrd">ref</span> IntPtr phtok); |
1 |
1 |
[DllImport(<span class="str">"advapi32.dll"</span>, SetLastError = <span class="kwrd">true</span>)] |
1 |
<span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">extern</span> <span class="kwrd">bool</span> LookupPrivilegeValue(<span class="kwrd">string</span> host, <span class="kwrd">string</span> name, <span class="kwrd">ref</span> <span class="kwrd">long</span> pluid); |
1 |
1 |
[DllImport(<span class="str">"advapi32.dll"</span>, ExactSpelling = <span class="kwrd">true</span>, SetLastError = <span class="kwrd">true</span>)] |
1 |
<span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">extern</span> <span class="kwrd">bool</span> AdjustTokenPrivileges(IntPtr htok, <span class="kwrd">bool</span> disall, |
1 |
<span class="kwrd">ref</span> TokPriv1Luid newst, <span class="kwrd">int</span> len, IntPtr prev, IntPtr relen); |
1 |
1 |
[DllImport(<span class="str">"user32.dll"</span>, ExactSpelling = <span class="kwrd">true</span>, SetLastError = <span class="kwrd">true</span>)] |
1 |
<span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">extern</span> <span class="kwrd">bool</span> ExitWindowsEx(<span class="kwrd">int</span> flg, <span class="kwrd">int</span> rea); |
1 |
1 |
<span class="preproc">#endregion</span> |
1 |
1 |
<span class="kwrd">private</span> <span class="kwrd">const</span> <span class="kwrd">int</span> SE_PRIVILEGE_ENABLED = 0x00000002; |
1 |
1 |
<span class="kwrd">private</span> <span class="kwrd">const</span> <span class="kwrd">int</span> TOKEN_QUERY = 0x00000008; |
1 |
1 |
<span class="kwrd">private</span> <span class="kwrd">const</span> <span class="kwrd">int</span> TOKEN_ADJUST_PRIVILEGES = 0x00000020; |
1 |
1 |
<span class="kwrd">private</span> <span class="kwrd">const</span> <span class="kwrd">string</span> SE_SHUTDOWN_NAME = <span class="str">"SeShutdownPrivilege"</span>; |
1 |
1 |
<span class="preproc">#region</span> Exit Windows Flags |
1 |
<span class="kwrd">private</span> <span class="kwrd">const</span> <span class="kwrd">int</span> EWX_LOGOFF = 0x00000000; |
1 |
1 |
<span class="kwrd">private</span> <span class="kwrd">const</span> <span class="kwrd">int</span> EWX_SHUTDOWN = 0x00000001; |
1 |
1 |
<span class="kwrd">private</span> <span class="kwrd">const</span> <span class="kwrd">int</span> EWX_REBOOT = 0x00000002; |
1 |
1 |
<span class="kwrd">private</span> <span class="kwrd">const</span> <span class="kwrd">int</span> EWX_FORCE = 0x00000004; |
1 |
1 |
<span class="kwrd">private</span> <span class="kwrd">const</span> <span class="kwrd">int</span> EWX_POWEROFF = 0x00000008; |
1 |
1 |
<span class="kwrd">private</span> <span class="kwrd">const</span> <span class="kwrd">int</span> EWX_FORCEIFHUNG = 0x00000010; |
1 |
1 |
<span class="preproc">#endregion</span> |
1 |
1 |
<span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">void</span> DoExitWin(<span class="kwrd">int</span> flg) |
1 |
{ |
1 |
1 |
<span class="rem">//give current process SeShutdownPrivilege</span> |
1 |
TokPriv1Luid tp; |
1 |
1 |
IntPtr hproc = GetCurrentProcess(); |
1 |
1 |
IntPtr htok = IntPtr.Zero; |
1 |
1 |
<span class="kwrd">if</span> (!OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, <span class="kwrd">ref</span> htok)) |
1 |
{ |
1 |
<span class="kwrd">throw</span> <span class="kwrd">new</span> Exception(<span class="str">"Open Process Token fail"</span>); |
1 |
} |
1 |
1 |
tp.Count = 1; |
1 |
1 |
tp.Luid = 0; |
1 |
1 |
tp.Attr = SE_PRIVILEGE_ENABLED; |
1 |
1 |
<span class="kwrd">if</span> (!LookupPrivilegeValue(<span class="kwrd">null</span>, SE_SHUTDOWN_NAME, <span class="kwrd">ref</span> tp.Luid)) |
1 |
{ |
1 |
<span class="kwrd">throw</span> <span class="kwrd">new</span> Exception(<span class="str">"Lookup Privilege Value fail"</span>); |
1 |
} |
1 |
1 |
<span class="kwrd">if</span> (!AdjustTokenPrivileges(htok, <span class="kwrd">false</span>, <span class="kwrd">ref</span> tp, 0, IntPtr.Zero, IntPtr.Zero)) |
1 |
{ |
1 |
<span class="kwrd">throw</span> <span class="kwrd">new</span> Exception(<span class="str">"Adjust Token Privileges fail"</span>); |
1 |
} |
1 |
1 |
<span class="rem">//Exit windows</span> |
1 |
<span class="kwrd">if</span> (!ExitWindowsEx(flg, 0)) |
1 |
{ |
1 |
<span class="kwrd">throw</span> <span class="kwrd">new</span> Exception(<span class="str">"Exit Windows fail"</span>); |
1 |
} |
1 |
} |
1 |
1 |
<span class="rem">/// <summary></span> |
1 |
<span class="rem">/// Reboot computer</span> |
1 |
<span class="rem">/// </summary></span> |
1 |
<span class="rem">/// <param name="force">force reboot</param></span> |
1 |
<span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">void</span> Reboot(<span class="kwrd">bool</span> force) |
1 |
{ |
1 |
<span class="kwrd">if</span> (force) |
1 |
{ |
1 |
DoExitWin(EWX_REBOOT | EWX_FORCE); |
1 |
} |
1 |
<span class="kwrd">else</span> |
1 |
{ |
1 |
DoExitWin(EWX_REBOOT | EWX_FORCEIFHUNG); |
1 |
} |
1 |
} |
1 |
1 |
<span class="rem">/// <summary></span> |
1 |
<span class="rem">/// Reboot computer force if hung</span> |
1 |
<span class="rem">/// </summary></span> |
1 |
<span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">void</span> Reboot() |
1 |
{ |
1 |
Reboot(<span class="kwrd">false</span>); |
1 |
} |
1 |
1 |
<span class="rem">/// <summary></span> |
1 |
<span class="rem">/// Shut down computer</span> |
1 |
<span class="rem">/// </summary></span> |
1 |
<span class="rem">/// <param name="force">force shut down</param></span> |
1 |
<span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">void</span> Shutdown(<span class="kwrd">bool</span> force) |
1 |
{ |
1 |
<span class="kwrd">if</span> (force) |
1 |
{ |
1 |
DoExitWin(EWX_SHUTDOWN | EWX_FORCE); |
1 |
} |
1 |
<span class="kwrd">else</span> |
1 |
{ |
1 |
DoExitWin(EWX_SHUTDOWN | EWX_FORCEIFHUNG); |
1 |
} |
1 |
} |
1 |
1 |
<span class="rem">/// <summary></span> |
1 |
<span class="rem">/// Shut down computer force if hung</span> |
1 |
<span class="rem">/// </summary></span> |
1 |
<span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">void</span> Shutdown() |
1 |
{ |
1 |
Shutdown(<span class="kwrd">false</span>); |
1 |
} |
1 |
1 |
<span class="rem">/// <summary></span> |
1 |
<span class="rem">/// Log off</span> |
1 |
<span class="rem">/// </summary></span> |
1 |
<span class="rem">/// <param name="force">force logoff</param></span> |
1 |
<span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">void</span> Logoff(<span class="kwrd">bool</span> force) |
1 |
{ |
1 |
<span class="kwrd">if</span> (force) |
1 |
{ |
1 |
DoExitWin(EWX_LOGOFF | EWX_FORCE); |
1 |
} |
1 |
<span class="kwrd">else</span> |
1 |
{ |
1 |
DoExitWin(EWX_LOGOFF | EWX_FORCEIFHUNG); |
1 |
} |
1 |
} |
1 |
1 |
<span class="rem">/// <summary></span> |
1 |
<span class="rem">/// logoff computer force if hung</span> |
1 |
<span class="rem">/// </summary></span> |
1 |
<span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">void</span> Logoff() |
1 |
{ |
1 |
Logoff(<span class="kwrd">false</span>); |
1 |
} |
1 |
} |
from:http://www.cnblogs.com/eaglet/archive/2012/04/13/2445674.html