2

I'm trying to format my output to look like so

PSComputerName       Value
--------------       ------
Computer1           Restricted
Computer2           Unrestricted
Computer3           Unrestricted

This is my code the variable $computers points to Get-Content of a file with computer names that I will be connecting to remotely

$test = Invoke-Command -ComputerName $computers -ScriptBlock {
$policy3 = Get-ExecutionPolicy 
Write-Output $policy3
}
write $test 

The output

PSComputerName             RunspaceId                 Value                     
--------------             ----------                 -----                     
Computer1                    7e4ebfbe-62d3-4035-9d5a... Restricted                
Computer2                    2ecd6932-1ed4-4f57-b9e9... Unrestricted              
Computer3                    73a119de-5d6d-4525-9958... Restricted                

I've been trying to get rid of the RunSpaceId by echoing the invoke-command and doing a foreach of the computer names, I only did PSComputerNames to test if it would work.

write $test % {$_.PSComputerName }

I know that Invoke-Command has a foreach function built in it but I don't know how to use to my advantage in this situation. What is the best way to achieve my desired output?

Katz
  • 826
  • 3
  • 19
  • 40
  • 1
    Are you familiar with the [`Select-Object` cmdlet](https://learn.microsoft.com/powershell/module/microsoft.powershell.utility/select-object) and its capabilities? – Lance U. Matthews Oct 01 '17 at 23:22
  • I am and I did try it before but inside the Invoke-Command and for some reason it did not display anything for PSComputerName or Value and it was disordered however I just tried it outside the invoke-command and it did in fact work. @BACON Thanks! – Katz Oct 01 '17 at 23:28
  • 1
    The `PSComputerName` and `RunspaceId` properties are added by `Invoke-Command` which is why you can only access them (or strip them off) outside of the call to `Invoke-Command`. – Lance U. Matthews Oct 01 '17 at 23:38

1 Answers1

2
PS> Invoke-Command $computers { Get-ExecutionPolicy } |
      Format-Table PSComputerName, Value

PSComputerName  Value                     
--------------  -----                     
Computer1       Restricted                
...

As BACON points out in comments on the question, it is Invoke-Command that implicitly adds the PSComputerName and RunSpaceId properties to the objects returned by the script block ({ ... }) run on each target computer, and whether they are displayed by default depends on the type of the object returned.
In the case of the [Microsoft.PowerShell.ExecutionPolicy] instances returned by Get-ExecutionPolicy, they are displayed by default, which means that in order to display only the properties of interest you need an explicit Format-* call.

Note that an automatically added Value property is an artifact of the remotely executed script block returning an instance of an [enum]-derived type, such as the instances of [Microsoft.PowerShell.ExecutionPolicy] returned by Get-ExecutionPolicy.

Remotely invoked Invoke-Command script blocks outputting non-primitive-.NET-type instances return deserialized objects of type Deserialized.<original-type-name>.
[enum]-derived instances result in a deserialized type with a Value property defined as a ScriptProperty member with signature System.Object Value {get=$this.ToString();}; for general information about how serialization and deserialization works in PowerShell remoting and background jobs, see this answer.


General tips:

  • Write-Output is generally not needed, because the output of any statement that is not captured in a variable or redirected to a file / to $null is implicitly sent to the output stream.

  • If you ever need to write cross-platform-compatible code, avoid aliases such as write, because they won't work as expected on Unix-like platforms in PowerShell Core, where aliases that would shadow native utilities aren't defined.

mklement0
  • 382,024
  • 64
  • 607
  • 775