版本信息最后核对:2026-10-25
需要在多台 Windows 主机上批量查询状态、收集日志、启停服务或做配置变更时使用。典型场景是域内巡检、把本地脚本推到远程执行、在跳板机上复用会话做多步操作。只操作本机时不需要 remoting,直接本地执行更简单,也少一层认证和序列化。
不适合的场景:目标机只开放 SSH 且没有 WinRM;需要跨不可信网络直接暴露 WinRM;工作组环境既没有域信任也没有证书。此时优先用 PowerShell 7.x 的 SSH 远程、堡垒机或配置管理工具,不要把 5985 端口直接开到公网。
Enable-PSRemoting 会启动 WinRM 服务、注册监听器并放行防火墙规则,需要管理员权限。Enter-PSSession 是一对一交互;Invoke-Command -ComputerName 是一对多执行。New-PSSession 建立可复用会话,适合多步操作、复制文件和断线重连。-ComputerName 仍走 WinRM,-HostName 配合 -SSHTransport 走 SSH;Linux 上的 PowerShell 只能作为 SSH 端点。Invoke-Command、New-PSSession 增加了 SSH 参数;跨平台脚本不要假设远端一定是 Windows,也不要假设 5.1 与 7.x 的默认端点配置相同。# 1. 在目标机启用 WinRM(管理员)。会改服务、监听器和防火墙规则
PS C:\> Enable-PSRemoting -Force
PS C:\> Test-WSMan -ComputerName SRV01
# 2. 单机执行;凭据交互输入,不要写进脚本
PS C:\> Invoke-Command -ComputerName SRV01 -Credential (Get-Credential) -ScriptBlock { Get-Service Spooler }
# 3. 批量执行,主机列表来自文件,限制并发
PS C:\> $hosts = Get-Content .\hosts.txt
PS C:\> Invoke-Command -ComputerName $hosts -ThrottleLimit 16 -ScriptBlock { Get-CimInstance Win32_OperatingSystem | Select-Object PSComputerName, LastBootUpTime }
# 4. 建立可复用会话,进入交互后再退出,会话仍保留
PS C:\> $s = New-PSSession -ComputerName SRV01
PS C:\> Enter-PSSession -Session $s
PS C:\> Exit-PSSession
# 5. 在复用会话里传本地变量,必须用 $using:
PS C:\> $svc = 'Spooler'
PS C:\> Invoke-Command -Session $s -ScriptBlock { Get-Service -Name $using:svc }
# 6. 通过会话复制文件,不必另外开放 SMB 共享
PS C:\> Copy-Item .\deploy.ps1 -Destination C:\Temp\deploy.ps1 -ToSession $s
# 7. PowerShell 7.x 用 SSH 连 Linux 或 Windows,不依赖 WinRM
PS C:\> Invoke-Command -HostName linux01 -UserName ops -SSHTransport -ScriptBlock { uname -a }
# 8. 断开后远程会话和作业可保留,稍后重连
PS C:\> Disconnect-PSSession -Session $s
PS C:\> Connect-PSSession -Session $s
Test-WSMan 失败时,先查 WinRM 服务、防火墙和 5985 端口,再看目标机是否执行过 Enable-PSRemoting;不要直接怀疑脚本。Access is denied 常见于账号不在 Remote Management Users、工作组 UAC 远程限制,或跨域没有信任。先确认用的是域账号还是本地账号,再查端点权限。-ComputerName 和 -HostName 不是同一条路径:前者走 WinRM,后者走 SSH。只开了 SSH 的机器上写 -ComputerName 会失败。Deserialized.System.ServiceProcess.ServiceController 却调用 .Stop() 失败,应在远程 ScriptBlock 里完成操作。$using: 只用于直接传给远程或并行 ScriptBlock 的变量;复杂对象会被序列化,修改不会回传,结果要用输出接收。Remove-PSSession、Remove-Job 清理,断线会话也要确认是否还需要。Invoke-Command -AsJob 的作业管理合上页面,先回答,再展开对照。
-ComputerName 还是 -HostName?5.1 能做吗?Invoke-Command 返回的对象为什么调用不了原来的方法?-HostName 配合 -SSHTransport;5.1 没有 SSH 传输,只能走 WinRM 或改用 ssh 命令和远程 shell。Deserialized. 前缀的对象,只保留属性和部分类型信息,方法不会传输;操作要在远程 ScriptBlock 内完成。
小程序版
微信扫码,随时查命令