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?
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.