需開啟 SE_SHUTDOWN_NAME 權限,再呼叫 ExitWindowsEx 配合旗標實現不同操作。
using System;
using System.Runtime.InteropServices;
class Shutdown
{
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct TokPriv1Luid
{
public int Count;
public long Luid;
public int Attr;
}
[DllImport("kernel32.dll", ExactSpelling = true)]
static extern IntPtr GetCurrentProcess();
[DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
static extern bool OpenProcessToken(IntPtr h, int acc, ref IntPtr phtok);
[DllImport("advapi32.dll", SetLastError = true)]
static extern bool LookupPrivilegeValue(string host, string name, ref long pluid);
[DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall, ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen);
[DllImport("user32.dll", ExactSpelling = true, SetLastError = true)]
static extern bool ExitWindowsEx(int flg, int rea);
const int SE_PRIVILEGE_ENABLED = 0x00000002;
const int TOKEN_QUERY = 0x00000008;
const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;
const string SE_SHUTDOWN_NAME = "SeShutdownPrivilege";
const int EWX_LOGOFF = 0x00;
const int EWX_SHUTDOWN = 0x01;
const int EWX_REBOOT = 0x02;
const int EWX_FORCE = 0x04;
const int EWX_POWEROFF = 0x08;
const int EWX_FORCEIFHUNG = 0x10;
static void DoExitWin(int flg)
{
TokPriv1Luid tp = new TokPriv1Luid { Count = 1, Attr = SE_PRIVILEGE_ENABLED };
IntPtr hproc = GetCurrentProcess(), htok = IntPtr.Zero;
OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok);
LookupPrivilegeValue(null, SE_SHUTDOWN_NAME, ref tp.Luid);
AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero);
ExitWindowsEx(flg, 0);
}
public static void Main()
{
Console.WriteLine("正在關機……");
// 修改旗標:EWX_SHUTDOWN / EWX_REBOOT / EWX_LOGOFF / EWX_POWEROFF 等
DoExitWin(EWX_SHUTDOWN | EWX_FORCE);
}
}
EWX_SHUTDOWN (0x01):關機EWX_REBOOT (0x02):重啟EWX_LOGOFF (0x00):登出EWX_POWEROFF (0x08):切斷電源EWX_FORCE (0x04):強制關閉應用程式EWX_SHUTDOWN | EWX_FORCEXP 下可在命令列執行 SHUTDOWN /? 查看完整參數說明。