Here’s a straightforward class I’ve created for shutting down, rebooting, and logging off Windows using the ExitWindowsEx
function. Each method in this class is overloaded with a variant that forces the action. This means it doesn’t allow Windows to send the WM_QUERYENDSESSION
message, preventing the user from canceling the action.
Here’s the complete code for the class:
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
static class ExitWindows {
private struct LUID {
public int LowPart;
public int HighPart;
}
private struct LUID_AND_ATTRIBUTES {
public LUID pLuid;
public int Attributes;
}
private struct TOKEN_PRIVILEGES {
public int PrivilegeCount;
public LUID_AND_ATTRIBUTES Privileges;
}
[DllImport("advapi32.dll")]
static extern int OpenProcessToken(IntPtr ProcessHandle,
int DesiredAccess, out IntPtr TokenHandle);
[DllImport("advapi32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool AdjustTokenPrivileges(IntPtr TokenHandle,
[MarshalAs(UnmanagedType.Bool)]bool DisableAllPrivileges,
ref TOKEN_PRIVILEGES NewState,
UInt32 BufferLength,
IntPtr PreviousState,
IntPtr ReturnLength);
[DllImport("advapi32.dll")]
static extern int LookupPrivilegeValue(string lpSystemName,
string lpName, out LUID lpLuid);
[DllImport("user32.dll", SetLastError = true)]
static extern int ExitWindowsEx(uint uFlags, uint dwReason);
const string SE_SHUTDOWN_NAME = "SeShutdownPrivilege";
const short SE_PRIVILEGE_ENABLED = 2;
const short TOKEN_ADJUST_PRIVILEGES = 32;
const short TOKEN_QUERY = 8;
const ushort EWX_LOGOFF = 0;
const ushort EWX_POWEROFF = 0x00000008;
const ushort EWX_REBOOT = 0x00000002;
const ushort EWX_RESTARTAPPS = 0x00000040;
const ushort EWX_SHUTDOWN = 0x00000001;
const ushort EWX_FORCE = 0x00000004;
private static void getPrivileges() {
IntPtr hToken;
TOKEN_PRIVILEGES tkp;
OpenProcessToken(Process.GetCurrentProcess().Handle,
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, out hToken);
tkp.PrivilegeCount = 1;
tkp.Privileges.Attributes = SE_PRIVILEGE_ENABLED;
LookupPrivilegeValue("", SE_SHUTDOWN_NAME,
out tkp.Privileges.pLuid);
AdjustTokenPrivileges(hToken, false, ref tkp,
0U, IntPtr.Zero, IntPtr.Zero);
}
public static void Shutdown() { Shutdown(false); }
public static void Shutdown(bool force) {
getPrivileges();
ExitWindowsEx(EWX_SHUTDOWN |
(uint)(force? EWX_FORCE : 0) | EWX_POWEROFF, 0);
}
public static void Reboot() { Reboot(false); }
public static void Reboot(bool force) {
getPrivileges();
ExitWindowsEx(EWX_REBOOT |
(uint)(force ? EWX_FORCE : 0), 0);
}
public static void LogOff() { LogOff(false); }
public static void LogOff(bool force) {
getPrivileges();
ExitWindowsEx(EWX_LOGOFF |
(uint)(force ? EWX_FORCE : 0), 0);
}
}
I hope you find this class helpful for managing system power states in your C# applications!