如何找到已安装 MSI 设置的产品 G​​UID?

Posted

技术标签:

【中文标题】如何找到已安装 MSI 设置的产品 G​​UID?【英文标题】:How can I find the product GUID of an installed MSI setup? 【发布时间】:2015-07-08 09:00:05 【问题描述】:

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

【问题讨论】:

绝对简单快捷的方式:github.com/glytzhkof/all/blob/master/MsiRetrieveProductCode.vbs(保存并从桌面运行 - 输出 msiinfo.csv)。 【参考方案1】:

对于升级代码检索: How can I find the Upgrade Code for an installed MSI file?(or use the html table export script - 如下第 2 节所示)


短版

随着时间的推移,以下信息已显着增加,可能有些过于详尽。 如何快速获取产品代码?(四种方式):

1 - Use the Powershell "one-liner"

向下滚动查看屏幕截图和分步操作。免责声明也在下方 - 轻微或中等风险,具体取决于您询问的对象。对我来说没问题。此选项触发的任何自我修复通常都应该可以取消。不过,触发的包完整性检查确实添加了一些事件日志“噪音”。 注意IdentifyingNumber ProductCode(WMI 特性)。

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

Powershell快速启动:按住Windows键,点击R,输入“powershell”并按Enter

更新:正如 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 自我修复,因为它不通过 WMI(它直接访问 MSI COM API - 以极快的速度)。 但是,它比 Powershell 选项更复杂(几行代码)。

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

3 - Registry Lookup

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

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

您需要一个工具来查看 MSI 文件。有关可以下载的免费工具列表,请参阅以下答案的底部(或查看下面的快速选项):How can I compare the content of two (or more) MSI files?

更新:为了方便和需要速度 :-),请立即从this direct-download hotlink 下载SuperOrca - 该工具足以获得工作完成 - 安装,打开 MSI 并直接转到 Property table 并找到 ProductCode 行(请始终检查直接下载热链接 - 显然 - 你可以使用 virustotal.com 来做所以 - 使用数十种防病毒和恶意软件套件来扫描您上传的内容的在线扫描)。

Orca 是微软自己的工具,它与 Visual Studio 一起安装,并且 Windows SDK。尝试搜索 Orca-x86_en-us.msi - 在 Program Files (x86) 并安装 MSI(如果找到)。

当前路径C:\Program Files (x86)\Windows Kits\10\bin\10.0.17763.0\x86 根据需要更改版本号

您会在下面找到“有机地成长”成很多细节的原始答案。

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


检索产品代码

更新:如果您还需要升级代码,请查看以下答案: How can I find the Upgrade Code for an installed MSI file?(在 表格输出 - 类似于下面的输出)。

不能使用 PowerShell? 请参阅下面的“替代工具”部分。 要卸载?请参阅下面的“卸载 MSI 软件包”部分。

启动 Powershell按住 Windows 键,点击 R,松开 Windows 键,输入“powershell”并按 OK)并运行以下命令获取已安装的 MSI 包产品代码列表以及本地缓存包路径产品名称(最大化 PowerShell 窗口以避免截断名称)。

在运行此命令行之前,请阅读下面的免责声明(没有危险,只是一些潜在的麻烦)。 “替代工具”下的第 3 节显示了使用 VBScript 获取相同信息的替代非 WMI 方法。如果您尝试卸载软件包,下面有一个部分包含一些示例 msiexec.exe 命令行:

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

输出应该类似于:

注意!出于某种奇怪的原因,“ProductCode” 在 WMI 中被称为 “IdentifyingNumber” .所以换句话说 - 在上图中,IdentifyingNumber ProductCode。

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

免责声明(重要,请在运行命令前阅读!):由于奇怪的 Microsoft 设计,任何对 Win32_Product 的 WMI 调用 (如下面的 PowerShell 命令)将触发对 包房地产。除了相当慢之外,这在极少数情况下可能 触发 MSI 自我修复。这可以是一个小包裹之类的 巨大的 - 像 Visual Studio。在大多数情况下,这不会发生 - 但是 有风险。 不要在重要任务之前运行此命令 会议 - 它并不危险(它是只读的),但它可能 在极少数情况下会导致长时间维修(我认为您可以取消 自我修复也 - 除非有问题的包主动阻止,但如果你调用 Win32_Product 它将重新启动 再次,这将一直持续到您让自我修复完成 - 有时即使您让它完成,它也可能会继续:How can I determine what causes repeated Windows Installer self-repair?)。

仅作记录:some people report their event logs filling up with MsiInstaller EventID 1035 entries(参见代码主管的回答)——显然是由对 Win32_Product 类的 WMI 查询引起的(我个人从未见过这种情况)。这与上面建议的 Powershell 命令直接相关,它是在 WIM 类 Win32_Product 的一般使用的上下文中。

您还可以获取列表形式的输出(而不是表格):

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) 的影响>(加上任何其他非 Microsoft 因素 - 例如真正的防火墙第三方软件防火墙各种安全软件等。 .)。它是否有效取决于您的确切设置。

Setting up a Remote WMI Connection Connecting to WMI Remotely with PowerShell

更新:可以在此答案中找到有关远程 WMI 运行的详细部分:How can I find the Upgrade Code for an installed MSI file?。似乎防火墙规则和通过注册表调整来抑制 UAC 提示可以使事情在工作组网络环境中工作。不建议在安全方面进行更改,但它对我有用。


替代工具

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

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

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

    接下来,您可以尝试自定义、功能更全的 WMI 工具,例如 WMIExplorer.exe
这不包含在 Windows 中。然而,它是一个非常好的工具。推荐。 查看:https://github.com/vinaypamnani/wmie2/releases 启动工具,点击连接,双击ROOT\CIMV2 在“查询选项卡”中,输入以下查询SELECT IdentifyingNumber,Name,Version FROM Win32_Product,然后按执行。 已跳过屏幕截图,应用程序需要太多屏幕空间。
    最后你可以尝试VBScript通过MSI自动化界面访问信息(Windows的核心功能-它与WMI无关) .
复制以下脚本并粘贴到桌面上的 *.vbs 文件中,然后尝试通过双击运行它。您的桌面必须是可写的,或者您可以使用任何其他可写位置。 这不是一个很棒的 VBScript。 简洁优于错误处理和完整性,但它应该以最低的复杂性完成工作。 在您从中运行脚本的文件夹中创建输出文件(文件夹必须是可写的)。输出文件名为msiinfo.csv。 双击文件以在电子表格应用程序中打开,在导入时选择逗号作为分隔符 - 或者 - 只需在记事本或任何文本查看器中打开文件。 在电子表格中打开将允许使用高级排序功能。 这个脚本可以很容易地适应显示a significant amount of further details about the MSI installation。可在此处找到此演示: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

目前我想不出任何其他通用选项来检索产品代码,如果您知道,请添加。 只需编辑内联,不要添加太多 cmets。

您当然可以从您的应用程序中访问这些信息 通过调用the MSI automation interface(基于COM)或C++ MSI installer functions(Win32 API)。甚至可以在应用程序中使用 WMI 查询,就像在上面的示例中使用 PowerShellwbemtest.exeWMIExplorer.exe 一样。


卸载 MSI 包

如果您想要卸载找到产品代码的 MSI 软件包,您可以使用 提升的命令提示符执行以下操作(搜索cmd.exe,右键单击并以管理员身份运行):

选项 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 节,其中链接了一些常见和标准卸载命令行变体的答案。

还有一个指向msiexec.exe (command line options) 的快速链接(来自 MSDN 的 msiexec.exe 命令行概述)。还有the Technet version


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

更新:请查找a new answer on how to find the upgrade code for installed packages,而不是手动查找 MSI 文件中的代码。为了 安装包这更可靠。如果包裹没有 安装后,您仍然需要查看 MSI 文件(或源文件 用于编译 MSI)来查找升级代码。留在下面的旧部分:

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

要打开缓存的 MSI 文件,请使用 Orca 或其他打包工具。以下是对不同工具的讨论(其中任何一个都可以):What installation product to use? InstallShield, WiX, Wise, Advanced Installer, etc。如果您没有安装这样的工具,您最快的选择可能是尝试Super Orca(它使用简单,但未经我广泛测试)。

更新:这是一个新答案,其中包含可用于查看 MSI 文件的各种免费产品的信息:How can I compare the content of two (or more) MSI files?

如果您安装了 Visual Studio,请尝试搜索 Orca-x86_en-us.msi - 在 Program Files (x86) 下 - 并安装它(这是 Microsoft 自己的官方 MSI 查看器和编辑器)。然后在开始菜单中找到 Orca。马上去:-)。从技术上讲,Orca 是作为 Windows SDK(不是 Visual Studio)的一部分安装的,但 Windows SDK 与 Visual Studio 安装捆绑在一起。 如果您没有安装 Visual Studio,也许您知道有人安装了?只需让他们搜索此 MSI 并将其发送给您(这是一个很小的半 mb 文件)- 应该花费他们几秒钟的时间。 更新:您需要几个 CAB 文件以及 MSI - 这些文件位于找到 MSI 的同一文件夹中。如果没有,你可以随时下载Windows SDK(它是免费的,但它很大——你安装的所有东西都会降低你的电脑速度)。我不确定 SDK 的哪个部分安装了 Orca 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

【讨论】:

谢谢。我尝试使用 geek.exe 和 Revo,但我通过注册表对关键字进行了核对,但我没有记录 guid,这会显示空白。 Win32_Product 真的不应该被查询,因为它不是只读操作。显然,它会对每个软件包进行一致性检查,然后如果发现任何软件包,则继续进行修复安装。见sdmsoftware.com/group-policy-blog/wmi/… 和support.microsoft.com/kb/974524 我相信这已经在上面的答案中得到了详尽的记录(免责声明部分)。 Win32_Product 之所以被调用,是因为 UpgradeCode 不容易以其他方式访问。 There is another way described here,但它也有一些不愉快的方面(MSI API 会话对象)。 我以为你在谈论 UpgradeCode。您可以通过 MSI API 轻松获取 ProductCode,我在上面提供了一个 VBScript(“替代工具”中的第 3 节)。也许可以创建一个 Powershell cmdlet 来完成这项工作。也许我有时间会看看。它可以直接通过 MSI API - 在引擎盖下。 我有一个更高级的 VBScript 可以将输出格式化为可排序、可过滤/可搜索的 HTML 格式,但我还没有完成它的 QA,它也主要供我自己使用和测试。它还显示升级代码和相关产品代码(共享相同的升级代码)。我建议您在电子表格应用程序(例如 Microsoft Excel)中打开导出的文本文件,并将其作为分隔列表导入,以逗号作为分隔符 - 然后您可以对格式进行任何操作。只需将输出文件重命名为 msiinfo.csv 并双击它 - 然后将逗号设置为分隔符。【参考方案2】:

如果您的安装程序太多而无法轻松找到所需内容,这里有一些 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

【讨论】:

至于之前的答案,Get-WmiObject 在 PS 7 中不可用。此代码完美运行。谢谢!【参考方案3】:

还有一个非常有用的 GUI 工具,称为产品浏览器,它似乎是由 Microsoft 或至少是 Microsoft 的员工制作的。

可以在 Github 上找到 Product Browser

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

【讨论】:

【参考方案4】:

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

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

【讨论】:

【参考方案5】:

我没有足够的 Rep 点数可以直接回复 Stein Asmul,也许有人可以给他发消息,但这是我从 VBScript 解决方案改编的 powershell 单行代码,我发现它比现有的 powershell 更可靠-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 以查找潜伏在每个用户安装而不是机器范围内的程序。

【讨论】:

是的,这通过 COM 而不是 WMI,因此与我列出的 VBScript 选项一样快。我将把它作为对第一点的评论。

以上是关于如何找到已安装 MSI 设置的产品 G​​UID?的主要内容,如果未能解决你的问题,请参考以下文章

安装后MSI文件复制到哪里?

如何找到已安装 MSI 文件的升级代码?

获取已安装 Msi 的产品代码

使用字符串操作为MSI安装程序设置安装目录

可以卸载的已安装程序/更新列表

如何设置 wix msi 以运行管理员广告