我们正在尝试从我们的组织中删除旧版软件。我们有不同的版本,并且正在尝试为所有版本创建通用卸载程序。我们遇到了一个似乎无法通过命令行卸载的特定版本。并且证明难以创建变通方法。
我通过
在注册表中找到了应用程序的GUIDHKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall
我运行的命令是:
msiexec /x {080FDF44-6D15-4D2E-977E-74D5168198E7}
我收到一个应用程序提示,询问我是否要卸载该产品,因此单击“是”。然后它看起来像是开始但从未真正做过任何事情。所以我在注册表中挖了一下,发现了另一个GUID:
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\Userdata\S-1-5-18\Products\44FDF08051D6E2D479E7475D6118897E
如果我使用不同的GUID运行与上面相同的命令,我会收到要求卸载的应用程序确认框,然后在单击“确定”后,我收到错误消息:
The installation package could not be opened. Verify the package exists and you can access it.......
我已经进入具有上述GUID的文件夹中的C:\ Windows \ Installer,其中包含一个图标和一个* .mst文件。在C:\ Windows \ Installer的根目录中,* .msi在详细信息中称为相同的产品,但具有另一个版本ID:
8A2C4F93-4B31-4474-B9F2-2E51BF5D71A8
如果我针对该ID运行msiexec,那么我会再次收到一个确认框,然后显示另一个错误
The action is only valid for products that are currently installed.
如果我运行卸载程序,它会从程序和功能中卸载并使用生成的* .msi进行卸载(例如C:\ Windows \ Installer \ 241a6.msi并匹配产品ID 8A2C4F93-4B31-4474 -B9F2-2E51BF5D71A8)。这将改变机器之间的形式。关于如何以整洁和有管理的方式解决这个问题的任何其他想法?
答案 0 :(得分:2)
您无法对ProductCode guid的注册表进行疏导,因为它们是混淆的。如果您真的不了解ProductCode,那么请查看枚举已安装产品的方法。例如,直接C ++方式是MsiEnumerateProducts和C#pinvoke等价物,如下所示:
MSI Interop using MSIEnumRelatedProducts and MSIGetProductInfo
然后您将获得实际的ProductCode,并可以获得其他信息。
如果有时在您完全确定ProductCode时它不起作用,那么它可能安装在每个用户上下文中,与您运行该程序的上下文不同。
此外,对于MSI安装的产品,Windows不使用卸载字符串,它只是直接使用ProductCode。同样,当存在专门用于枚举已安装的MSI产品的实际API时,注册表挖掘不是正确的。
如果卸载需要访问安装它的原始MSI,那么至少有两个原因:
MSI具有无条件的ResolveSource操作,强制它请求oroginal MSI文件。
已从C:\ windows \ installer中删除了MSI文件的缓存版本。