0
votes

I need a hint how to get the upgrade code from an installed MSI out of the registry. Actually I'm having the product code, which can be retrieved from HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\.

Now I want to retrieve the upgrade code (based on the product code) from HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UpgradeCodes.

My problem is that the product code is used as value-name, which means I've a REG_SZ where the name is the product code guid and the value is empty.

One way to retrieve the product code might be:

PS HKLM:\SOFTW...Codes> Get-ItemProperty * | select -First 1 | gm

    TypeName: System.Management.Automation.PSCustomObject

Name                             MemberType   Definition
----                             ----------   ----------
Equals                           Method       bool Equals(System.Object obj)
GetHashCode                      Method       int GetHashCode()
GetType                          Method       type GetType()
ToString                         Method       string ToString()
42F79228D77BA4A4EB5150F3DC090CE3 NoteProperty System.String 42F79228D77BA4A4EB5150F3DC090CE3=
...

How can I check if a PSCustomObject has the property 42F79228D77BA4A4EB5150F3DC090CE3?

Does anybody knows if there is a more elegant way?

1
You can achieve this using WMI so you don't have to read registry keys and interpret them. You will get the real upgrade code back in its proper format automagically. See this answer: How can I find the Upgrade Code for an installed MSI file? (the VBScript towards the bottom).Stein Åsmul
@SteinÅsmul: Using WMI to query installed MSIs is a bad idea -> Read this -> stackoverflow.com/questions/25083520/….Moerwald
I am fully aware of this, but there is no self-heal running if the package estate is properly installed. What is running is an integrity check of the package estate (admittedly making things very slow), but self-repair only runs if a discrepancy is found. And in most cases the self-repair can be cancelled if you are busy. I already warn about this issue in my answer on how to find product codes here: How can I find the product GUID of an installed MSI setup?.Stein Åsmul
Thanks for reminding me to add a disclaimer about this "package integrity check issue" to my new answer on how to retrieve upgrade codes as well. And thanks for the link - I added an answer to that question too on how to use the MSI automation interface instead of WMI. Unfortunately it seems upgrade codes can only be retrieved via WMI (it is missing from the MSI automation interface it seems).Stein Åsmul

1 Answers

1
votes

This is how you can check. Working on that elegant solution...

$properties = Get-ItemProperty * | select -first 1 | Get-Member | Where-object {$_.MemberType -eq "NoteProperty"}

if("42F79228D77BA4A4EB5150F3DC090CE3" -in $properties.Name){
    Write-Output "It's in there!"
}

Edit

This is a bit more elegant. It goes to the HKLM path, and checks for a PSChildName (Registry Key) that is the same as the code.

If found, it will return the Name and property. If not found, the variable $codeExists will be $null.

$code       = "42F79228D77BA4A4EB5150F3DC090CE3" 
$codeExists = Get-ChildItem "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UpgradeCodes" | Where-Object {$_.PSChildName -eq $code}

if($codeExists){
     Write-Output "It's in there!"
}