如何为C++编写的Wix自定义动作DLL打包vcruntime140.dll?
解决Wix自定义动作依赖vcruntime140.dll的安装失败问题
你遇到的问题核心是:自定义动作DLL执行时需要vcruntime140.dll,但纯净系统中没有该文件,而直接用<Binary>元素添加会导致文件名被MSI重命名,无法被正确加载。下面是几种靠谱的解决方式:
方法一:用Burn引导程序安装VC++官方运行时包(推荐)
微软官方推荐通过VC++ Redistributable包部署运行时依赖,你可以用Wix的Burn工具创建一个引导程序,先安装VC++运行时,再执行你的MSI包:
- 下载对应位数的VC++ Redistributable安装包(比如vc_redist.x64.exe,对应64位系统);
- 创建Wix Bootstrapper项目,配置链式安装:
<Bundle Name="你的安装包名称" Version="1.0.0.0" Manufacturer="你的厂商名" UpgradeCode="生成一个唯一GUID"> <BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLicense" /> <!-- 引入VC++运行时包 --> <Chain> <PackageGroupRef Id="VCRedist" /> <MsiPackage SourceFile="path\to\你的MSI文件.msi" /> </Chain> </Bundle> <!-- 定义VC++运行时包的引用 --> <Fragment> <PackageGroup Id="VCRedist"> <ExePackage SourceFile="vc_redist.x64.exe" InstallCommand="/quiet /norestart" RepairCommand="/quiet /norestart" UninstallCommand="/uninstall /quiet /norestart" PerMachine="yes" DetectCondition="VCRedistInstalled" Vital="yes" /> </PackageGroup> <!-- 检测VC++运行时是否已安装的条件 --> <util:RegistrySearch Id="VCRedistSearch" Root="HKLM" Key="SOFTWARE\Microsoft\VisualStudio\14.0\VC\Runtimes\x64" Value="Version" Variable="VCRedistInstalled" /> </Fragment>
这种方式能确保系统先安装好完整的VC++运行时,从根源上解决依赖问题,还能自动处理后续的运行时更新。
方法二:将vcruntime140.dll安装到系统目录
如果不想用引导程序,可以把vcruntime140.dll作为普通文件安装到系统目录(比如System32),这样自定义动作执行时就能找到它:
- 在Wix的目录结构中添加System32目录的组件:
<Directory Id="TARGETDIR" Name="SourceDir"> <Directory Id="ProgramFilesFolder" Name="PFiles" /> <Directory Id="SystemFolder" Name="System32" /> </Directory> <Feature Id="MainFeature" Title="主功能" Level="1"> <!-- 你的其他组件 --> <ComponentRef Id="VCRuntimeComponent" /> </Feature> <Component Id="VCRuntimeComponent" Guid="生成一个新的GUID" Directory="SystemFolder"> <File Id="VCRuntimeFile" Source="path\to\vcruntime140.dll" KeyPath="yes" /> </Component>
- 注意:要匹配DLL的位数——如果你的MSI是64位,
SystemFolder会指向C:\Windows\System32;如果是32位MSI,则指向C:\Windows\SysWOW64,必须对应正确的vcruntime140.dll版本。
方法三:静态链接VC++运行时(不推荐)
在编译自定义动作DLL时,将VC++运行库设置为静态链接:
- 打开你的C++项目属性;
- 转到
C/C++ -> 代码生成 -> 运行库,选择多线程(/MT)(Release版本)或多线程调试(/MTd)(Debug版本); - 重新编译DLL。
这样vcruntime的代码会被直接编译进你的DLL中,不再依赖外部文件。但这种方式会增大DLL体积,且无法自动获取微软发布的运行时安全补丁,所以仅适合特殊场景。
为什么直接用<Binary>元素不行?
Wix的<Binary>元素会把文件嵌入MSI的Binary表,安装时会被提取到临时目录,但MSI会自动重命名这些文件(比如改成类似randomname.tmp的名称),导致你的自定义动作DLL无法找到名为vcruntime140.dll的依赖文件,自然加载失败。
内容的提问来源于stack exchange,提问作者Acewind
相关产品推荐
相关产品推荐

