1

I just want to use the list of servers returned from the compare-object output and I get 2 columns. InputObject and SideIndicator. InputObject has the servers I want, and SideIndicator has the '<='. I've tried to just select InputObject from the variable using dot notation but not having any luck.

How do I return just the InputObject values with nothing else?

current output

$GetAllVMs = Get-VM
$AllVMNames = $GetAllVMs.Name
$TaggedVMs = $GetAllVMs | Get-NsxSecurityTagAssignment
$TaggedVMsNames = $TaggedVMs.VirtualMachine.Name

$testing = Compare-Object -ReferenceObject $AllVMNames -DifferenceObject $TaggedVMsNames | Where-Object {$_.SideIndicator -eq "<="} | Select-Object $_.InputObject | Sort-Object InputObject | Format-Table



$testing


InputObject                                                              SideIndicator
-----------                                                              -------------
server1                                                                  <=
server2                                                                  <=
server3                                                                  <=
dcvl
  • 485
  • 1
  • 7
  • 21

2 Answers2

1

The simplest way to get the input objects themselves is to use the -PassThru switch:

PS> Compare-Object 'server1', 'server2', 'server3' @() -PassThru
server1
server2
server3

The caveat is that the input objects are still decorated with a SideIndicator NoteProperty member (as opposed to being wrapped in a [pscustomobject] instance with InputObject and SideIndicator prperties), using PowerShell's ETS (Extended Type System).

As shown above, this property doesn't necessarily surface, but there are contexts where it does, such when you serialize the objects via ConvertTo-Json for instance.

Unfortunately, the only way to avoid this decoration is to not use -PassThru and to extract the InputObject property value from the output [pscustomobject] instances, which is what you tried:

I've tried to just select InputObject from the variable using dot notation but not having any luck.

Accessing the .InputObject property on all output objects via member-access enumeration does work:

# Test command that compares an array of strings to the empty array.
PS> (Compare-Object 'server1', 'server2', 'server3' @()).InputObject
server1
server2
server3

If you're planning to collect all objects in memory anyway, this will do and is the fastest option.

Only if streaming of the results via the pipeline is needed (for one-by-one processing without accumulating the results in memory) do you need to pipe to ForEach-Object InputObject or Select-Object -ExpandProperty InputObject.

mklement0
  • 382,024
  • 64
  • 607
  • 775
0

You should pipe the output through Select-Object e.g.

Get-MyServers | Compare-Object -ReferenceObject $refobj | Select-Object -ExpandProperty 'InputObject'

Where Get-MyServers is the name of the cmdlet that you're using to get your server names, and $refobj is the object you're comparing against. See https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/select-object?view=powershell-7

cschadl
  • 66
  • 1
  • 3