必须使用 shutdown 命令关机/重启,推荐 process.start 配合 useshellexecute=false、createnowindow=true 和错误重定向;需检查 exitcode 判定成败,权限不足时不会抛异常。

关机/重启必须用 Shutdown 命令,Process.Start("shutdown") 是最可靠方式
Windows 系统级关机或重启不能靠 .NET 的 Environment.Exit 或 Application.Exit —— 那只是退出当前程序。真正生效的只有调用系统 shutdown 命令。直接拼接参数比用 WMI 或 P/Invoke 更稳定、权限要求更低、兼容 Win7 到 Win11。
-
shutdown /s /t 0立即关机(/s 表示 shutdown,/t 0 表示延迟 0 秒) -
shutdown /r /t 0立即重启(/r 表示 restart) - 加
/f强制关闭正在运行的应用(如弹窗未响应时必需):shutdown /s /f /t 0 - 避免用
/l(注销),它不等于关机,且在服务上下文中可能失败
执行 CMD 命令要用 ProcessStartInfo 配置,否则容易静默失败
直接 Process.Start("shutdown", "/s /t 0") 在某些环境(如无桌面会话的服务、UAC 提权后)会卡住或没反应。根本原因是没显式指定 UseShellExecute = false 和 CreateNoWindow = true,导致命令在隐藏 shell 中无法正确继承权限或输出流。
- 必须设
UseShellExecute = false,否则参数会被忽略或解析错 - 推荐设
CreateNoWindow = true,避免闪黑窗;若需调试可临时设为false观察报错 - 加
RedirectStandardError = true并读取StandardError,能捕获如“拒绝访问”“参数错误”等真实原因 - 示例关键片段:
var startInfo = new ProcessStartInfo("shutdown", "/s /f /t 0") { UseShellExecute = false, CreateNoWindow = true, RedirectStandardError = true }; using var proc = Process.Start(startInfo); string error = proc.StandardError.ReadToEnd(); proc.WaitForExit();
权限不足时会直接失败,没有异常抛出——必须检查退出码和错误输出
shutdown 是受保护操作,普通用户默认只能对自己会话执行注销,关机/重启需要“关机系统”权限。这权限通常只对管理员组或明确赋权的账户开放。而 .NET 的 Process.Start 即使失败也常返回非空 Process 对象,且不抛异常,极易误判成功。
- 务必检查
proc.ExitCode:0 表示成功;非 0(如 1190=权限不足,5=拒绝访问)才是真实失败信号 - 不要只依赖
try/catch,shutdown出错不会触发 .NET 异常,而是写入 stderr 或设退出码 - 如果应用以标准用户运行,又必须支持关机,得提前用 manifest 声明
requireAdministrator,否则弹 UAC 后仍可能因策略被拒 - 域环境下还可能被组策略禁用 shutdown 命令,此时错误输出里会出现类似“指令被系统策略阻止”的提示
别用 PowerShell 替代 shutdown,除非你明确需要远程或条件判断
有人想用 PowerShell -Command "Stop-Computer",看起来更“.NET 原生”,但实际更重、启动慢、权限模型更复杂,且默认不允许远程执行(需额外配置 WS-Management)。对本地立即关机/重启这种简单场景,纯属增加不可靠性。
-
Stop-Computer在无交互会话(如 Windows 服务)中大概率报错Cannot validate argument on parameter 'ComputerName' - PowerShell 进程本身可能被杀毒软件拦截,尤其当命令含
-Force或-Restart - 如果真要跨机器或加条件(比如“仅当 CPU >90% 持续 5 分钟才关机”),那另说;但单机即时操作,请坚持用
shutdown.exe - 路径不用写全:
shutdown在 System32 下,PATH 默认包含,无需写C:\Windows\System32\shutdown.exe











