Home > Back-end >  Powershell - Hashtable collection in new PSObject
Powershell - Hashtable collection in new PSObject

Time:08-27

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 :

  • HKLM:\SYSTEM\CurrentControlSet\services\SNMP\Parameters\RFC1156Agent
  • HKLM:\SYSTEM\CurrentControlSet\Services\SNMP\Parameters\ValidCommunities
  • HKLM:\SYSTEM\CurrentControlSet\Services\SNMP\Parameters\PermittedManagers

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 :(

CodePudding user response:

I suggest refactoring your approach:

  • Use the intrinsic psobject property to reflect on the properties of the Get-ItemProperty output objects, which allows you to eliminate the PS-prefixed properties.

  • Then, for each remaining property, construct a [pscustomobject] instance with Name and Value properties, which you can supplement with the desired Server and SNMP-Service properties.

$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 = ...).

  • Related