在远程计算机上运行命令

启用 Powershell 远程处理后(Enable-PSRemoting)你可以在远程计算机上运行命令,如下所示:

Invoke-Command -ComputerName "RemoteComputerName" -ScriptBlock {
    Write host "Remote Computer Name: $ENV:ComputerName"
}

上面的方法创建一个临时会话,并在命令或脚本块结束后立即关闭它。

要使会话保持打开状态并在以后运行其他命令,你需要先创建一个远程会话:

$Session = New-PSSession -ComputerName "RemoteComputerName"

然后,每次在远程计算机上调用命令时都可以使用此会话:

Invoke-Command -Session $Session -ScriptBlock {
    Write host "Remote Computer Name: $ENV:ComputerName"
}

Invoke-Command -Session $Session -ScriptBlock {
    Get-Date
}

如果你需要使用不同的凭据,可以使用 -Credential 参数添加它们:

$Cred = Get-Credential
Invoke-Command -Session $Session -Credential $Cred -ScriptBlock {...}

远程序列化警告

注意:

重要的是要知道远程处理序列化远程系统上的 PowerShell 对象并在远程处理会话结束时对它们进行反序列化,即它们在传输过程中转换为 XML 并丢失所有方法。

$output = Invoke-Command -Session $Session -ScriptBlock {
    Get-WmiObject -Class win32_printer
}

$output | Get-Member -MemberType Method

  TypeName: Deserialized.System.Management.ManagementObject#root\cimv2\Win32_Printer

Name     MemberType Definition
----     ---------- ----------
GetType  Method     type GetType()
ToString Method     string ToString(), string ToString(string format, System.IFormatProvi...

而你在常规 PS 对象上有方法:

Get-WmiObject -Class win32_printer | Get-Member -MemberType Method

 TypeName: System.Management.ManagementObject#root\cimv2\Win32_Printer

Name                  MemberType Definition                                                                                                                          
----                  ---------- ----------                                                                                                                          
CancelAllJobs         Method     System.Management.ManagementBaseObject CancelAllJobs()                                                                              
GetSecurityDescriptor Method     System.Management.ManagementBaseObject GetSecurityDescriptor()                                                                      
Pause                 Method     System.Management.ManagementBaseObject Pause()                                                                                      
PrintTestPage         Method     System.Management.ManagementBaseObject PrintTestPage()                                                                              
RenamePrinter         Method     System.Management.ManagementBaseObject RenamePrinter(System.String NewPrinterName)                                                  
Reset                 Method     System.Management.ManagementBaseObject Reset()                                                                                      
Resume                Method     System.Management.ManagementBaseObject Resume()                                                                                     
SetDefaultPrinter     Method     System.Management.ManagementBaseObject SetDefaultPrinter()                                                                          
SetPowerState         Method     System.Management.ManagementBaseObject SetPowerState(System.UInt16 PowerState, System.String Time)                                  
SetSecurityDescriptor Method     System.Management.ManagementBaseObject SetSecurityDescriptor(System.Management.ManagementObject#Win32_SecurityDescriptor Descriptor)

参数用法

要使用参数作为远程脚本块的参数,可以使用 Invoke-CommandArgumentList 参数,或使用 $Using:语法。

使用带有未命名参数的 ArgumentList(即按照它们传递给 scriptblock 的顺序):

$servicesToShow = "service1"
$fileName = "C:\temp\servicestatus.csv"
Invoke-Command -Session $session -ArgumentList $servicesToShow,$fileName -ScriptBlock {
    Write-Host "Calling script block remotely with $($Args.Count)"
    Get-Service -Name $args[0]
    Remove-Item -Path $args[1] -ErrorAction SilentlyContinue -Force
}

ArgumentList 与命名参数一起使用:

$servicesToShow = "service1"
$fileName = "C:\temp\servicestatus.csv"
Invoke-Command -Session $session -ArgumentList $servicesToShow,$fileName -ScriptBlock {
    Param($serviceToShowInRemoteSession,$fileToDelete)

    Write-Host "Calling script block remotely with $($Args.Count)"
    Get-Service -Name $serviceToShowInRemoteSession
    Remove-Item -Path $fileToDelete -ErrorAction SilentlyContinue -Force
}

使用 $Using:语法:

$servicesToShow = "service1"
$fileName = "C:\temp\servicestatus.csv"
Invoke-Command -Session $session -ScriptBlock {
    Get-Service $Using:servicesToShow
    Remove-Item -Path $fileName -ErrorAction SilentlyContinue -Force
}