在遠端計算機上執行命令

啟用 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
}