powershellhashtablepsobject

Powershell - Hashtable collection in new PSObject


I'm started a query for our infrastructure to see how SNMP Service is configured on the servers. I managed to find a function that would extract just the relevant keys and values (without the PS* properties) from the 3 Registry paths :

Edit 1: I've copied the wrong Function initially. Also added the missing part where the function is called. I hope this clears out the confusion

Function Get-HashedProperty {
  [CmdletBinding()]
  Param(    
    [Parameter(Mandatory=$True)]
    [ValidateScript({Test-Path $_})]
    [String]$RegPath,
    [Parameter(Mandatory=$False)]
    [ValidateSet("Json","HashTable")]
    [String]$As
  )
  $Hash = @{}
  Get-ItemProperty "$RegPath" | 
    Get-Member -MemberType NoteProperty |
      Where-Object {$_.Name -notlike "PS*"} | Foreach {
        $_ | Select-Object -ExpandProperty Name | Foreach {
          $Value = Get-ItemProperty "$RegPath" -Name "$_"
          $Hash.Add("$_","$($Value."$_")")
        }
      }
   If($As -eq "Json"){
     $Hash = $Hash | ConvertTo-Json
   }
   Return $Hash
}

$mypaths = @("HKLM:\SYSTEM\CurrentControlSet\Services\SNMP\Parameters\ValidCommunities","HKLM:\SYSTEM\CurrentControlSet\services\SNMP\Parameters\RFC1156Agent","HKLM:\SYSTEM\CurrentControlSet\Services\SNMP\Parameters\PermittedManagers")

$all = $mypaths | foreach { Get-HashedProperty $_ }

The output of $all variable is below.

Name Value
BO@CA_w3Ad 8
BO@CA_r3Ad 4
sysLocation
sysContact
sysServices 76
one hp-sim-ap
three hp-sim-ap
1 localhost
two hp-sim-ap

What i'm struggling is to get this values in a separate hashtable or PSObject where i have to add also the ServerName and the InstallState of the SNMP Service. Whatever i do i still get the registry values as array.

Server SNMP-Service Col1 Col2
MyTestServer Installed {BO@CA_w3Ad, BO@CA_r3Ad, sysLocation, sysContact...} {8, 4, , ...}

I tried in few different ways, but i assume my lack of knowledge makes it hard to understand where i'm doing wrong.

For example

$a = @()
$item = New-Object PSObject -Property @{
    Server = $ENV:ComputerName
    'SNMP-Service' = (Get-WindowsFeature -Name SNMP-Service | Select InstallState).InstallState
    Col1 = @($All.Keys)
    Col2 = @($all.Values)
        }

$a += $item
$a
}

Expected output should be

Server SNMP-Service Name Value
MyTestServer Installed BO@CA_w3Ad 8
MyTestServer Installed BO@CA_r3Ad 4
MyTestServer Installed sysLocation
MyTestServer Installed sysContact
MyTestServer Installed sysServices 76
MyTestServer Installed one hp-sim-ap
MyTestServer Installed three hp-sim-ap
MyTestServer Installed 1 localhost
MyTestServer Installed two hp-sim-ap

Would highly appreciate a bit of help here :(


Solution

  • I suggest refactoring your approach:

    $mypaths | 
      Get-ItemProperty | 
      ForEach-Object {
        foreach ($prop in $_.psobject.Properties.Where({ $_.Name -notlike 'PS*'})) {
          # Construct and output an object with the desired properties.
          [pscustomobject] @{
            Server = $ENV:ComputerName
            # Note: Better to move this call out of the loop and use a cached value.
            'SNMP-Service' = (Get-WindowsOptionalFeature -Name SNMP-Service).InstallState
            Name = $prop.Name
            Value = $prop.Value
          }
        }
      }
    

    This outputs a stream of objects with the desired structure and values, which you can capture in an array by simple assignment ($a = ...).