使用System.Management.Automation远程重启计算机的正确方法咨询
System.Management.Automation 远程重启设备实现规范
包引用规范
最新版本的System.Management.Automation属于PowerShell 7+ SDK的一部分,不要单独安装零散的System.Management.Automation NuGet包,正确的依赖安装方式是直接引用Microsoft.PowerShell.SDK包,避免依赖冲突导致的Runspace异常。
前置环境要求
目标设备需要提前完成WinRM配置:
- 开启WinRM服务
- 放通防火墙5985(HTTP)/5986(HTTPS)端口
- 配置对应账号的远程PowerShell访问权限
Runspace生命周期管理规范
Runspace损坏属于预期正常行为:远程重启命令会直接销毁目标设备上的PowerShell会话,关联的本地Runspace会因为连接断开进入损坏状态,遵循以下规则即可避免问题:
- 重启操作和后续存活检测完全分离Runspace实例,不要复用同一个Runspace
- 所有Runspace、PowerShell实例都放入
using代码块,操作完成后自动释放资源,不要手动管理生命周期 - 不要尝试重新打开已经触发过重启命令的Runspace,直接销毁重建即可
完整实现示例
using System.Management.Automation; using System.Management.Automation.Runspaces; using System.Security; // 替换为实际的目标配置 string targetHost = "192.168.1.100"; string userName = "administrator"; string password = "你的密码"; // 构造凭据(不需要凭据可跳过此步) SecureString securePwd = new SecureString(); foreach (char c in password) securePwd.AppendChar(c); PSCredential credential = new PSCredential(userName, securePwd); // 构造远程连接信息 WSManConnectionInfo connInfo = new WSManConnectionInfo(new Uri($"http://{targetHost}:5985/wsman")); connInfo.Credential = credential; connInfo.OperationTimeout = 10 * 1000; // 单次操作超时10秒 // ========== 第一步:单独用独立Runspace执行重启命令 ========== using (Runspace restartRunspace = RunspaceFactory.CreateRunspace(connInfo)) { restartRunspace.Open(); using (PowerShell ps = PowerShell.Create()) { ps.Runspace = restartRunspace; ps.AddCommand("Restart-Computer") .AddParameter("Force", true) // 强制重启,跳过程序阻止 .AddParameter("Timeout", 5); // 给系统5秒触发重启,不需要等完全关机 ps.Invoke(); } } // 此处重启用的Runspace会自动释放,完全不需要保留 // ========== 第二步:轮询检测设备是否恢复 ========== bool deviceOnline = false; int maxRetryCount = 20; // 最多重试20次,合计5分钟超时,可自行调整 int retryCount = 0; while (!deviceOnline && retryCount < maxRetryCount) { retryCount++; Thread.Sleep(15000); // 每次检测间隔15秒,可自行调整 try { // 每次检测都新建独立的Runspace using Runspace detectRunspace = RunspaceFactory.CreateRunspace(connInfo); detectRunspace.Open(); using PowerShell detectPs = PowerShell.Create(); detectPs.Runspace = detectRunspace; detectPs.AddScript("Get-ComputerInfo | Select-Object -ExpandProperty OsName"); var result = detectPs.Invoke(); // 调用成功且返回值正常即判定设备恢复 if (result.Count > 0 && !result.Any(item => item == null)) { deviceOnline = true; } } catch (PSRemotingTransportException) { // 传输异常说明设备还未启动完成,继续轮询即可 continue; } }
常见异常规避
- 不要给
Restart-Computer加-Wait参数等待重启完成,该参数的底层实现逻辑不稳定,容易触发Runspace死锁 - 不要在同一个PowerShell实例里同时加入重启命令和检测命令,远程会话断开会直接导致整个实例进入损坏状态
- 如果目标设备是工作组环境而非域环境,需要在本地WinRM配置中把目标IP加入信任列表
内容的提问来源于stack exchange,提问作者user3120136
相关产品推荐
相关产品推荐

