如何将变量值传递给 Invoke-Command

How to pass variable value to Invoke-Command

我正在尝试获取处于特定状态(已保存、运行、已停止)的机器列表。我将机器的状态作为参数传递给函数。

Function global:Resource-Summary
{
    Param(
    [parameter(mandatory=$true)] $ProgramName,
    [parameter(mandatory=$true)] $ServerName
    )

    PROCESS
    {

    Foreach ($Server in $ServerName)
    {

      Invoke-Command -ComputerName $Server -ScriptBlock {
      $VMs = Get-VM

      $colVMs = @()

      foreach ($VM in $VMs)
      {

      $objVM = New-Object System.Object
      $objVM | Add-Member -MemberType NoteProperty -Name VMName -Value $VM.VMName 
      $objVM | Add-Member -MemberType NoteProperty -Name VMNotes -Value $VM.Notes
      $objVM | Add-Member -MemberType NoteProperty -Name VMState -Value $VM.State

    $colVMs += $objVM
      }

     $a = @{Expression={$_.VMName};Label='VM Name'}, `
          @{Expression={$_.VMNotes};Label='VM Description'}, `
          @{Expression={$_.VMState};Label='State'}

     "Program Name : $ProgramName"
     $colVMs |Where-Object {($_.VMState -eq '$ProgramName')} | Format-Table $a -AutoSize 

       } -ArgumentList $ProgramName
     }
  }
}

当我运行Resource-Summary -ProgramName Running -ServerName Demo

我没有得到任何价值。

当我用 RUNNING 替换 $ProgramName 时,我得到了预期的输出。

有几件事跳出来了:

如果您在单引号内有一个变量,它不会被 PowerShell 自动解析,因此在本节中,您实际上是将 VM 的状态与字符串 $ProgramName 而不是它的值:

$_.VMState -eq '$ProgramName'

尝试更改为双引号,或者根本 none。

此外,请检查括号 - 您缺少 Where-Object.

的结尾括号

供参考,例如参见post 关于如何 将参数传递给 powershell 中的脚本块 .

你的脚本中的问题是你如何调用脚本块,这在上面的 link 中有更详细的解释,但是你需要以相同的方式将任何 "external" 输入传递给它就好像你会像函数一样调用它。

您部分正确地执行了此操作,您正在使用 -ArgumentList 参数将 $ProgramName 发送到脚本锁,但您尚未在脚本块中指定如何访问它。

例如,查看

Invoke-Command -ArgumentList "Application" -ScriptBlock { 
    param($log)
    Get-EventLog $log
}

此处 -ArgumentList 包含输入,在脚本块内,$log 被赋值。

更新脚本以考虑到这一点:

Function global:Resource-Summary
{
    Param(
    [parameter(mandatory=$true)] $ProgramName,
    [parameter(mandatory=$true)] $ServerName
    )

    PROCESS
    {
        Foreach ($Server in $ServerName)
        {

            Invoke-Command -ComputerName $Server -ScriptBlock {
                param($name)
                $VMs = Get-VM

                $colVMs = @()

                foreach ($VM in $VMs)
                {

                $objVM = New-Object System.Object
                $objVM | Add-Member -MemberType NoteProperty -Name VMName -Value $VM.VMName 
                $objVM | Add-Member -MemberType NoteProperty -Name VMNotes -Value $VM.Notes
                $objVM | Add-Member -MemberType NoteProperty -Name VMState -Value $VM.State

                $colVMs += $objVM
                }

                $a = @{Expression={$_.VMName};Label='VM Name'}, `
                  @{Expression={$_.VMNotes};Label='VM Description'}, `
                  @{Expression={$_.VMState};Label='State'}

                "Program Name : $ProgramName"
                $colVMs |Where-Object {($_.VMState -eq "$name") | Format-Table $a -AutoSize 

                } 
            } -ArgumentList $ProgramName
        }
    }
}

另外,在我看来,-ArgumentList 在错误的行上,它需要在下面的右括号之后,一行完成。这样它就与 Invoke-Command 和脚本块在同一个 cmdlet 上。