如何将变量值传递给Invoke-Command并实现特定状态虚拟机筛选
解决PowerShell远程脚本块传递变量的问题
嘿,我明白你现在的困扰:在global:Resource-Summary函数里用Invoke-Command远程执行脚本时,没法把外部的变量(比如你要筛选的VM状态,还有函数必填的$ProgramName)传到远程脚本块里对吧?别着急,下面给你几种靠谱的解决方法,都是实际工作里常用的:
方法1:用$Using:作用域(PowerShell 3.0+首选)
这是最省心的方式,PowerShell 3.0及以上版本都支持。你只需要在远程脚本块里引用外部变量时,加上$Using:前缀就行。比如我帮你加了个$VMStatus参数用来指定要筛选的状态(Saved、Running、Stopped),修改后的代码如下:
Function global:Resource-Summary { Param( [parameter(Mandatory=$true)] $ProgramName, [parameter(Mandatory=$true)] $ServerName, # 新增状态参数,限定可选值避免输入错误 [parameter(Mandatory=$true)] [ValidateSet("Saved", "Running", "Stopped")] $VMStatus ) PROCESS { Foreach ($Server in $ServerName) { Invoke-Command -ComputerName $Server -ScriptBlock { # 用$Using:直接引用外部的$VMStatus和$ProgramName $VMs = Get-VM | Where-Object { $_.State -eq $Using:VMStatus } $colVMs = @() foreach ($VM in $VMs) { # 用[PSCustomObject]创建自定义对象比New-Object更简洁 $objVM = [PSCustomObject]@{ VMName = $VM.Name VMState = $VM.State ProgramName = $Using:ProgramName } $colVMs += $objVM } $colVMs } } } }
方法2:用-ArgumentList参数(兼容旧版本)
如果你的环境还在用PowerShell 2.0,那可以用Invoke-Command的-ArgumentList参数来传递变量,有两种写法:
写法A:用$args数组接收
这种写法简单直接,变量会按顺序放到$args数组里,远程脚本块里按索引取就行:
Function global:Resource-Summary { Param( [parameter(Mandatory=$true)] $ProgramName, [parameter(Mandatory=$true)] $ServerName, [parameter(Mandatory=$true)] [ValidateSet("Saved", "Running", "Stopped")] $VMStatus ) PROCESS { Foreach ($Server in $ServerName) { Invoke-Command -ComputerName $Server -ScriptBlock { # $args[0]对应传递的第一个变量$VMStatus,$args[1]对应$ProgramName $VMs = Get-VM | Where-Object { $_.State -eq $args[0] } $colVMs = @() foreach ($VM in $VMs) { $objVM = [PSCustomObject]@{ VMName = $VM.Name VMState = $VM.State ProgramName = $args[1] } $colVMs += $objVM } $colVMs } -ArgumentList $VMStatus, $ProgramName # 按顺序传递变量 } } }
写法B:参数化脚本块(可读性更好)
给远程脚本块定义明确的参数,这样代码更清晰,不容易搞混变量顺序:
Function global:Resource-Summary { Param( [parameter(Mandatory=$true)] $ProgramName, [parameter(Mandatory=$true)] $ServerName, [parameter(Mandatory=$true)] [ValidateSet("Saved", "Running", "Stopped")] $VMStatus ) PROCESS { Foreach ($Server in $ServerName) { Invoke-Command -ComputerName $Server -ScriptBlock { # 给脚本块定义参数 param( [string]$TargetVMStatus, [string]$TargetProgramName ) $VMs = Get-VM | Where-Object { $_.State -eq $TargetVMStatus } $colVMs = @() foreach ($VM in $VMs) { $objVM = [PSCustomObject]@{ VMName = $VM.Name VMState = $VM.State ProgramName = $TargetProgramName } $colVMs += $objVM } $colVMs } -ArgumentList $VMStatus, $ProgramName # 对应脚本块的参数顺序传递 } } }
小提示
- 如果你不需要单独的
$VMStatus参数,而是直接在函数里固定筛选某几种状态,也可以用同样的方法传递其他需要的变量; - 记得确认远程服务器的PowerShell版本:
$Using:是3.0及以上才支持的,旧版本就用-ArgumentList; - 用
[PSCustomObject]创建自定义对象比New-Object写法更简洁,还能自动处理属性,推荐用这个。
内容的提问来源于stack exchange,提问作者Vinay
相关产品推荐
相关产品推荐

