about_Remote_Variables
简短说明
说明如何在远程命令中使用本地和远程变量。
长说明
可以在远程计算机上运行的命令中使用变量。 为变量赋值,然后使用变量代替该值。
默认情况下,假定远程命令中的变量是在运行命令的会话中定义的。 在本地会话中定义的变量必须在 命令中标识为局部变量。
使用远程变量
PowerShell 假定远程命令中使用的变量是在运行命令的会话中定义的。
在此示例中,变量 $ps
是在运行命令的临时会话中 Get-WinEvent
定义的。
Invoke-Command -ComputerName S1 -ScriptBlock {
$ps = "*PowerShell*"; Get-WinEvent -LogName $ps
}
当命令在持久会话 PSSession 中运行时,必须在该会话中定义远程变量。
$s = New-PSSession -ComputerName S1
Invoke-Command -Session $s -ScriptBlock {$ps = "*PowerShell*"}
Invoke-Command -Session $s -ScriptBlock {Get-WinEvent -LogName $ps}
使用局部变量
可以在远程命令中使用局部变量,但必须在本地会话中定义该变量。
从 PowerShell 3.0 开始,可以使用 Using
范围修饰符在远程命令中标识局部变量。
的 Using
语法如下所示:
$Using:<VariableName>
在以下示例中, $ps
变量在本地会话中创建,但在运行命令的会话中使用。 范围 Using
修饰符标识 $ps
为局部变量。
$ps = "*PowerShell*"
Invoke-Command -ComputerName S1 -ScriptBlock {
Get-WinEvent -LogName $Using:ps
}
范围 Using
修饰符可以在 PSSession 中使用。
$s = New-PSSession -ComputerName S1
$ps = "*PowerShell*"
Invoke-Command -Session $s -ScriptBlock {Get-WinEvent -LogName $Using:ps}
变量引用(如 ) $using:var
从调用方上下文扩展到变量 $var
的值。 无法访问调用方变量对象。
范围 Using
修饰符不能用于修改 PSSession 中的局部变量。 例如,以下代码不起作用:
$s = New-PSSession -ComputerName S1
$ps = "*PowerShell*"
Invoke-Command -Session $s -ScriptBlock {$Using:ps = 'Cannot assign new value'}
有关 的详细信息 Using
,请参阅 about_Scopes
使用展开
PowerShell 展开将参数名称和值的集合传递给命令。 有关详细信息,请参阅 about_Splatting。
在此示例中,splatting 变量 $Splat
是在本地计算机上设置的哈希表。 连接到 Invoke-Command
远程计算机会话。 ScriptBlock 使用Using
带有 At (@
) 符号的范围修饰符来表示已展开的变量。
$Splat = @{ Name = "Win*"; Include = "WinRM" }
Invoke-Command -Session $s -ScriptBlock { Get-Service @Using:Splat }
需要“Using”范围修饰符的其他情况
对于在会话外执行的任何脚本或命令,需要 Using
作用域修饰符来嵌入调用会话范围内的变量值,以便会话外代码可以访问它们。 以下 Using
上下文支持范围修饰符:
- 远程执行的命令,以
Invoke-Command
使用 ComputerName、 HostName、 SSHConnection 或 Session 参数 (远程会话) - 后台作业,从
Start-Job
(进程外会话) - 线程作业,通过
Start-ThreadJob
或ForEach-Object -Parallel
(单独的线程会话) 启动
根据上下文,嵌入的变量值可以是调用方范围内数据的独立副本或对其的引用。 在远程会话和进程外会话中,它们始终是独立的副本。 在线程会话中,它们通过引用传递。
变量值的序列化
远程执行的命令和后台作业在进程外运行。 进程外会话使用基于 XML 的序列化和反序列化使变量的值跨进程边界可用。 序列化过程将对象转换为包含原始对象属性但不包含其方法的 PSObject 。
对于一组有限的类型,反序列化会将对象解除冻结回原始类型。 解除冻结的对象是原始对象实例的副本。 它具有类型属性和方法。 对于简单类型(如 System.Version),复制是精确的。 对于复杂类型,副本不完善。 例如,解除冻结的证书对象不包括私钥。
所有其他类型的实例都是 PSObject 实例。 PSTypeNames 属性包含以反序列化为前缀的原始类型名称,例如 Deserialized.System.Data.DataTable
将局部变量与 ArgumentList 参数配合使用
可以通过定义远程命令的参数并使用 cmdlet 的 Invoke-Command
ArgumentList 参数将局部变量指定为参数值,在远程命令中使用局部变量。
使用
param
关键字 (keyword) 定义远程命令的参数。 参数名称是不需要与局部变量名称匹配的占位符。在 命令中使用
param
由关键字 (keyword) 定义的参数。使用 cmdlet 的
Invoke-Command
ArgumentList 参数将局部变量指定为参数值。
例如,以下命令在本地会话中定义 变量, $ps
然后在远程命令中使用它。 该命令使用 $log
作为参数名称, $ps
使用局部变量 作为其值。
$ps = "*PowerShell*"
Invoke-Command -ComputerName S1 -ScriptBlock {
param($log)
Get-WinEvent -LogName $log
} -ArgumentList $ps