如何在C++中启用SE_SHUTDOWN_NAME权限?按MSDN操作仍无法关机
在C++中启用SE_SHUTDOWN_NAME权限并实现系统关机的解决方法
标准权限流程的常见疏漏排查
如果你按照MSDN文档操作仍失败,先检查以下细节:
- 调用
OpenProcessToken时,必须传入TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY权限,且确保当前进程句柄有效 LookupPrivilegeValue的系统名称参数传NULL(指向本地系统),权限名称严格使用SE_SHUTDOWN_NAME- 执行
AdjustTokenPrivileges后,不要只看返回值,必须通过GetLastError()确认:若返回ERROR_NOT_ALL_ASSIGNED,说明当前用户根本没有被分配关机权限 - 关机函数参数要正确:比如
ExitWindowsEx需传入EWX_SHUTDOWN | EWX_FORCE(强制关闭未响应程序),远程桌面环境可能需要额外参数
可运行的完整代码示例
#include <windows.h> #include <iostream> bool EnableShutdownPrivilege() { HANDLE hToken; if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) { std::cerr << "OpenProcessToken 失败,错误码:" << GetLastError() << std::endl; return false; } LUID luid; if (!LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &luid)) { std::cerr << "LookupPrivilegeValue 失败,错误码:" << GetLastError() << std::endl; CloseHandle(hToken); return false; } TOKEN_PRIVILEGES tp; tp.PrivilegeCount = 1; tp.Privileges[0].Luid = luid; tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL)) { std::cerr << "AdjustTokenPrivileges 失败,错误码:" << GetLastError() << std::endl; CloseHandle(hToken); return false; } DWORD err = GetLastError(); if (err == ERROR_NOT_ALL_ASSIGNED) { std::cerr << "当前用户未被分配关机权限" << std::endl; CloseHandle(hToken); return false; } CloseHandle(hToken); return true; } int main() { if (EnableShutdownPrivilege()) { if (!ExitWindowsEx(EWX_SHUTDOWN | EWX_FORCE, SHTDN_REASON_MAJOR_OPERATINGSYSTEM | SHTDN_REASON_MINOR_UPGRADE)) { std::cerr << "ExitWindowsEx 失败,错误码:" << GetLastError() << std::endl; return 1; } } else { return 1; } return 0; }
替代方法与额外处理
如果标准流程仍无效,尝试以下方案:
- 改用
InitiateSystemShutdownEx函数:该函数权限控制更灵活,支持强制关机和远程操作,示例代码:if (!InitiateSystemShutdownEx(NULL, L"系统即将关机", 0, TRUE, TRUE, SHTDN_REASON_MAJOR_OPERATINGSYSTEM | SHTDN_REASON_MINOR_UPGRADE)) { std::cerr << "InitiateSystemShutdownEx 失败,错误码:" << GetLastError() << std::endl; } - 检查本地安全策略:打开「本地安全策略」→「本地策略」→「用户权限分配」→「关闭系统」,确保当前用户或所属组在列表中
- 强制管理员权限运行:在VS项目属性中设置「链接器」→「清单文件」→「UAC执行级别」为
requireAdministrator,或右键程序选择「以管理员身份运行」 - 远程桌面适配:若在远程会话中,需添加
EWX_LOGOFF参数,或确认远程桌面服务允许关机操作
内容的提问来源于stack exchange,提问作者Kaarthikeyan K
相关产品推荐
相关产品推荐

