Virtual Box中用Wix Toolset部署.NET 4.8 MSI报错:存在运行中安装
问题描述
用Wix Toolset构建了用于安装.NET Framework 4.8的MSI安装包,在Virtual Box环境执行安装时,弹出“存在其他正在运行的安装程序”报错;重试安装仍失败,最终只能取消安装。
原Wix代码片段:
<?xml version="1.0" encoding="UTF-8"?> <Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:bal="http://schemas.microsoft.com/wix/BalExtension" xmlns:util="http://schemas.microsoft.com/wix/UtilExtension" xmlns:netfx="http://schemas.microsoft.com/wix/NetFxExtension"> <Product Id="48CAD6F2-CA57-401E-AE5A-EEE8665F9750" Name="dotNetInstallationUsingWix" Language="1033" Version="1.0.0.0" Manufacturer="Naveen Ltd" UpgradeCode="0dabc91d-b2a0-4dd2-9ceb-cde6716edef7"> <Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" /> <MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." /> <MediaTemplate EmbedCab="yes"/> <UIRef Id="WixUI_Minimal" /> <Property Id="NETFRAMEWORK48INSTALLED"> <RegistrySearch Id="DotNetFX48Installed" Root="HKLM" Key="SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full" Name="Release" Type="raw" /> </Property> <Feature Id="ProductFeature" Title="dotNetInstallationUsingWix" Level="1"> <ComponentGroupRef Id="ProductComponents"/> </Feature> <CustomAction Id="DotNetFX48Install" Directory="INSTALLFOLDER" ExeCommand=""[INSTALLFOLDER]ndp48-x86-x64-allos-enu.exe"/q /norestart" Execute="deferred" Impersonate="no" Return="ignore" /> <InstallExecuteSequence> <Custom Action="DotNetFX48Install" After="InstallFiles"> NOT Installed </Custom> <ScheduleReboot After="InstallFinalize"/> </InstallExecuteSequence> </Product> <Fragment> <Directory Id="TARGETDIR" Name="SourceDir"> <Directory Id="ProgramFilesFolder"> <Directory Id="Foldername" Name="dotNetInstallationUsingWix"> <Directory Id="INSTALLFOLDER" Name="Softwares" /> </Directory> </Directory> </Directory> </Fragment> <Fragment> <ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER"> <Component Id="MainExecutable" Guid="C2E4D2D1-ECBE-4E06-A582-E4DDC0B74191"> <File Id="abc" Source="ndp48-x86-x64-allos-enu.exe" KeyPath="yes" /> </Component> </ComponentGroup> </Fragment> </Wix>
报错表现:安装过程中提示“存在其他正在运行的安装程序”,重试无效。
问题根源
Windows Installer(MSI运行核心)会持有全局互斥锁,禁止多个MSI/安装程序并发执行。当前代码在自身MSI的安装流程中,调用了.NET Framework 4.8的安装包(其本质是包裹MSI的引导程序),触发了互斥锁冲突,导致报错。此外代码还存在以下问题:
- 未正确判断.NET 4.8是否已安装,可能重复触发安装
- 用
Return="ignore"忽略了安装返回值,无法处理失败场景 - 将.NET安装包部署到Program Files目录,属于不必要的冗余
解决修改方案
方案1:改用Wix Burn引导程序(强烈推荐)
Wix Burn是专门用于链式安装的工具,能完美处理多个安装包的顺序执行、依赖检查和并发冲突问题,无需手动调用外部exe。
修改步骤:
- 创建Wix Bootstrapper项目(而非MSI项目)
- 引入NetFxExtension,直接使用内置的.NET 4.8安装支持
- 示例代码:
<?xml version="1.0" encoding="UTF-8"?> <Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:bal="http://schemas.microsoft.com/wix/BalExtension" xmlns:netfx="http://schemas.microsoft.com/wix/NetFxExtension"> <Bundle Name=".NET Framework 4.8 安装程序" Version="1.0.0.0" Manufacturer="Naveen Ltd" UpgradeCode="0dabc91d-b2a0-4dd2-9ceb-cde6716edef7"> <!-- 使用标准引导界面 --> <BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLicense" /> <!-- 链式安装:自动检查.NET 4.8,未安装则执行安装 --> <Chain> <!-- 使用Web版本自动下载,若需离线安装可改用NetFx48Redist --> <PackageGroupRef Id="NetFx48Web" /> <!-- 若需要同时安装你的主程序MSI,可添加以下行 --> <!-- <MsiPackage SourceFile="你的主程序MSI路径" /> --> </Chain> </Bundle> </Wix>
优势:
- 自动处理.NET 4.8的安装状态检查
- 管理安装顺序,避免Windows Installer互斥锁冲突
- 支持在线下载或离线部署两种模式
- 提供统一的安装界面和错误处理
方案2:修改原MSI代码(应急方案,不推荐)
若必须基于现有MSI修改,需解决互斥锁和安装检查问题:
1. 完善.NET 4.8已安装的判断
.NET 4.8的Registry Release值为528040及以上,需补充条件判断:
<Property Id="NETFRAMEWORK48INSTALLED"> <RegistrySearch Id="DotNetFX48Installed" Root="HKLM" Key="SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full" Name="Release" Type="raw" /> </Property> <!-- 添加安装前检查,已安装则跳过 --> <Condition Message=".NET Framework 4.8 已安装,无需重复操作。"> Installed OR NETFRAMEWORK48INSTALLED >= "#528040" </Condition>
2. 优化自定义动作的执行方式
- 将.NET安装包嵌入到MSI的Binary元素中,避免部署到Program Files
- 修改自定义动作的返回值为
check,以便捕获安装失败 - 调整执行条件,仅在未安装.NET时触发:
<!-- 嵌入.NET安装包到MSI中 --> <Binary Id="NetFx48Exe" SourceFile="ndp48-x86-x64-allos-enu.exe" /> <CustomAction Id="DotNetFX48Install" BinaryKey="NetFx48Exe" ExeCommand="/q /norestart" Execute="deferred" Impersonate="no" Return="check" /> <InstallExecuteSequence> <Custom Action="DotNetFX48Install" After="InstallFiles"> NOT Installed AND NOT (NETFRAMEWORK48INSTALLED >= "#528040") </Custom> <ScheduleReboot After="InstallFinalize"/> </InstallExecuteSequence>
注意:
即使做了以上修改,仍可能因为Windows Installer的全局互斥锁机制触发报错,因此仅建议作为临时应急方案,长期来看还是推荐使用Burn引导程序。
内容的提问来源于stack exchange,提问作者naveen
相关产品推荐
相关产品推荐

