Merging dictionaries within powershell

I needed to join dictionaries from within a list together, so that they become one whole dictionary.
First I thought it may be a trivial task. Than I used google and realized, that everything on the first page was just wrong or impracticable for lists with unknown size.

What I found, was stuff like:

$a = @{"foo"=1}
$b = @{"bar"=2}
$c = @($a,$b) | ForEach-Object {$_}


$a = @{"foo"=1}
$b = @{"bar"=2}
$c = $a + $b

The console output of $c will look identical for both:

Name                           Value
----                           -----
foo                            1
bar                            2

But the issue is with the data structure. This becomes a problem when we would like to access the data.


Will output $null for the first example and “2” for the 2nd. But why is this?
Lets convert it to json (without piping, this is important) to see:

ConvertTo-Json -InputObject $c

which outputs for the first case:

    "foo": 1
    "bar": 2

and for the 2nd what we originally expected:

  "bar": 2,
  "foo": 1

So now we know that the first one did not join the dictionaries, but warped them into a list. As we originally looked for a solution to join a list of dictionaries, this is not helpful.
(From now on $c is the output from the first example, as it is the same as my original input)
The 2nd one however looks helpful, but has two issues:

  1. It only works if we know how many elements we have (hard coded element count)
  2. It copies the list once for each element we want to add to it.

So let’s address these issues:

  1. For the 1st one something like this will do the trick:
    $c | ForEach-Object -Begin {[Hashtable]$aa = @{}} -Process {$aa += $_} -End {$aa} | ConvertTo-Json
  2. But for the 2nd we need something a bit more advanced like
    $c | ForEach-Object -Begin {[Hashtable]$aa = @{}} -Process {foreach($element in ($_.GetEnumerator())) {$aa.Add($element.Key,$element.Value)}} -End {$aa} | ConvertTo-Json

Documentation of a given infrastructure

Getting the same information from every pc especially in a very complex and grown environment can be a tedious work. So why don’t just call a script to help out 😉

# Network Drives
Get-WmiObject -Class Win32_MappedLogicalDisk | Select-Object Name,ProviderName

# Powershell Version

# Get all Printer
Get-WMIObject -Class Win32_Printer | Select-Object -Property Name,PortName,Default | Sort-Object Name |Sort-Object Default -Descending | Out-String

# Get Office
Get-WmiObject -Class Win32_Product -Filter "name like '%office%'" | Select-Object -Property Vendor,Name,Version | Out-String

# Get all Applications
Get-WmiObject -Class Win32_Product | Select-Object -Property Vendor,Name,Version | Out-String

# Local Drives (with ntfs):
Get-WmiObject win32_volume -Filter "filesystem like 'ntfs'" | Sort-Object Name | Select-Object Name,Label | Out-String

# Find all local PST-Files
# Get-ChildItem -Path C:\ -Filter *.pst -Recurse -ErrorAction SilentlyContinue
Get-WmiObject win32_volume -Filter "filesystem like 'ntfs' and DriveLetter like '%'" | foreach-object {Get-ChildItem -Path $ -Filter *.pst -Recurse -ErrorAction SilentlyContinue | Select-Object FullName | Out-String}

# Processor and Windows Architecture
Get-WmiObject Win32_processor | Select-Object Name,Caption,AddressWidth,DataWidth | Out-String
Get-WmiObject Win32_OperatingSystem | Select-Object OSArchitecture | Out-String

# Get Bios Information
Get-WmiObject win32_bios | Select-Object SerialNumber,Manufacturer,BiosVersion,ReleaseDate,SMBIOSBIOSVersion,SMBIOSMajorVersion,SMBIOSMinorVersion | Format-Table | Out-String
Get-WmiObject Win32_ComputerSystem | Select-Object Manufacturer,Model,NumberOfProcessors,NumberOfLogicalProcessors | Out-String

# Environment Variables
Get-ChildItem Env: | Out-String

# # Get EventLog
# Get-EventLog -LogName *