You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将变量值传递给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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 07:42:11