系統管理工具、安裝程式、排程軟體常需程式化控制 Windows 關機/重開機/登出。核心 API 為 ExitWindowsEx。
function ExitWindowsEx(uFlags: UINT; dwReserved: DWORD): BOOL; stdcall; external 'user32.dll';
const
EWX_LOGOFF = 0; { 登出 }
EWX_SHUTDOWN = 1; { 關機 }
EWX_REBOOT = 2; { 重開機 }
EWX_FORCE = 4; { 強制關閉應用程式(不儲存資料) }
EWX_POWEROFF = 8; { 關機並切斷電源 (ATX) }
EWX_FORCEIFHUNG = 10; { 僅強制關閉無回應程式 }
var
How: UINT;
begin
How := EWX_SHUTDOWN; { 或 EWX_REBOOT, EWX_LOGOFF }
if not ExitWindowsEx(How, 0) then
ShowMessage('操作失敗,錯誤碼: ' + IntToStr(GetLastError));
end;
在 NT 核心系統 (2000/XP/Vista/7/10/11) 上,呼叫進程需擁有 SE_SHUTDOWN_NAME 特權,否則 ExitWindowsEx 會失敗 (ERROR_PRIVILEGE_NOT_HELD = 1314)。
uses WinSvc; { 或手動宣告 OpenProcessToken, LookupPrivilegeValue, AdjustTokenPrivileges }
function EnableShutdownPrivilege: Boolean;
var
hToken: THandle;
tp: TTokenPrivileges;
begin
Result := False;
if OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, hToken) then
try
if LookupPrivilegeValue(nil, 'SeShutdownPrivilege', tp.Privileges[0].Luid) then
begin
tp.PrivilegeCount := 1;
tp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
Result := AdjustTokenPrivileges(hToken, False, tp, 0, nil, DWORD(0));
end;
finally
CloseHandle(hToken);
end;
end;
procedure TForm1.ShutdownSystem;
begin
if EnableShutdownPrivilege then
begin
if not ExitWindowsEx(EWX_SHUTDOWN or EWX_FORCEIFHUNG, 0) then
ShowMessage('關機失敗: ' + SysErrorMessage(GetLastError));
end
else
ShowMessage('無法取得關機特權,請以管理員身分執行。');
end;
支援遠端關機、倒數計時、自訂訊息、強制應用程式關閉:
function InitiateSystemShutdownEx(
lpMachineName: PWideChar; lpMessage: PWideChar;
dwTimeout: DWORD; bForceAppsClosed: BOOL; bRebootAfterShutdown: BOOL;
dwReason: DWORD): BOOL; stdcall; external 'advapi32.dll';
{ 範例:60 秒後重開機,顯示訊息 }
InitiateSystemShutdownEx(nil, '系統將在 60 秒後重新啟動進行更新', 60, True, True,
SHTDN_REASON_MAJOR_OPERATINGSYSTEM or SHTDN_REASON_MINOR_INSTALLATION or SHTDN_REASON_FLAG_PLANNED);
掌握 ExitWindowsEx 基本用法與 SE_SHUTDOWN_NAME 特權調整,是開發系統級工具的必備技能。新專案建議改用 InitiateSystemShutdownEx 獲得更豐富的控制選項。