Wix 工具集:“由于存在另一个客户端,因此不允许卸载组件”后完成清理
Posted
技术标签:
【中文标题】Wix 工具集:“由于存在另一个客户端,因此不允许卸载组件”后完成清理【英文标题】:Wix toolset: complete cleanup after "disallowing uninstallation of component since another client exists" 【发布时间】:2014-12-31 14:26:20 【问题描述】:今天我发现我的安装程序不再正确卸载。这意味着从那里卸载后,我的应用程序不再显示在控制面板中,但所有文件仍然存在。我查看了日志文件,发现很多“由于存在另一个客户端而不允许卸载组件”,这意味着我搞砸了..
那么清理我的电脑并防止它在未来发生的最佳方法是什么?是什么原因造成的? afaik 未完全卸载我的应用程序的早期版本是导致此错误的原因吗?
很遗憾,由于各种原因,无法使用 VM..
仅供参考:出于开发和测试目的,我通常使用 1.0.xxxxx 测试和创建安装程序,其中 xxxxx 通常保持不变。我的升级代码总是一样的。此外,我正在使用热量,并且尽可能让 wix 自动生成 GUID。此外,我有一个 CA 在安装后显示我的自述文件,还有一个用于执行批处理文件(使用 powercfg 修改注册表项)。卸载后运行可执行文件以导入 .reg 文件以恢复修改后的注册表项(因为它们将被 wix 卸载)。
【问题讨论】:
不,这不是错误;这是信息性的。由于您是在一个接一个地安装共享一个组件的产品,因此在卸载所有产品之前不应删除该组件。您可能只想确保在安装下一个版本生成的产品之前卸载产品。 【参考方案1】:听起来您需要卸载安装了不需要的组件的功能(或整个产品)。 Windows Installer 具有用于查询组件、功能和产品的 API。 WiX 工具集在 API 周围集成了一个称为 DTF 的包装器。您可以使用它按组件查询功能。
所以,打开你最喜欢的 .NET 脚本运行器(我的是 LINQPad)并运行一个查询。例如,要了解如何删除“candle.exe”:
// using System.Linq;
// using Microsoft.Deployment.WindowsInstaller;
// <ref>"C:\Program Files (x86)\WiX Toolset v3.8\SDK\
Microsoft.Deployment.WindowsInstaller.dll"</ref>
ComponentInstallation.AllComponents
.Where(c=>c.State == InstallState.Local)
.Where(c => c.Path.ToLowerInvariant().EndsWith(@"\candle.exe"))
.SelectMany(c => c.ClientProducts
.SelectMany(p => p.Features.Where(f => f.Usage.UseCount > 0)
.Select(f => new
c.Path,
f.FeatureName,
p.LocalPackage,
p.UserSid,
p.ProductCode)))
LINQPad Instant Share
然后,运行msiexec /x <ProductCode>
删除产品的所有功能
或msiexec /i <LocalPackage> REMOVE=<FeatureName>
仅删除安装该组件的功能。
【讨论】:
【参考方案2】:尽管这是一个有点旧的链接,但是发布我的发现可能会对面临同样情况的其他人有所帮助。
如果您在日志文件中找到了"Disallowing uninstallation of component: Some GUID since another client exists"
,那么原因可能是您之前的安装可能仍然引用此组件/GUID。
此外,如果您冒着尝试手动删除注册表项的风险,您甚至可能在 regedit 中找不到 GUID。
但这些注册表中可能很少有,而且它们可能是隐藏的。在这种情况下,请使用 RegSeeker 工具 http://www.hoverdesk.net/ ,它可以帮助找到隐藏的注册表。在处理注册表时要保持警惕和谨慎。
根据 GUID,从您的解决方案/项目中获取组件的名称,并使用此工具的“在注册表中查找”选项找到它。仅验证并删除您认为不需要的条目。
诚然,我是通过以下链接了解这个工具的
http://www.daviddeley.com/solutions/msiexec/index.htm
【讨论】:
一点更正:注册表项本身没有隐藏(可以通过regedit或任何其他注册表查看/编辑实用程序正常查看);但它们不包含组件的 GUID。相反,GUID 值被转换为字节,字节被转换为十六进制字符串,这就是注册表路径的一部分。【参考方案3】:我们最近遇到了这样一个案例,即我们的一台开发机器在卸载时无法删除所有组件。然而,在其他机器上,WiX
设置按预期工作。
因此,如果您错误地卸载了产品的早期版本并收到消息 Disallowing uninstallation of component: GUID since another client exists
,则很有可能您的注册表中存在孤立组件。
有一个更优雅的解决方案可以使用PowerShell
删除那些隐藏注册表项,而不是像其他人提到的那样使用第三方应用程序。
$productName = "Path\\YourProductName" # this should basically match against your previous
# installation path. Make sure that you don't mess with other components used
# by any other MSI package
$components = Get-ChildItem -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Components\
$count = 0
foreach ($c in $components)
foreach($p in $c.Property)
$propValue = (Get-ItemProperty "Registry::$($c.Name)" -Name "$($p)")."$($p)"
if ($propValue -match $productName)
Write-Output $propValue
$count++
Remove-Item "Registry::$($c.Name)" -Recurse
Write-Host "$($count) key(s) removed"
如果您想获得有关消息disallowing uninstallation...
的原因的更详细说明,请查看here。
【讨论】:
谢谢!我能够对此进行修改,并纠正了我正在构建的 WixInstaller 应用程序的卸载问题。【参考方案4】:遵循此工作流程完美:
How to fix "disallowing uninstallation of component since another client exists"?
在那里创建两个文件后,在应用下一步之前有必要为它们删除 BOM。我用过记事本++ (Encoding
> Encode in UTF-8
)。
使用 Notepad++ 的多光标可以轻松地为每一行添加 /f 选项 - 使用 SHIFT
+ALT
+Arrows
激活它
【讨论】:
以上是关于Wix 工具集:“由于存在另一个客户端,因此不允许卸载组件”后完成清理的主要内容,如果未能解决你的问题,请参考以下文章
将 MsiPackage 安装为 /passive(WIX 工具集)