Trouble getting properties and object structured correctly

118 Views Asked by At

I am trying to create an object with properties identical to the code below. The following bit of code creates the $TempValueICM object with 2 added NoteProperties:

$TempValueICM = Invoke-Command -ComputerName $computer -ScriptBlock {
                $AppPull = Get-ItemProperty HKLM:\software\Microsoft\Windows\CurrentVersion\Uninstall\* |
                    Select-Object DisplayName, DisplayVersion}

It creates $temptValueICM as an array object with NoteProperties of DisplayName and Display version which appear like this:

DisplayVersion : 4.92.12.0

DisplayName : Conexant 20561 SmartAudio HD

DisplayVersion :

DisplayName : Connection Manager

DisplayVersion :

DisplayName : MouseSuite98

...

I am trying to pull the same data using .NET pull with the following code:

$Hive = [Microsoft.Win32.RegistryHive]::LocalMachine
$AppAddressMain = "software\Microsoft\Windows\CurrentVersion\Uninstall\"
$AppAddressWOW = "software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\"



Function Get-InstalledApps {
    param ($MainHive, $Computer, [string[]]$RegAddress)

    Foreach($Address in $RegAddress) {
        $RegBaseKey = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($MainHive, $computer)
        $RegSubKey= $RegBaseKey.OpenSubKey($Address)
        foreach($Subkey in $RegSubKey.GetSubKeyNames()){
            $AppAddress = $Address + $Subkey

            $DisplayName = $($RegBaseKey.OpenSubKey($AppAddress)).GetValue("DisplayName")
            $DisplayVersion = $($RegBaseKey.OpenSubKey($AppAddress)).GetValue("DisplayVersion")
            Write-Output  @{
                DisplayName = $DisplayName
                DisplayVersion = $DisplayVersion
                }
             }
        }

This produces a Hash table data and I can get some information out and access it by using dot notation (e.g. - "$TempValue.DisplayName") but when looking at the object it is showing only "keys" and "values" as object properties for $TempValue object instead of what I would want to be the property names (e.g. - DisplayName and DisplayVersion).

I have tried creating a temporary variable within the function to hold the data as properties e.g. -

 $Temp = "" | select DisplayName, DisplayVersion
     $Temp.DisplayName += ,$DisplayName
     $Temp.Publisher += ,$Publisher
     $Temp.DisplayVersion += ,$DisplayVersion

But that doesn't do it...

Specifically I will eventually have to do a sort-object -properties on it and need for the logic for both functions to be the same (i.e. - so that data can come from either "logic" in the same format so it can be treated the same way.

How do I get the object formatted so the same information is available in the same way as the $TempValueICM above above (i.e. - how do I get the items in the hash table to fill in properties on the object)? Thanks,

2

There are 2 best solutions below

3
On BEST ANSWER
$Hive = [Microsoft.Win32.RegistryHive]::LocalMachine
$AppAddressMain = "software\Microsoft\Windows\CurrentVersion\Uninstall\"
$AppAddressWOW = "software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\"

Function Get-InstalledApps
{
    param ($MainHive,
        $Computer,
        [string[]]$RegAddress)

    Foreach ($Address in $RegAddress)
    {
        $RegBaseKey = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($MainHive, $computer)
        $RegSubKey = $RegBaseKey.OpenSubKey($Address)
        $output = @()
        foreach ($Subkey in $RegSubKey.GetSubKeyNames())
        {
            $AppAddress = $Address + $Subkey
            $DisplayName = $($RegBaseKey.OpenSubKey($AppAddress)).GetValue("DisplayName")
            $DisplayVersion = $($RegBaseKey.OpenSubKey($AppAddress)).GetValue("DisplayVersion")
            $output += [PSCustomObject]@{ DisplayName = $DisplayName; DisplayVersion = $DisplayVersion }
        }
    }
    return $output
}

Get-InstalledApps -MainHive $Hive -Computer "MyPC" -RegAddress $AppAddressMain | sort DisplayName
0
On

The following appears to work although it looks a little clunky:

 Function Get-InstalledApps {
    param ($MainHive, $Computer, [string[]]$RegAddress)

    Foreach($Address in $RegAddress) {
        $RegBaseKey = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($MainHive, $computer)
        $RegSubKey= $RegBaseKey.OpenSubKey($Address)
        $ReturnTotal = foreach($Subkey in $RegSubKey.GetSubKeyNames()){
            $ReturnInd = "" | Select-Object DisplayName, DisplayVersion
            $AppAddress = $Address + $Subkey
            $DisplayName = $($RegBaseKey.OpenSubKey($AppAddress)).GetValue("DisplayName")
            $DisplayVersion = $($RegBaseKey.OpenSubKey($AppAddress)).GetValue("DisplayVersion")

            $ReturnInd.DisplayName = $DisplayName
            $ReturnInd.DisplayVersion = $DisplayVersion
            Write-Output $Return
        }
        Write-Output $ReturnTotal
    }
} 

Essentially I added an individual variable ($ReturnInd) to gather each pull from each Subkey run. Then I made another variable to contain the entire results of the foreach subkey loop ($ReturnTotal) and then wrote that to output.

The result isn't exactly like the other method - the first produces a "Deserialized.Selected.System.Management.Automation.PSCustomObject" whereas this produces a "Selected.System.String" but they both have the properties I need.

I am able to sort both with the following command:

$TempValue | Sort-Object -Property DisplayName

If someone can figure out a better way of getting this (or better/cleaner/easier-to-read code), please do...