使用msiexec卸载应用程序时,是否有GUID的替代方法?

时间:2018-02-07 16:55:45

标签: powershell windows-installer installer uninstall msiexec

我们当前正在使用GUID在运行包含msiexec的卸载脚本时识别应用程序。我遇到的问题是每次安装最新版本的应用程序时GUID都会更改,所以我想知道是否有一种不同的方法可以识别我们使用msiexec运行的应用程序?

3 个答案:

答案 0 :(得分:1)

首先:产品GUID对应用程序的新版本更改是正常的,但也可以在不更改产品GUID的情况下升级某些应用程序(称为{{3 - 而不是更改产品GUID的minor upgrades。在同一产品的不同版本之间保持稳定的是 UpgradeCode (它定义了一系列相关产品)。 ProductCode唯一标识产品(在特定版本中)。

此处列出了一些卸载选项: major upgrades

我想您可以使用section 3中所示的MSI文件名,或者如果产品名称保持稳定,您可以将其与自动化一起使用,以查找正确的产品GUID以卸载相关产品。我将在稍后对此进行测试并更新答案。

更新:通过“产品名称”卸载产品的示例VBScript(假设它在各个版本中保持不变,它通常会这样做,但不保证 - 这取决于产品)。< / p>

在“添加/删除程序”中查找产品名称 - 或使用此答案底部链接的微小VBScript导出一个包含所有已安装软件包信息的小文本文件。

' On Error Resume Next ' Used to suppress errors

Const msiUILevelNone = 2
Const msiUILevelFull = 5
Const msiInstallStateAbsent = 2

Set installer = CreateObject("WindowsInstaller.Installer")
Set products = installer.ProductsEx("", "", 7)
installer.UILevel = msiUILevelFull  ' Running with full GUI (if available in MSI)
' installer.UILevel = msiUILevelNone ' Will run uninstall silently, run script with admin rights

' Get the product name from the user
productname = InputBox("Please enter the product name for the MSI package you wish to uninstall:")
If productname = vbCancel Or Trim(productname) = "" Then
   WScript.Quit(0)
End If    

' Iterate over all MSI packages on the box
For Each product In products

   currentproduct = product.InstallProperty("ProductName")

   If LCase(currentproduct) = LCase(productname) Then

      installer.ConfigureProduct product.productcode, 0, 2 ' msiInstallStateAbsent
      MsgBox "Ran uninstall for: " & currentproduct
      Exit For ' End product iteration, assuming only one product needed uninstall

   End If 

Next

Set installer = Nothing

MsgBox "Finished."

更新:您可以使用VBScript自行创建产品代码和产品名称的快速列表,如本答案底部所述:Uninstalling an MSI file from the command line without using msiexec。这个特殊的VBScript就像我想的那样简单。

答案 1 :(得分:1)

在这种情况下,人们绕过各种ProductCode值的常用方法是从更常量的UpgradeCode开始。

鉴于UpgradeCode,您可以使用MsiEnumRelatedProducts(或脚本或MSI interop等效项)来返回ProductCode。像这样的代码通常永远不需要改变。

我非常确定PowerShell应该能够做到这一点。

答案 2 :(得分:0)

您知道什么不会改变,或者确实会改变但您可以轻松跟踪?

  • 说产品代码更改,但升级代码没有。您可以按照PhilDW的建议,使用MsiEnumRelatedProductsInstaller.Related或同等版本从该升级代码中检索产品代码。

  • 假设名称不相同。您可以按照Stein的建议按产品名称查找产品代码,从MsiEnumProductsExInstaller.ProductsEx或同等产品开始。

  • 假设您将安装.msi的本地副本缓存在一个不变的位置,或者您的脚本很容易找到的位置。您可以按照4c74356b41的建议在msiexec的命令行中使用该路径。 (请注意,msiexec /x接受包路径或产品代码。)

  • 假设您不喜欢这些选项。也许您可以在HKEY_LOCAL_MACHINE \ Software \ YourCompany \ YourProduct中添加注册表值,将字符串值ProductCode设置为[ProductCode]。然后,您可以使用reg query HKLM\Software\YourCompany\YourProduct /v ProductCode或等效的(抱歉,我是PowerShell)来获取当前的产品代码。 (当然,至少如果您考虑32位与64位路径。)