Find GUID From MSI File

2019-01-24 07:15发布

问题:

How can I list the GUID of an installed program in Windows? Alternatively, is it easier to find the GUID if I have the MSI file?

I'm looking through the MSI file with Orca but not sure where to look to find the GUID.

Thanks!

回答1:

The three main GUIDs of a Windows Installer database are the Package Code, ProductCode, and UpgradeCode. The first is stored in the summary information stream (View menu in Orca), and the others are stored in the Property table. (Other forms of databases such as merge modules and patches have similar GUIDs in similar places, such as the merge module's GUID or the patch code GUID - each stored identically to the package code.)

To find them on a machine, you can look in the Uninstall key, where the ProductCode is often used. Or better yet, if you are looking to enumerate what is currently installed on the machine, you can call MsiEnumProducts.



回答2:

There are several ways to locate the product GUID for installed packages. Please prefer option number 3.

The most common are:

  1. Check in the registry underneath the following base paths using regedit.exe. Search for the application name (or just browse through each sub folder untill you find it). When you have found it you can pass it to msiexec.exe:
- 32-BIT SECTION:

 HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall
 HKCU\Software\Microsoft\Windows\CurrentVersion\Uninstall (per user section)
- 64-BIT SECTION:

 HKLM\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall
- MERGED SECTION (supposedly all of the above merged together, I have not verified):

 HKCR\Installer\Products
  1. Check the locally cached MSI package in %SystemRoot%\Installer. This is a cached version of the original MSI that was originally used to install the product on your computer.
    • You will need a tool capable of opening MSI files. Here is a list and comparison of features: What installation product to use? InstallShield, WiX, Wise, Advanced Installer, etc.
    • An MSI is an MS SQL database in disguise, you should also be able to open it with any compatible MS SQL data viewer tool.
    • The free MSI tool "Orca" from the Windows SDK is the preferred one for this simple data retrieval task. It is quick, small and reliable.
    • Then follow Michael Uhrman's advice from his answer above, and locate the package code in the summary stream, and the upgrade and the product code in the Property table. The package code is also visible from an MSI file's property page in Windows Explorer.
  2. Use Powershell to list package information. I find this the easiest and most practical option. See this answer for a screenshot and a sample: How can I find the product GUID of an installed MSI setup?

If what you are trying to do is to uninstall the product in question, see this comprehesive uninstall MSI answer: Uninstalling an MSI file from the command line without using msiexec

If you feel more comfortable using VBScript instead of Powershell, please try this answer from Phil Wilson: how to find out which products are installed - newer product are already installed MSI windows



回答3:

Typically (though not universally) if a piece of software uses MSI-based installation the GUID can be found in the Uninstall entry. It will usually either be the key name or will appear in the UninstallString and/or UninstallPath value. Sometimes life is easy and there is a ProductGuid value.

Uninstall entries can be found here:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall

On a 64-bit version of Windows there are two such keys, one for 64-bit software and a second for 32-bit software:

HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall


回答4:

My solution is that I wrote a small console app which returns ProductCode of any MSI file (name is passed as program argument). I'm doing it by reading the guid from .msi file itself. Basically I'm opening that msi file as a string and looking for a text started with "ProductCode", getting its index and taking 38-chars before that index position. Here is the screenshot:



回答5:

if you just want to know what ProductName and ProductCode (ProductId) a given MSI contains, without installing that MSI and checking the registry, you can query the MSI itself with PowerShell using a function like this (inspired by http://www.scconfigmgr.com/2014/08/22/how-to-get-msi-file-information-with-powershell):

function Get-MSIProperties {
  param (
    [Parameter(Mandatory=$true)]
    [ValidateNotNullOrEmpty()]
    [System.IO.FileInfo] $path,

    [string[]] $properties = @('ProductCode', 'ProductVersion', 'ProductName', 'Manufacturer', 'ProductLanguage')
  )
  begin {
    $windowsInstaller = (New-Object -ComObject WindowsInstaller.Installer)
  }
  process {
    $table = @{}
    $msi = $windowsInstaller.GetType().InvokeMember('OpenDatabase', 'InvokeMethod', $null, $windowsInstaller, @($Path.FullName, 0))
    foreach ($property in $properties) {
      try {
        $view = $msi.GetType().InvokeMember('OpenView', 'InvokeMethod', $null, $msi, ("SELECT Value FROM Property WHERE Property = '$($property)'"))
        $view.GetType().InvokeMember('Execute', 'InvokeMethod', $null, $view, $null)
        $record = $view.GetType().InvokeMember('Fetch', 'InvokeMethod', $null, $view, $null)
        $table.add($property, $record.GetType().InvokeMember('StringData', 'GetProperty', $null, $record, 1))
      }
      catch {
        $table.add($property, $null)
      }
    }
    $msi.GetType().InvokeMember('Commit', 'InvokeMethod', $null, $msi, $null)
    $view.GetType().InvokeMember('Close', 'InvokeMethod', $null, $view, $null)
    $msi = $null
    $view = $null
    return $table
  }
  end {
    [System.Runtime.Interopservices.Marshal]::ReleaseComObject($windowsInstaller) | Out-Null
    [System.GC]::Collect()
  }
}