如何找到已安装的 MSI 安装程序的产品 G​​UID?

How can I find the product GUID of an installed MSI setup?

我需要为已安装的 MSI 文件找到产品 GUID,以便执行维护,例如 patchinguninstall (how-to uninstall) 以及 auditing purposes .

For upgrade code retrieval: (or use the html table export script - shown below in section 2)


精简版

下面的信息随着时间的推移有了很大的增长,可能变得有点过于详尽了。 如何快速获取产品码?(四种方法):

1 - Use the Powershell "one-liner"

向下滚动屏幕截图和 step-by-step。免责声明也在下方 - 轻微或中等风险取决于您询问的对象。适合我。由该选项触发的任何 self-repair 通常应该可以取消。 包完整性检查触发确实添加了一些事件日志"noise"。 注意IdentifyingNumber ProductCode(WMI 特性)。

get-wmiobject Win32_Product | Sort-Object -Property Name |Format-Table IdentifyingNumber, Name, LocalPackage -AutoSize
    

Powershell 快速启动:按住Windows键,点击R , 输入 "powershell" 然后按 Enter

UPDATE:正如 Alexis Coles 所说,您可以跳过 WMI 并通过 COM(更快):

$Installer = New-Object -ComObject WindowsInstaller.Installer; $InstallerProducts = $Installer.ProductsEx("", "", 7); $InstalledProducts = ForEach($Product in $InstallerProducts){[PSCustomObject]@{ProductCode = $Product.ProductCode(); LocalPackage = $Product.InstallProperty("LocalPackage"); VersionString = $Product.InstallProperty("VersionString"); ProductPath = $Product.InstallProperty("ProductName")}} $InstalledProducts
    

If you want the upgrade code, maybe use the html export instead(下面第 2 部分)

2 - Use VBScript (script on github.com - html export version)

在下面的“替代工具”(第 3 部分) 下进行了描述。此选项可能 比 Powershell 更安全,原因将在下面详细说明。从本质上讲,它 更快 并且无法触发 MSI self-repair 因为它不通过 WMI(它直接访问 MSI COM API - 以极快的速度). 但是,它比 Powershell 选项更复杂(多行代码)。

注意:html版本也获得了升级代码。它可以触发 self-repair 和过多的日志记录。请参阅 script itself 中嵌入的警告。通常它 运行 没有问题,但需要一段时间才能完成。

3 - Registry Lookup

有些人发誓要在注册表中查找内容。不是我推荐的方法——我喜欢通过适当的 API(或者换句话说:OS 函数调用)。总是有一些奇怪的异常仅由 API-implementation:

的内部解释
  • HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall
  • HKLM\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall
  • HKCU\Software\Microsoft\Windows\CurrentVersion\Uninstall

4 - Original MSI File / WiX Source

您可以找到任何 MSI 文件的 Product Code in the Property table(以及任何其他 属性)。但是,GUID 可以想象(很少)被安装时应用的转换覆盖,因此与产品注册的 GUID 不匹配(上面的方法 1 和 2 将报告真实的产品代码 - 用 Windows - 在这种罕见的情况下)。

您需要一个工具来查看 MSI 文件。请参阅以下答案的底部,了解您可以下载的免费工具列表(或查看下面的快速选项):

更新:您可以下载 SuperOrca - the tool is good enough to get the job done - install, open MSI and go straight to the Property table and find the ProductCode row (please run the download through a malware check - you can use virustotal.com 来执行此操作 - 在线扫描使用数十个 anti-virus 和恶意软件套件来扫描您上传的内容)。

Orca is Microsoft's own tool, it is installed with Visual Studio and the Windows SDK. Try searching for Orca-x86_en-us.msi - under Program Files (x86) and install the MSI if found.

  • Current path: C:\Program Files (x86)\Windows Kits\bin.0.17763.0\x86
  • Change version numbers as required towards the end of the path - obviously

您会在下面找到原始答案,其中 "organically grew" 包含很多细节。

如果这是您需要执行的任务,请参阅下面的“卸载 MSI 软件包”部分。


检索产品代码

UPDATE: If you also need the upgrade code, check this answer: (retrieves associated product codes, upgrade codes & product names in a table output - similar to the one below).

  • Can't use PowerShell? See "Alternative Tools" section below.
  • Looking to uninstall? See "Uninstall MSI packages" section below.

启动Powershell按住Windows键,点击R,松开Windows键,输入"powershell" 并按 OK) 和 运行 下面的命令以获取已安装的 MSI 软件包列表 产品代码 以及 local缓存包路径产品名称(最大化PowerShell window以避免t运行分类名称)。

在 运行 使用此命令行之前,请阅读下面的免责声明(没有危险,只是一些潜在的麻烦)。 "Alternative Tools" 下的第 3 节显示了另一种 non-WMI 使用 VBScript 获取相同信息的方法。如果您正在尝试卸载软件包,下面有一节包含一些示例 msiexec.exe 命令行:

get-wmiobject Win32_Product | Format-Table IdentifyingNumber, Name, LocalPackage -AutoSize
    

输出应该类似于这样:

注意! 由于某些奇怪的原因,"ProductCode" 被称为 "IdentifyingNumber" 在 WMI 中。所以换句话说 - 在上面的图片中,IdentifyingNumber ProductCode.

如果您需要 运行 对大量远程计算机进行远程查询,请参阅“从远程计算机检索产品代码”下面的部分。

DISCLAIMER (important, please read before running the command!): Due to strange Microsoft design, any WMI call to Win32_Product (like the PowerShell command below) will trigger a validation of the package estate. Besides being quite slow, this can in rare cases trigger an MSI self-repair. This can be a small package or something huge - like Visual Studio. In most cases this does not happen - but there is a risk. Don't run this command right before an important meeting - it is not ever dangerous (it is read-only), but it might lead to a long repair in very rare cases (I think you can cancel the self-repair as well - unless actively prevented by the package in question, but it will restart if you call Win32_Product again and this will persist until you let the self-repair finish - sometimes it might continue even if you do let it finish: How can I determine what causes repeated Windows Installer self-repair?).

And just for the record: some people report their event logs filling up with MsiInstaller EventID 1035 entries (see code chief's answer) - apparently caused by WMI queries to the Win32_Product class (personally I have never seen this). This is not directly related to the Powershell command suggested above, it is in context of general use of the WIM class Win32_Product.

你也可以得到列表形式的输出(而不是table):

get-wmiobject -class Win32_Product
    

在这种情况下,输出类似于:


从远程计算机检索产品代码

理论上,您应该能够将远程计算机名称指定为命令本身的一部分。这是在机器 "RemoteMachine" 上设置为 运行 的相同命令(添加了 -ComputerName RemoteMachine 部分):

get-wmiobject Win32_Product -ComputerName RemoteMachine | Format-Table IdentifyingNumber, Name, LocalPackage -AutoSize
    

如果您是适当域的 运行 域管理员权限,这可能会起作用。在工作组环境(小型办公室/家庭网络)中,您可能必须将用户凭据直接添加到 WMI 调用才能使其正常工作。

此外,WMI 中的远程连接(至少)受Windows 防火墙DCOM 设置用户帐户控制 (UAC)(加上任何其他 non-Microsoft 因素 - 例如 真正的防火墙第三方软件防火墙各种安全软件,等等...)。它是否有效取决于您的具体设置。

更新:关于远程 WMI 运行ning 的详尽部分可以在这个答案中找到:。看起来防火墙规则和通过注册表调整抑制 UAC 提示可以使事情在工作组网络环境中工作。不推荐更改 security-wise,但对我有用。


替代工具

PowerShell 需要安装 .NET 框架(目前似乎是 3.5.1 版?2017 年 10 月)。即使安装了 .NET,实际的 PowerShell 应用程序本身 也可能从计算机中丢失。最后,我相信 PowerShell 可以被各种系统策略和权限禁用或锁定

如果是这种情况,您可以尝试其他几种方法来检索产品代码。我的首选替代方案是 VBScript - 它快速且灵活(但也可以锁定在某些机器上,并且脚本总是比使用工具更复杂)。

  1. 让我们从 built-in Windows WMI 工具开始wbemtest.exe.
  • 启动wbemtest.exe按住Windows键,点击R,松开Windows键,输入"wbemtest.exe"并按下OK).
  • 单击连接然后确定(命名空间默认为root\cimv2),然后单击“连接" 再一次。
  • 单击“查询”并输入此WQL 命令(SQL 风格):SELECT IdentifyingNumber,Name,Version FROM Win32_Product 和单击 "Use"(或等效项 - 该工具将被本地化)。
  • 示例输出屏幕截图(t运行cated)。不是最好的格式,但您可以获得所需的数据。 IdentifyingNumber 是 MSI 产品代码:

  1. 接下来,您可以尝试自定义的、功能更全的 WMI 工具,例如 WMIExplorer.exe
  • 这不包含在 Windows 中。然而,这是一个非常好的工具。推荐。
  • 查看:https://github.com/vinaypamnani/wmie2/releases
  • 启动该工具,单击连接,双击 ROOT\CIMV2
  • 从“查询选项卡”,输入以下查询SELECT IdentifyingNumber,Name,Version FROM Win32_Product并按执行。
  • 已跳过屏幕截图,应用程序需要太多屏幕空间。
  1. 最后您可以尝试 VBScript 通过 MSI 自动化接口 访问信息(Windows 的核心功能 - 它与 WMI)无关。
  • 复制以下脚本并粘贴到桌面上的 *.vbs 文件中,然后双击 运行 尝试。您的桌面必须是 writable,或者您可以使用任何其他 writable 位置。
  • 这不是一个很棒的 VBScript。 简洁优于错误处理和完整性,但它应该以最小的复杂性完成工作。
  • 输出文件创建在您运行脚本所在的文件夹中(文件夹必须是writable)。输出文件名为 msiinfo.csv.
  • 双击文件以在电子表格应用程序中打开,select导入时逗号作为分隔符 - 或者 - 只需在记事本或任何文本查看器中打开文件。
  • 在电子表格中打开将允许高级排序功能。
  • 这个脚本可以很容易地适应显示 a significant amount of further details about the MSI installation. A demonstration of this can be found here: how to find out which products are installed - newer product are already installed MSI windows
' Retrieve all ProductCodes (with ProductName and ProductVersion)
    Set fso = CreateObject("Scripting.FileSystemObject")
    Set output = fso.CreateTextFile("msiinfo.csv", True, True)
    Set installer = CreateObject("WindowsInstaller.Installer")
    
    On Error Resume Next ' we ignore all errors
    
    For Each product In installer.ProductsEx("", "", 7)
       productcode = product.ProductCode
       name = product.InstallProperty("ProductName")
       version=product.InstallProperty("VersionString")
       output.writeline (productcode & ", " & name & ", " & version)
    Next
    
    output.Close
    

I can't think of any further general purpose options to retrieve product codes at the moment, please add if you know of any. Just edit inline rather than adding too many comments please.

You can certainly access this information from within your application by calling the MSI automation interface (COM based) OR the C++ MSI installer functions (Win32 API). Or even use WMI queries from within your application like you do in the samples above using PowerShell, wbemtest.exe or WMIExplorer.exe.


卸载 MSI 软件包

如果您想做的是卸载您找到产品代码的 MSI 程序包,您可以使用 提升的命令提示符按如下方式执行此操作(搜索cmd.exe,右击并运行 as admin):

选项 1无需记录的基本交互式卸载(快速简便):

msiexec.exe /x {00000000-0000-0000-0000-00000000000C}
    

快速参数说明:

/X = run uninstall sequence
    {00000000-0000-0000-0000-00000000000C} = product code for product to uninstall
    

如果需要,您还可以在静默模式下启用(详细)日志记录和 运行,让我们选择选项 2:

选项 2带有详细日志记录的静默卸载(更适合批处理文件):

msiexec.exe /x {00000000-0000-0000-0000-00000000000C} /QN /L*V "C:\My.log" REBOOT=ReallySuppress
    

快速参数说明:

/X = run uninstall sequence
    {00000000-0000-0000-0000-00000000000C} = product code for product to uninstall
    /QN = run completely silently
    /L*V "C:\My.log"= verbose logging at specified path
    REBOOT=ReallySuppress = avoid unexpected, sudden reboot
    

此处有MSI 卸载的综合参考(卸载MSI 软件包的各种不同方法):Uninstalling an MSI file from the command line without using msiexec。有多种不同的卸载方法。

如果您正在编写批处理文件,请查看上面的第 3 部分,link编辑了一些常见和标准卸载命令行变体的答案。

并快速 link 到 msiexec.exe (command line options) (overview of the command line for msiexec.exe from MSDN). And the Technet version


正在检索其他 MSI 属性/信息(f.ex 升级代码)

UPDATE: please find instead of manually looking up the code in MSI files. For installed packages this is much more reliable. If the package is not installed, you still need to look in the MSI file (or the source file used to compile the MSI) to find the upgrade code. Leaving in older section below:

如果您想获取 UpgradeCode其他 MSI 属性,您可以从该位置打开产品的缓存安装 MSI由上图中的“LocalPackage”指定(类似于:C:\WINDOWS\Installerc080ae.msi - 它是一个十六进制文件名,在每个系统上都是唯一的)。然后你在“属性 table”中查找 UpgradeCode(UpgradeCode 可以在转换中重新定义 - 以确保你得到正确的您需要从系统中以编程方式检索代码的值 - 我将很快为此提供一个脚本。但是,在缓存的 MSI 中找到的升级代码通常是正确的)。

要打开缓存的 MSI 文件,请使用 Orca or another packaging tool. Here is a discussion of different tools (any of them will do): What installation product to use? InstallShield, WiX, Wise, Advanced Installer, etc. If you don't have such a tool installed, your fastest bet might be to try Super Orca(使用起来很简单,但我没有广泛测试)。

更新:这是一个新答案,其中包含有关可用于查看 MSI 文件的各种免费产品的信息:

如果你安装了Visual Studio,尝试搜索Orca-x86_en-us.msi - 在Program Files (x86)下 - 然后安装它(这是微软自己的,官方 MSI 查看器和编辑器)。然后在开始菜单中找到Orca。马上去吧:-)。从技术上讲,Orca 作为 Windows SDK(而非 Visual Studio)的一部分安装,但 Windows SDK 与 Visual Studio 安装捆绑在一起。 如果您没有安装 Visual Studio,也许您认识安装了的人?只需让他们搜索此 MSI 并发送给您(这是一个很小的半 mb 文件)- 他们应该花几秒钟的时间。 更新:您需要多个 CAB 文件以及 MSI - 这些文件位于 MSI 所在的同一文件夹中。如果没有,您可以随时下载 Windows SDK(它是免费的,但它很大 - 您安装的所有内容都会降低您的 PC 速度)。我不确定 SDK 的哪一部分安装了 Orca MSI。如果您这样做,请在此处编辑并添加详细信息。


  • 关于MSI卸载问题更全面的文章在这里:Uninstalling an MSI file from the command line without using msiexec
  • 这是一篇类似的文章,其中包含 一些其他选项,用于使用注册表或缓存的 msi 检索 MSI 信息:Find GUID From MSI File

类似主题(供参考和轻松访问 - 我应该清理此列表):

  • How to find the UpgradeCode and ProductCode of an installed application in Windows 7
  • How can I find the upgrade code for an installed application in C#?
  • Wix: how to uninstall previously installed application that is installed using different installer
  • WiX - Doing a major upgrade on a multi instance install
  • how to find out which products are installed - newer product are already installed MSI windows(使用 VBScript)
  • How to uninstall with msiexec using product id guid without .msi file present
  • Find GUID of MSI Package

如果安装程序太多而无法轻松找到所需的内容,这里有一些 powershell 可以提供过滤器并通过显示名称缩小范围。

$filter = "*core*sdk*"; (Get-ChildItem HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall).Name | % { $path = "Registry::$_"; Get-ItemProperty $path } | Where-Object { $_.DisplayName -like $filter } | Select-Object -Property DisplayName, PsChildName

还有一个非常有用的 GUI 工具,称为 Product Browser,它似乎是由 Microsoft 或至少是由 Microsoft 的员工制作的。

可以在 Github 此处找到 Product Browser

我个人很容易找到我需要的 GUID。

你可以看看MSI Finder。它允许您按名称、GUID 或位置搜索产品或组件,查看它们的属性,以及修复或卸载单个产品。

免责声明:我一直在寻找类似的解决方案,但找不到任何可靠或易于使用的解决方案。所以,我开发了这个工具。

我没有足够的 Rep 点数直接回复 Stein Asmul,也许有人可以给他发消息,但这是我从 VBScript 解决方案改编的 powershell one-liner,我发现它比现有的更可靠powershell one-liner,特别是当 运行 作为非管理员时,速度更快

$Installer = New-Object -ComObject WindowsInstaller.Installer; $InstallerProducts = $Installer.ProductsEx("", "", 7); $InstalledProducts = ForEach($Product in $InstallerProducts){[PSCustomObject]@{ProductCode = $Product.ProductCode(); LocalPackage = $Product.InstallProperty("LocalPackage"); VersionString = $Product.InstallProperty("VersionString"); ProductPath = $Product.InstallProperty("ProductName")}} $InstalledProducts

专业提示:将 7 更改为 3 以查找潜伏在每个用户而不是机器范围内的程序。