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

在此示例中,展开变量 $Splat 是在本地计算机上设置的哈希表。 Invoke-Command连接到远程计算机会话。 ScriptBlockUsing 作用域修饰符与位于 () 符号一起使用, @ 以表示 splatted 变量。

$Splat = @{ Name = "Win*"; Include = "WinRM" }
Invoke-Command -Session $s -ScriptBlock { Get-Service @Using:Splat }

需要 "Using" 作用域修饰符的其他情况

对于任何执行进程外的脚本或命令,都需要 Using 范围修饰符来嵌入调用会话范围内的变量值,以便使会话代码不能访问它们。 Using以下上下文支持作用域修饰符:

  • 远程执行的命令,已开始 Invoke-Command 使用 ComputerNameHostNameSSHConnectionSession 参数 (远程会话)
  • 后台作业, Start-Job (进程外会话开始)
  • 通过 Start-ThreadJobForEach-Object -Parallel (单独的线程会话启动的线程作业)

根据上下文,嵌入变量值是调用方的作用域中的数据的独立副本或对其的引用。 在远程和进程外会话中,它们始终是独立的副本。 在线程会话中,它们是通过引用传递的。

变量值的序列化

远程执行的命令和后台作业在进程外运行。 进程外会话使用基于 XML 的序列化和反序列化来使变量的值可在进程边界内使用。 序列化进程将对象转换为包含原始对象属性但不包含其方法的 PSObject

对于有限的一组类型,反序列化将对象重新Hydrate back to original 类型。 rehydrated 对象是原始对象实例的副本。 它具有类型属性和方法。 对于简单类型(如 System.Version), 副本是确切的。 对于复杂类型,副本是不完整的。 例如,重新冻结的证书对象不包括私钥。

所有其他类型的实例都是 PSObject 实例。 PSTypeNames 属性包含以反初始化 为前缀的原始类型名称,例如,Deserialized.Sys tem。Data.DataTable

将局部变量与 ArgumentList 参数 一同使用

可以通过为远程命令定义参数并使用 cmdlet 的 ArgumentList 参数将局部变量指定为参数值,在远程命令中 Invoke-Command 使用局部变量。

  • 使用 param 关键字定义远程命令的参数。 参数名称是不需要与局部变量名称匹配的占位符。

  • 使用 命令中的 关键字 param 定义的参数。

  • 使用 cmdlet 的 ArgumentList Invoke-Command 参数将局部变量指定为参数值。

例如,以下命令在本地会话中定义变量,然后在远程 $ps 命令中使用它。 该命令使用 $log 作为参数名称,将局部变量 用作 $ps 其值。

$ps = "*PowerShell*"
Invoke-Command -ComputerName S1 -ScriptBlock {
  param($log)
  Get-WinEvent -LogName $log
} -ArgumentList $ps

另请参阅

about_PSSessions

about_Remote

about_Scopes

about_Splatting

about_Variables

Enter-PSSession

Invoke-Command

New-PSSession

Start-ThreadJob

ForEach-Object