C # There are many methods to restart the computer, and there are also many articles on the Internet. However, many methods provided on the Internet cannot obtain the permission to restart the computer in some cases, resulting in a restart failure. This article briefly discusses these methods.
Author: eaglet
The following two methods are described on the Internet:
System. Diagnostics. Process. Start ("shutdown", @ "/r ");
And
[DllImport ("user32.dll")]
Static extern bool ExitWindowsEx (ExitWindows uFlags, ShutdownReason dwReason );
[STAThread]
Static void Main (string [] args)
{
ExitWindowsEx (ExitWindows. LogOff, ShutdownReason. MajorOther & ShutdownReason. MinorOther );
// This statement will cancel the computer operation www.2cto.com
}
These two methods work normally, but in some special cases, such as when the desktop is locked by other users, the computer cannot be restarted. I encountered in my actual work that when the current screen was locked by the remote control software, my background daemon tried to restart the computer, and the above two methods failed. The reason for the analysis is that the remote control software has locked the screen with another account (usually windows service or network service ), at this time, the daemon fails to restart the computer with the current account because it has no permissions.
To solve this problem, we must grant sufficient permissions to the process, so I run the following code before calling ExitWindowsEx to grant the current process the permission to shut down the computer.
// Give current process SeShutdownPrivilege
TokPriv1Luid tp;
IntPtr hproc = GetCurrentProcess ();
IntPtr htok = IntPtr. Zero;
If (! OpenProcessToken (hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok ))
{
Throw new Exception ("Open Process 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 ("Lookup Privilege Value fail ");
}
If (! AdjustTokenPrivileges (htok, false, ref tp, 0, IntPtr. Zero, IntPtr. Zero ))
{
Throw new Exception ("Adjust Token Privileges fail ");
}
The code above grants the current process the permission to shut down the computer. It should be noted that the above Code requires sufficient permissions to be successfully executed. Generally, the current process needs to run in an account with at least system administrator permissions. If you do not have sufficient permissions, you need to use a program to simulate the system administrator permissions. The problem of simulating other account permissions is not covered in this article.
After the code above is added, the computer is successfully restarted after another user locks the machine.
Complete code is provided below
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 IntPtr GetCurrentProcess ();
[DllImport ("advapi32.dll", ExactSpelling = true, SetLastError = true)]
Private static extern bool OpenProcessToken (IntPtr h, int acc, ref IntPtr phtok );
[DllImport ("advapi32.dll", SetLastError = true)]
Private static extern bool LookupPrivilegeValue (string host, string name, ref long pluid );
[DllImport ("advapi32.dll", ExactSpelling = true, SetLastError = true)]
Private static extern bool AdjustTokenPrivileges (IntPtr htok, bool disall,
Ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen );
[DllImport ("user32.dll", ExactSpelling = true, SetLastError = true)]
Private static extern bool ExitWindowsEx (int flg, int rea );
# Endregion
Private const int SE_PRIVILEGE_ENABLED = 0x00000002;
Private const int TOKEN_QUERY = 0x00000008;
Private const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;
Private const string SE_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 int EWX_FORCEIFHUNG = 0x00000010;
# Endregion
Public static void DoExitWin (int flg)
{
// Give current process SeShutdownPrivilege
TokPriv1Luid tp;
IntPtr hproc = GetCurrentProcess ();
IntPtr htok = IntPtr. Zero;
If (! OpenProcessToken (hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok ))
{
Throw new Exception ("Open Process 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 ("Lookup Privilege Value fail ");
}
If (! AdjustTokenPrivileges (htok, false, ref tp, 0, IntPtr. Zero, IntPtr. Zero ))
{
Throw new Exception ("Adjust Token Privileges fail ");
}
// Exit windows
If (! ExitWindowsEx (flg, 0 ))
{
Throw new Exception ("Exit Windows fail ");
}
}
/// <Summary>
/// Reboot computer
/// </Summary>
/// <Param name = "force"> force reboot </param>
Public static void Reboot (bool force)
{
If (force)
{
DoExitWin (EWX_REBOOT | EWX_FORCE );
}
Else
{
DoExitWin (EWX_REBOOT | EWX_FORCEIFHUNG );
}
}
/// <Summary>
/// Reboot computer force if hung
/// </Summary>
Public static void Reboot ()
{
Reboot (false );
}
/// <Summary>
/// Shut down computer
/// </Summary>
/// <Param name = "force"> force shut down </param>
Public static void Shutdown (bool force)
{
If (force)
{
DoExitWin (EWX_SHUTDOWN | EWX_FORCE );
}
Else
{
DoExitWin (EWX_SHUTDOWN | EWX_FORCEIFHUNG );
}
}
/// <Summary>
/// Shut down computer force if hung
/// </Summary>
Public static void Shutdown ()
{
Shutdown (false );
}
/// <Summary>
/// Log off
/// </Summary>
/// <Param name = "force"> force logoff </param>
Public static void Logoff (bool force)
{
If (force)
{
DoExitWin (EWX_LOGOFF | EWX_FORCE );
}
Else
{
DoExitWin (EWX_LOGOFF | EWX_FORCEIFHUNG );
}
}
/// <Summary>
/// Logoff computer force if hung
/// </Summary>
Public static void Logoff ()
{
Logoff (false );
}
}
From eaglet