1

I have a variable which is declared as (for example)

$dict_object = @{Firstname="A";Lastname="B"}

I want to run another command , any command for example, Get-CIMInstance -class win32_BIOS and I wanted to compare the output with the $dict_object variable using compare-object. The problem is that the $dict_object is a hashtable whereas the command output is not a hashtable. This is just example but is there any way to convert Powershell command output into a hashtable and compare it with a Hashtable variable/object. I tried using Convertfrom-stringData but it is not assigning key value pairs as expected.

For example, this is the command with convertfrom-stringdata

PS C:\Windows\System32> Get-CimInstance -class win32_bios | ConvertFrom-StringData
Name                           Value
----                           -----
Win32_BIOS: 1.6.0 (Name        "1.6.0", SoftwareElementID = "1.6.0", SoftwareElementState = 3, TargetOperatingSystem =…

versus normal output

PS C:\Windows\System32> Get-CimInstance -class win32_bios

SMBIOSBIOSVersion : 1.6.0
Manufacturer      : Dell Inc.
Name              : 1.6.0
SerialNumber      : BDM8P93
Version           : DELL   - 20170001 

I am expecting the above to has first column as key and second column as value but it seems ConvertFrom-StringData is not working that way.

I need this to compare existing variable with output from Get-WebconfigurationProperty (IIS Module) and if the value is not right, then else block will execute Add-webconfigurationProperty where I have tested that the Add-webconfigurationProperty takes HashTable as input

Dennis
  • 871
  • 9
  • 29
  • 2
    Why compare a hash table to an object with referenceable properties? You could easily turn your hash table into a custom object and then compare properties with `Compare-Object` -> `$dict_object = [pstcustomobject]@{Firstname="A";Lastname="B"}` – AdminOfThings Jan 09 '22 at 18:50
  • Cannot use [pscustomobject] as the output of a command with values are not known earlier to create it. – Vijayanand A Jan 16 '22 at 17:20

2 Answers2

1
  • Get-CimInstance outputs (non-string) objects, not strings, so its output cannot meaningfully serve as input to ConvertFrom-StringData, which expects strings in a specific format.

  • While you cannot (directly) convert objects to hashtables, you can directly convert preexisting[1] hashtables to ([pscustomobject]) objects; e.g.:

    $dict_object = 
    $object_from_dict = [pscustomobject] $dict_object
    
  • And, of course, you may directly a [pscustomobject] instance directly, as a literal[1]:

    $object = [pscustomobject] @{Firstname="A";Lastname="B"}
    

As AdminOfThings notes, once you have (non-hashtable) objects to compare, you can compare multiple properties across two [collections of] objects using the Compare-Object cmdlet, passing the set of properties to compare the objects by to the -Property parameter:

# Reference object (the one with comparison values).
$refObj = [pscustomobject] @{ Manufacturer = 'Dell Inc'; Name = '1.6.0' }

# Difference object (the one to compare against, from command output)
$diffObj = Get-CimInstance -Class win32_BIOS

# Compare the two objects, by the properties defined on the reference object.
Compare-Object $refObj $diffObj -Property $obj.psobject.Properties.Name

By default, Compare-Object outputs only those input objects that differ, wrapped in a [pscustomobject] instance with a .SideIndicator property indicating which input side the object is unique to; see this answer for more information.


[1] Creating [pscustomobject] literals even uses hashtable syntax (e.g., [pscustomobject] @{Firstname="A";Lastname="B"}), but that is actually syntactic sugar that constructs the object directly, not via an intermediate hashtable. Also note that such a literal preserves the definition order of the keys / property names, unlike true hashtables.

mklement0
  • 382,024
  • 64
  • 607
  • 775
  • I have given the example as it stated here in this forum. In ideal situation, comparing a dictionary value which is predefined to output of a command where I expect the command output to anything and the comparison is not going to be between properties of 2 objects rather it is going to be the object itself. So, by all means, I am hearing that the output of a powershell command cannot be converted into a hashtable object to compare with another dictionary and only the properties of 2 objects can be compared. – Vijayanand A Jan 16 '22 at 17:23
  • @VijayanandA, Alex_P's answers shows you how to construct a hashtable from the properties of an object (this could also be done without knowing the property names ahead of time). As for comparing objects by properties: you can pass any number of properties to `Compare-Object`'s `-Property` parameter. I don't understand the _is going to be the object itself_ part of your comment. Objects as a whole - unless they are instances of .NET value types - typically don't compare meaningfully, if they are distinct instances. – mklement0 Jan 16 '22 at 17:34
0

I would run the Get-CimInstance once and populate a hashtable according to the values you need. For example:

$cimInstance = Get-CIMInstance -class win32_BIOS
$cimHashTable = @{
  Name = $cimInstance.Name
  Version = $cimInstance.Version}
}
if ($cimHashTable.Name -eq 'CorrectValue')
{
  continue
}
else
{
  Fix-Value
}

However, in this case I actually wouldn't make the effort and create a new HashTable but just use the $cimInstance variable and check for the values directly.

Alex_P
  • 2,580
  • 3
  • 22
  • 37