C#控制Windows关机、重启与注销的两种实现方案

纸上星河
纸上星河
发布时间:2026-10-14| 6人浏览过
原创

在C#开发中,有时需要程序具备对操作系统进行基础管理的能力,如远程关机、定时重启或用户注销。本文将详细讲解两种主流实现方法:一是直接调用系统自带的 shutdown.exe 命令行工具,二是通过 P/Invoke 技术调用 Windows Win32 API 进行底层控制。前者简单易用但伴随界面交互,后者更隐蔽且可控性更强,适合无人值守或后台服务场景。

结果或目标

实现以下系统操作:

  • 关闭计算机:切断电源(软关)。
  • 重启计算机:终止所有进程并重新启动。
  • 注销当前用户:结束当前会话并返回登录界面。
  • 强制操作:无需等待应用程序响应,直接执行。

准备条件

  1. 运行环境为 Windows 操作系统(支持 Win32 API)。
  2. 项目需引用 System.Diagnostics 命名空间(用于方法一)。
  3. 若使用方法二,需确保运行程序具有管理员权限,否则可能因缺少 SeShutdownPrivilege 权限而调用失败。
  4. 了解基本的 C# 语法及结构体定义规则。

真实操作顺序

第1步:使用 System.Diagnostics.Process 调用 shutdown.exe

目的:快速实现简单的关机或重启功能,适用于不需要隐藏界面的场景。

入口:C# 代码中的任意可执行位置。

动作:启动 Process 实例,指定进程文件名为 "shutdown.exe",并在参数中传入相应的命令标志。

重要参数说明

  • -r:重启计算机。
  • -s:关闭计算机。
  • -l:注销当前用户。
  • -f:强制关闭正在运行的应用程序,不显示警告。
  • -t xx:设置倒计时秒数,例如 -t 0 为立即执行。
  • -a:中止关机过程(通常需在倒计时内调用)。

示例代码

using System.Diagnostics;

// 示例:15秒后强制重启电脑
Process.Start("shutdown.exe", "-r -f -t 15");

// 示例:立即注销
Process.Start("shutdown.exe", "-l");

注意:此方法会触发 Windows 标准的关机对话框或进度条窗口。若需完全静默执行,建议使用方法二。

第2步:通过 P/Invoke 调用 Win32 API 实现静默控制

目的:在不弹出系统默认界面、无倒计时的情况下,以编程方式精准控制系统状态。这是企业级后台服务或远程管理工具的常用做法。

原理:Windows 系统通过 ExitWindowsEx 函数处理注销、关机等操作,但调用该函数前必须获取当前进程的 SeShutdownPrivilege(关机特权)。我们需要通过 OpenProcessToken、LookupPrivilegeValue 和 AdjustTokenPrivileges 一系列 API 调用来申请该权限。

核心组件定义

首先定义所需的常量、枚举、结构体以及外部函数声明:

using System.Runtime.InteropServices;

public class SystemControl
{
    // 权限相关常量
    private const int SE_PRIVILEGE_ENABLED = 0x00000002;
    private const int TOKEN_QUERY = 0x00000008;
    private const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;
    private const string SE_SHUTDOWN_NAME = "SeShutdownPrivilege";

    // 退出操作类型枚举
    [Flags]
    public enum ExitWindows : uint
    {
        LogOff = 0x00,   // 注销
        ShutDown = 0x01, // 关机
        Reboot = 0x02,   // 重启
        Force = 0x04,    // 强制
        PowerOff = 0x08, // 断电(部分系统支持)
        ForceIfHung = 0x10 // 强制(即使无响应)
    }

    // 关机原因枚举 (可选)
    [Flags]
    private enum ShutdownReason : uint
    {
        MajorApplication = 0x00040000,
        MajorOperatingSystem = 0x00020000,
        MajorOther = 0x00000000,
        MinorMaintenance = 0x00000001,
        MinorUnstable = 0x00000006,
        FlagUserDefined = 0x40000000,
        FlagPlanned = 0x80000000
    }

    // 权限结构体
    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    private struct TokPriv1Luid
    {
        public int Count;
        public long Luid;
        public int Attr;
    }

    // DLL 导入
    [DllImport("kernel32.dll", ExactSpelling = true)]
    private static extern IntPtr GetCurrentProcess();

    [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
    private static extern bool OpenProcessToken(IntPtr h, int acc, ref IntPtr phtok);

    [DllImport("advapi32.dll", SetLastError = true)]
    private static extern bool LookupPrivilegeValue(string host, string name, ref long pluid);

    [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
    private static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall, ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen);

    [DllImport("user32.dll")]
    private static extern bool ExitWindowsEx(ExitWindows uFlags, ShutdownReason dwReason);

    /// <summary>
    /// 执行关机、重启或注销操作
    /// </summary>
    /// <param name="flag">操作类型 (ExitWindows枚举)</param>
    public static void DoExitWindows(ExitWindows flag)
    {
        TokPriv1Luid tp;
        IntPtr hproc = GetCurrentProcess();
        IntPtr htok = IntPtr.Zero;

        // 1. 打开当前进程令牌
        OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok);

        // 2. 填充权限结构
        tp.Count = 1;
        tp.Luid = 0;
        tp.Attr = SE_PRIVILEGE_ENABLED;

        // 3. 获取关机特权句柄值
        LookupPrivilegeValue(null, SE_SHUTDOWN_NAME, ref tp.Luid);

        // 4. 调整进程令牌权限
        AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero);

        // 5. 执行最终操作
        if (!ExitWindowsEx(flag, ShutdownReason.MajorOther))
        {
            throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
        }
    }
}

调用示例

// 强制关机
SystemControl.DoExitWindows(SystemControl.ExitWindows.ShutDown | SystemControl.ExitWindows.Force);

// 强制重启
SystemControl.DoExitWindows(SystemControl.ExitWindows.Reboot | SystemControl.ExitWindows.Force);

// 注销当前用户
SystemControl.DoExitWindows(SystemControl.ExitWindows.LogOff);

完成判断

  • 观察目标机器是否按预期进入关机、重启或登录界面。
  • 检查程序中是否有抛出 Win32Exception,若有,通常是因为权限不足(需以管理员身份运行程序)。

排错指南

  1. 操作无效或无反应:最常见的原因是缺乏管理员权限。Windows 安全策略要求拥有 SeShutdownPrivilege 的进程才能执行关机操作。请确保你的 C# 程序是在“以管理员身份运行”的上下文中启动的,或者在代码中增加请求 UAC 提权的清单配置。
  2. 返回值错误:ExitWindowsEx 返回 false 时,可通过 Marshal.GetLastWin32Error() 获取错误码。常见错误包括拒绝访问(5)或未找到设备。
  3. 应用未强制关闭:在 ExitWindows 枚举中务必加上 Force 标志,否则系统会尝试等待前台应用程序保存数据,可能导致长时间挂起。

简要总结

C# 控制系统开关机主要依赖两条路径:简单快捷的命令行调用适合前端展示或临时脚本;基于 Win32 API 的 P/Invoke 调用则提供了更底层、更静默的控制能力,是构建管理系统的首选方案。无论采用哪种方法,务必注意权限管理和强制标志的使用,以避免流程中断或用户体验不佳。以上就是C#调用API或命令行控制Windows关机、重启和注销的详细内容,更多关于Windows系统自动化管理的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。