How to extract ProductCode from msi package? I want to use it later to uninstall msi via msiexec as described here
Asked
Active
Viewed 1.2k times
11
-
2this is in VB script but could give some ideas: http://leereid.wordpress.com/2008/08/20/vbscript-get-msi-productcode/ – Davide Piras Feb 15 '11 at 14:45
-
1Orca.exe is your friend if you'd like to do this manually – Yan Sklyarenko Feb 15 '11 at 14:54
-
See also http://stackoverflow.com/questions/113542/how-can-i-uninstall-an-application-using-powershell – Ruben Bartelink Apr 11 '12 at 16:02
3 Answers
4
I can think of dozens of ways to do it. What programming languages do you currently use and/or comfortable with?
Take a look at
You could use WiRunSQL.vbs ( provided in the Platform SDK ) to run the command:
cscript /nologo WiRunSQL.vbs FOO.msi "SELECT Value FROM Property WHERE Property = 'ProductCode'"

ks1322
- 33,961
- 14
- 109
- 164

Christopher Painter
- 54,556
- 6
- 63
- 100
-
I want to do it from command line. The best way is to run some tool or at least VB script which will do the job. Standalone tool is preferable. – ks1322 Feb 15 '11 at 15:52
-
1Let's pretend I had GetProductCode.exe FOO.MSI ... what would you want it to do? Set an environment variable? Output to the console? I'm trying to understand the bigger picture so I can suggest something. – Christopher Painter Feb 15 '11 at 15:56
-
I would want it to output to console. Then I would save output and pass it to msiexec in this way: cmd /c msiexec /x {SOME_PRODUCT_CODE} /q no matter how. I only need some easy way to obtain ProductCode. – ks1322 Feb 15 '11 at 16:08
-
I updated my answer to do what you want but I am a little confused why you want to get the PC and /x PC when you could just say /x FOO.msi – Christopher Painter Feb 15 '11 at 17:46
-
In my case FOO.msi can be up to 300Mb so it takes some time to load it. With PC I can immediately start uninstall process without loading msi. Thanks for help, this is what I was looking for. – ks1322 Feb 16 '11 at 09:05
-
Realize that some (mostly poorly written) installers can end up requiring access to the 300MB MSI during uninstall. – Christopher Painter Feb 16 '11 at 11:56
-
@Christopher Painter: Some installers (like one I'm testing) give a "Another version is already installed" message if you `msiexec /u` them. So, I personally would be interested in one of your remaining 11 solutions which a) don't give that error b) ideally dont require arbitrary bits of arbitrary SDKs. – Ruben Bartelink Apr 11 '12 at 15:36
-
-
-
1Windows Installer XML (WiX) has an MSI SDK called Deployment Tools Foundation (DTF). DTF includes an MSI interop library called Microsoft.Deployment.WindowsInstaller which is the gold standard. If you don't want any dependencies then take a look at P/Invoke.Net or the source code to said assembly for how to query MSI's. – Christopher Painter Sep 24 '13 at 13:56
-
+1 Thanks for that detail (only seeing now due to absence of atting). Now I need to cross my fingers that my interest in this topic doesn't get retriggered :P – Ruben Bartelink Oct 11 '13 at 15:58
1
I wrote a Powershell function that I use when generating MSI-based Chocolatey packages at work, to detect if our internal package is installing a program that was already installed via other means:
function Get-MsiProductCode {
[CmdletBinding()]
param (
[Parameter(Mandatory=$true)]
[ValidateScript({$_ | Test-Path -PathType Leaf})]
[string]$Path
)
function Get-Property ( $Object, $PropertyName, [object[]]$ArgumentList ) {
return $Object.GetType().InvokeMember($PropertyName, 'Public, Instance, GetProperty', $null, $Object, $ArgumentList)
}
function Invoke-Method ( $Object, $MethodName, $ArgumentList ) {
return $Object.GetType().InvokeMember( $MethodName, 'Public, Instance, InvokeMethod', $null, $Object, $ArgumentList )
}
$ErrorActionPreference = 'Stop'
Set-StrictMode -Version Latest
#http://msdn.microsoft.com/en-us/library/aa369432(v=vs.85).aspx
$msiOpenDatabaseModeReadOnly = 0
$Installer = New-Object -ComObject WindowsInstaller.Installer
$Database = Invoke-Method $Installer OpenDatabase $Path, $msiOpenDatabaseModeReadOnly
$View = Invoke-Method $Database OpenView "SELECT Value FROM Property WHERE Property='ProductCode'"
[void]( Invoke-Method $View Execute )
$Record = Invoke-Method $View Fetch
if ( $Record ) {
Get-Property $Record StringData 1
}
[void]( Invoke-Method $View Close @() )
Remove-Variable -Name Record, View, Database, Installer
}

codewario
- 19,553
- 20
- 90
- 159
0
You could achieve a similar effect by doing the following in PowerShell based on the installed programs:
Get-WmiObject -Class Win32_Product -Filter "Vendor LIKE 'The Company%' AND Name LIKE '%The Product%'" | %{
Write-Host "Uninstalling $($_.IdentifyingNumber)"
$_.Uninstall()
}
(Obv the tighter the query, the quicker it will run - the LIKE above is very expensive)
Or you could apply the general technique in here on your stack.

Ruben Bartelink
- 59,778
- 26
- 187
- 249
-
Win32_Product queries will never run quickly because frankly the MSI WMI provider is horribly written. This also assumes that the MSI he wants the ProductCode for is installed on the system. – Christopher Painter Sep 24 '13 at 12:14
-
@ChristopherPainter Fair enough. To be honest I'm having difficulty recalling where I needed this and/or what solution I actually applied in the end :) – Ruben Bartelink Sep 24 '13 at 13:51
-
Another warning against using `Win32_Product`, this can trigger MSI repairs unintentionally. – codewario Jun 12 '19 at 16:28