0

I am trying to get the list of machines which are in particular state (Saved, Running, Stopped). I am passing the state of the machine as an argument in a function.

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
     }
  }
}

When I run Resource-Summary -ProgramName Running -ServerName Demo

I do not get any value.

When I replace $ProgramName with RUNNING I get the expected output.

2
  • Please check your question: Do you really call Resource-Summary -Program name ... or is it Resource-Summary -ProgramName ...? Commented Apr 4, 2018 at 6:14
  • Sorry there was a typo in the question. I use Resource-Summary -ProgramName Running -ServerName Demo .. Commented Apr 4, 2018 at 6:20

2 Answers 2

1

For reference, see e.g. this post on how Pass arguments to a scriptblock in powershell .

The problem in your script is how you call the script block, this is explained in more detail in the link above, but you need to pass any "external" input to it the same way as if you'd call it like a function.

You are doing this partially correctly, you are using the -ArgumentList parameter to send $ProgramName to the scriptslock but you haven't specified in the scriptblock how to access it.

For example, check out

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

Here -ArgumentList contains the input, and inside the scriptblock, $log is assigned its value.

Updating your script to take that into account:

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
        }
    }
}

Also, in my opinion, the -ArgumentList is on the wrong line, it needs to be after the following closing bracket, one line done. This way it's on the same cmdlet as Invoke-Command and the scriptblock.

Sign up to request clarification or add additional context in comments.

2 Comments

Kim, I am looking for one more help on this. In my example i am storing all my data to an array $a. How can i store this in an hash table ??? Please help me
Check out this blog alkanesolutions.co.uk/2016/11/22/… and this one mcpmag.com/articles/2017/06/08/…. In both posts are shown how you can create a multidimensional array. Hope this gets you started :)
1

A couple of things jump out:

If you have a variable inside single quotes, it won't be automatically resolved by PowerShell, so in this section, you are actually comparing the state of the VM to the string $ProgramName and not it's value:

$_.VMState -eq '$ProgramName'

Try changing to double quotes, or none at all.

Also, check the bracketing - you're missing the closing one for Where-Object.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.