0

Trying to take a number of objects from a class using get-WmiObject. I have to return this as a hash-table/ dict type.

Command I'm using:


get-WmiObject -class win32_SoundDevice | select-object Name, Status

What I get:

Name                   Status
----                   ------
Intel(R) Display Audio OK
Realtek Audio          OK

I want to create something that looks like this:

[
    {
        "Name":  "Intel(R) Display Audio",
        "Status":  "OK"
    },
    {
        "Name":  "Realtek Audio",
        "Status":  "OK"
    }
]

I know I can append the | convertTo-json command to the initial command, but I want to create the hash-table from scratch as I will be using it on legacy systems that may not have use of convertTo-json command.

suspense_hey
  • 85
  • 2
  • 11
  • what do you mean by "hashtable"? i don't see any hashtable anywhere in your examples ... [*grin*] – Lee_Dailey Jul 05 '19 at 16:59
  • `Select-Object` returns `System.Management.Automation.PSObject`, not a hashtable. `ConvertTo-Json` is available in PowerShell 3.0+. – JosefZ Jul 05 '19 at 17:16
  • @Lee_Dailey key : value pair objects in the form your see above. – suspense_hey Jul 05 '19 at 17:26
  • @JosefZ As i said at The bottom, I don't want to rely on the convertto-Json command. – suspense_hey Jul 05 '19 at 17:27
  • Seconding @Lee_Dailey What do you want? an object of type Hashtable, an object of type Dictionary, a custom PS Object, an object of type text that is formatted in a JSON format? By simply assigning the output of the command to a variable, you inherently have an object array of key-value objects. – HAL9256 Jul 05 '19 at 17:43
  • @JoshQuinn - i DO NOT see any hashtable anywhere. [*frown*] the JSON you show is an array of PSObjects that have two properties each. – Lee_Dailey Jul 05 '19 at 17:44
  • You could start with `Get-WmiObject -class win32_SoundDevice | Select-Object Name, Status | ForEach-Object { """$($_.Name)""", """$($_.Status)""" -join ':'}` (and try adding appropriate `[]`, `{}` and `,`… – JosefZ Jul 05 '19 at 17:47
  • Possible duplicate of [Save hash table in PowerShell object notation (PSON)](https://stackoverflow.com/questions/15139552/save-hash-table-in-powershell-object-notation-pson) – iRon Jul 05 '19 at 18:26

2 Answers2

2

If you cannot use the ConvertTo-Json cmdlet, this should help:

function ConvertTo-Json20([object] $item){
    # serializes object(s) to JSON. The result will be in compressed format.
    Add-Type -AssemblyName System.Web.Extensions

    $jsSerializer = New-Object System.Web.Script.Serialization.JavascriptSerializer
    return $jsSerializer.Serialize($item)
}


# When using 'Select-Object Name, Status' you will get an array of PSObjects which the above function 
# cannot handle. Therefore, I'm using Old-School to get the results from the Get-WmiObject cmdlet
# into an array of Hashtables.

$result = Get-WmiObject -Class win32_SoundDevice | ForEach-Object {
    @{
        'Name' = $_.Name
        'Status' = $_.Status
    }
}

ConvertTo-Json20 $result

On my machine, the result is

[{"Name":"Conexant ISST Audio","Status":"OK"},{"Name":"Intel(R) Display Audio","Status":"OK"}]

Theo
  • 57,719
  • 8
  • 24
  • 41
  • 1
    Appending to an array is an expensive memory operation. Please do not teach others to do that. You can actually assign the variable one time in memory by capturing all the output of the loop. Just do `$result = Get-WmiObject -Class win32_SoundDevice | ForEach-Object { @{ 'Name' = $_.Name; 'Status' = $_.Status } }`. – JosefZ Jul 05 '19 at 21:31
  • 1
    @JosefZ You're right, although the memory impact in his case is negligible with so few iterations. Updated my answer. – Theo Jul 05 '19 at 22:10
1

To Serialize a PowerShell object to a PowerShell expression, you might consider this ConvertTo-Expression cmdlet:

ConvertTo-Expression (get-WmiObject -class win32_SoundDevice | select-object Name, Status)

Result:

[PSCustomObject]@{
        'Name' = 'USB Multi-Channel Audio Device'
        'Status' = 'OK'
},
[PSCustomObject]@{
        'Name' = 'High Definition Audio Device'
        'Status' = 'OK'
},
[PSCustomObject]@{
        'Name' = 'High Definition Audio Device'
        'Status' = 'OK'
}

For more information, see: Save hash table in PowerShell object notation (PSON)

iRon
  • 20,463
  • 10
  • 53
  • 79
  • Note that legacy systems prior PSv3 do not support creating objects via the `[PSCustomObject]@{...}` method. For this systems, you should use the [`New-Object`](https://learn.microsoft.com/powershell/module/microsoft.powershell.utility/new-object?view=powershell-6) cmdlet. Therefore you might want to use the `ConvertTo-Expression -Explore` switch which will suppress all the type prefixes causing any object to cast to a `HashTable`. – iRon Jul 05 '19 at 19:17