一、Windows 实现关机/重启/注销的基本原理

在 Windows 中,关机、重启、注销属于系统级操作,普通程序不能直接调用,必须:

  1. 获取进程的关机权限(SE_SHUTDOWN_NAME)

  2. 调用系统 API 执行操作

Windows 提供了两类常见方式:

方式 特点
ExitWindowsEx 官方 API,推荐、规范
system("shutdown ...") 简单粗暴,依赖命令
InitiateSystemShutdownEx 更高级,服务器常用

教学和开发中最推荐:👉 ExitWindowsEx


二、必须解决的问题:权限(非常关键)

如果你直接调用关机 API,大概率会失败,原因是:

❌ 当前进程没有 “关机权限”

所以第一步必须做:

启用关机权限(SE_SHUTDOWN_NAME)

流程是:

  1. 打开当前进程的访问令牌

  2. 查找关机权限的 LUID

  3. 调整进程权限


三、核心 API 介绍

1️⃣ AdjustTokenPrivileges(开启权限)


AdjustTokenPrivileges

用于临时提升当前进程的系统权限。


2️⃣ ExitWindowsEx(执行操作)


BOOL ExitWindowsEx( UINT uFlags, DWORD dwReason );

常用 uFlags 参数:

功能 参数
注销 EWX_LOGOFF
关机 EWX_SHUTDOWN
重启 EWX_REBOOT
强制 EWX_FORCE / EWX_FORCEIFHUNG

四、三种功能的实现方式(核心逻辑)

✔ 注销


ExitWindowsEx(EWX_LOGOFF, 0);

✔ 关机


ExitWindowsEx(EWX_SHUTDOWN, 0);

✔ 重启


ExitWindowsEx(EWX_REBOOT, 0);

注意
如果不加 EWX_FORCE,系统会尝试正常关闭程序(更安全)


五、完整 C++ 示例源码

/*************************************************
 * 文件名:system_power.cpp
 * 功能:Windows 关机 / 重启 / 注销
 *************************************************/

#include <windows.h>
#include <iostream>

#pragma comment(lib, "advapi32.lib")

/* 启用关机权限 */
bool EnableShutdownPrivilege()
{
    HANDLE hToken;
    TOKEN_PRIVILEGES tkp;

    // 打开当前进程的访问令牌
    if (!OpenProcessToken(GetCurrentProcess(),
        TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
    {
        return false;
    }

    // 获取关机权限的 LUID
    LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid);

    tkp.PrivilegeCount = 1;
    tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

    // 调整权限
    AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, NULL, 0);

    CloseHandle(hToken);
    return GetLastError() == ERROR_SUCCESS;
}

int main()
{
    int choice;

    std::cout << "============================\n";
    std::cout << "1. 注销\n";
    std::cout << "2. 关机\n";
    std::cout << "3. 重启\n";
    std::cout << "请选择:";
    std::cin >> choice;

    if (!EnableShutdownPrivilege())
    {
        std::cout << "权限获取失败!\n";
        return 0;
    }

    switch (choice)
    {
    case 1:
        ExitWindowsEx(EWX_LOGOFF, 0);
        break;
    case 2:
        ExitWindowsEx(EWX_SHUTDOWN, 0);
        break;
    case 3:
        ExitWindowsEx(EWX_REBOOT, 0);
        break;
    default:
        std::cout << "无效选择\n";
        break;
    }

    return 0;
}

七、常见问题与解决办法

Q1:程序运行了但没反应?

✔ 原因:

  • 没有启用 SE_SHUTDOWN_NAME 权限

✔ 解决:

  • 必须调用 AdjustTokenPrivileges


Q2:为什么注销不需要管理员权限?

✔ 因为:

  • 注销当前用户不涉及系统级关闭


Q3:如何强制关闭所有程序?


ExitWindowsEx(EWX_SHUTDOWN | EWX_FORCE, 0);

慎用,可能丢失数据


Q4:Windows 11 可用吗?

✔ 完全可用
✔ 官方 API,长期稳定


八、可扩展方向(很适合课程设计)

  1. 定时关机 / 重启(Sleep + ExitWindowsEx)

  2. GUI 版(Win32 / MFC / Qt)

  3. 托盘程序

  4. 远程控制(Socket + 关机)

  5. 权限检测与失败提示


九、总结一句话

Windows 下的关机、重启、注销,本质就是:
👉 开启关机权限 + 调用 ExitWindowsEx

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐