// ==========================================================================
// system shutdown
// nSDType: 0 - Shutdown the system
// 1 - Shutdown the system and turn off the power (if supported)
// 2 - Shutdown the system and then restart the system
void SystemShutdown(UINT nSDType)
{
HANDLE hToken;
TOKEN_PRIVILEGES tkp ;
::OpenProcessToken(::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY, &hToken);
::LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid);
tkp.PrivilegeCount = 1 ; // set 1 privilege
tkp.Privileges[0].Attributes= SE_PRIVILEGE_ENABLED;
// get the shutdown privilege for this process
::AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
switch (nSDType)
{
case 0: ::ExitWindowsEx(EWX_SHUTDOWN|EWX_FORCE, 0); break;
case 1: ::ExitWindowsEx(EWX_POWEROFF|EWX_FORCE, 0); break;
case 2: ::ExitWindowsEx(EWX_REBOOT |EWX_FORCE, 0); break;
}
}
这段内容有点长,不太适合在丹尼尔的回答中进行讨论,所以我把它放在这里。
目前看来,你主要的问题是你的进程没有运行所需的权限来执行系统关闭操作。
ExitWindowsEx 的文档包含了以下内容:
为了关闭或重启系统, 调用进程必须使用
AdjustTokenPrivileges
函数来 启用SE_SHUTDOWN_NAME
权限。 更多信息请参考 使用特殊权限运行。
他们还提供了一些示例代码。如果需要,你可以直接复制这些代码。
#include<iostream>
using namespace std;
int main(){
system("shutdown -s -f -t 0");
}
关于 InitiateSystemShutdownEx
的一些工作代码:
// Get the process token
HANDLE hToken;
OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
&hToken);
// Build a token privilege request object for shutdown
TOKEN_PRIVILEGES tk;
tk.PrivilegeCount = 1;
tk.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
LookupPrivilegeValue(NULL, TEXT("SeShutdownPrivilege"), &tk.Privileges[0].Luid);
// Adjust privileges
AdjustTokenPrivileges(hToken, FALSE, &tk, 0, NULL, 0);
// Go ahead and shut down
InitiateSystemShutdownEx(NULL, NULL, 0, FALSE, FALSE, 0);
ExitWindowsEx
解决方案相比,这种方法的优点在于调用进程不需要属于活动用户。