0

Powershell script is only returning one value from Invoke-Command not all the objects I would expect.

I am adding a property to an existing object on a remote server then returning it back.

$inventory contains application objects that look like this:

Name         : Centinel-Dev-AmazonServer
Platform     : Centinel
Type         : Windows Service
Tier         : APP
Status       : Running

Name         : Portal-QA-Walmart
Platform     : Portal
Type         : Windows Service
Tier         : APP
Status       : Running

There are many more application objects similiar to the two given when I run my script it only returns the first object not all.

function verify_workingDir {
    param($server)
    $inventory = GetInventory -Server $server
    $return_object = @()
    $return_object += Invoke-Command -ComputerName $server -ScriptBlock {
        $inventory = $args[0]

        $return_object = @()
        foreach ($Application in $inventory) {

            $applicationParamters = Get-ItemProperty -Path x:\x\x\x\$($Application.Name)\Parameters


            $verify_object = [pscustomobject] @{
                WorkingDirectory = $applicationParamters.ServiceWorkingDir
            }


            $ExpandVerifyObject = $verify_object | Select-Object -Property @{
                Name       = "MyProperties"
                Expression = {$_.WorkingDirectory }
            } | Select-Object -ExpandProperty MyProperties

            Add-Member -MemberType NoteProperty -Name WorkingDirectory -InputObject $Application -TypeName PSObject -Value $ExpandVerifyObject
            $return_object += $Application    
        }

        return $return_object

    } -ArgumentList ($inventory) #| Select Name, Platform, Type, Tier, Status, ServerName, WorkingDirectory

    return $return_object
}

Answer:
  $inventory = $args[0] ---> $inventory = $args
Myron Walters
  • 193
  • 1
  • 4
  • 13

1 Answers1

1

Try $inventory = $args instead of $inventory = $args[0].

Passing arrays to script blocks is not the easiest thing because $args flattens everything to a single array. If you pass -ArgumentList @(1,2,3), 4, then $Args will be a single array @(1,2,3,4) and $Args[0] will be 1.

If you ever need to pass complex arguments with -ArgumentList, pass them all as a single HashTable: -ArgumentList @{FirstArg = @(1,2,3); SecondArg = 4}.

Bacon Bits
  • 30,782
  • 5
  • 59
  • 66
  • *Passing arrays to script blocks is not the easiest thing because `$args` flattens everything to a single array.* Can you show example of this? I am trying `Invoke-Command -Command { ConvertTo-Json -InputObject $args -Compress } -ArgumentList @(1,2,3),4` and get `[[1,2,3],4]` as result. No flattening here. – user4003407 Dec 05 '17 at 17:07
  • @PetSerAl [This](https://stackoverflow.com/questions/7152740/how-to-pass-an-array-as-a-parameter-to-another-script) or [this](https://stackoverflow.com/questions/17577705/passing-array-to-another-script-with-invoke-command) must be the problem I'm thinking of. The real problem comes when you need to pass multiple arrays as parameters, because `-Arg (,$Arr1),$Val1,(,$Arr2)` may not work at all. – Bacon Bits Dec 05 '17 at 17:56
  • *because `-Arg (,$Arr1),$Val1,(,$Arr2)` may not work at all.* Maybe it because you should use `$Arr1,$Val1,$Arr2` instead. You should not write it like this `(,$Arr1)` unless you are passing only one argument. – user4003407 Dec 05 '17 at 19:08
  • @PetSerAl "You should not write it like this" Why? This works just fine: `$x=@(1,2,3); $y = @((,$x),4,(,$x)); $y[0]; $y[1]; $y[2];`. The fact that with `Invoke-Command` you have to say `$x=@(1,2,3); Invoke-Command -Command { $args[0][0]; $args[1]; $args[2][0] } -ArgumentList @((,$x),4,(,$x))` is what's anomalous. The language should behave consistently and it doesn't here because of all the background encapsulation. That's why I say: stick all your arguments in a `HashTable` and pass arguments that way. It's the most consistent and obvious behavior. – Bacon Bits Dec 05 '17 at 20:19
  • *This works just fine: `$x=@(1,2,3); $y = @((,$x),4,(,$x)); $y[0]; $y[1]; $y[2];`.* But `$y[0].Length; $y[2].Length;` will return `1` and `1`, but not `3` and `3`. – user4003407 Dec 05 '17 at 20:29
  • *The fact that with Invoke-Command you have to say `$x=@(1,2,3); Invoke-Command -Command { $args[0][0]; $args[1][0] } -ArgumentList @((,$x),(,$x))` is what's anomalous.* You do not have to say it: `$x=@(1,2,3); Invoke-Command -Command { $args[0]; $args[1] } -ArgumentList ($x,$x)`. You have to write `$args[0][0]` instead of `$args[0]` only because you write `(,$x)` instead of `$x`. You just need to unwrap that additional array lever, which you created. – user4003407 Dec 05 '17 at 20:29
  • But can you show actual example, where language behave inconsistently with regard of `$args` variable? You claim it is, but not show any example yet. – user4003407 Dec 05 '17 at 20:35
  • @PetSerAl Sorry, I don't remember the precise details of problems I encountered and fixed over a year ago. I don't even remember what script it was. I just remember having a problem with PowerShell treating all the parameters as a single flat array and fixing it with HashTables. – Bacon Bits Dec 05 '17 at 21:34