如何用WiX安装含System.Configuration.Install.Installer的.NET程序集
刚好之前帮同事处理过几乎一模一样的场景——依赖第三方SDK的插件,自带System.Configuration.Install.Installer实现,又不能改SDK代码,还得避开WiX不推荐的InstallUtil.exe。给你两个最靠谱的方案,都是社区和WiX官方认可的:
方案一:用DTF托管自定义操作直接调用Installer逻辑
这是最推荐的方式,既不用调用外部工具,又能100%复用SDK的安装逻辑,完全符合WiX的最佳实践。
步骤1:创建DTF自定义操作项目
在你的解决方案里添加一个WiX Toolset Managed Custom Action Project(这是WiX自带的DTF项目模板,专门用来写托管自定义操作)。
步骤2:编写自定义操作代码
直接在代码里加载插件程序集,找到SDK定义的安装类子类,调用它的Install/Uninstall方法。示例代码如下:
using System; using System.Collections; using System.Configuration.Install; using System.Linq; using System.Reflection; using Microsoft.Deployment.WindowsInstaller; public class PluginInstallActions { [CustomAction] public static ActionResult InstallPlugin(Session session) { try { // 从WiX属性获取插件安装路径(提前在WiX里定义好INSTALLFOLDER属性) string pluginPath = $"{session["INSTALLFOLDER"]}YourPluginAssembly.dll"; session.Log($"Loading plugin assembly from: {pluginPath}"); // 加载插件程序集 Assembly pluginAssembly = Assembly.LoadFrom(pluginPath); // 找到继承自SDK安装类的Installer实现(替换成你的SDK基类名) var installerType = pluginAssembly.GetTypes() .First(t => typeof(YourSDKBaseInstaller).IsAssignableFrom(t) && !t.IsAbstract); // 实例化并执行安装 using (Installer installer = (Installer)Activator.CreateInstance(installerType)) { installer.Context = new InstallContext(null, new string[] { }); installer.Install(new Hashtable()); session.Log("Plugin installation completed successfully"); } return ActionResult.Success; } catch (Exception ex) { session.Log($"Error installing plugin: {ex.Message}\n{ex.StackTrace}"); return ActionResult.Failure; } } [CustomAction] public static ActionResult UninstallPlugin(Session session) { try { string pluginPath = $"{session["INSTALLFOLDER"]}YourPluginAssembly.dll"; session.Log($"Loading plugin assembly for uninstall: {pluginPath}"); Assembly pluginAssembly = Assembly.LoadFrom(pluginPath); var installerType = pluginAssembly.GetTypes() .First(t => typeof(YourSDKBaseInstaller).IsAssignableFrom(t) && !t.IsAbstract); using (Installer installer = (Installer)Activator.CreateInstance(installerType)) { installer.Context = new InstallContext(null, new string[] { }); installer.Uninstall(null); session.Log("Plugin uninstallation completed successfully"); } return ActionResult.Success; } catch (Exception ex) { session.Log($"Error uninstalling plugin: {ex.Message}\n{ex.StackTrace}"); return ActionResult.Failure; } } }
步骤3:在WiX项目里引用并配置自定义操作
编译自定义操作项目后,把生成的.CA.dll文件添加到WiX项目中,然后在WiX源文件里配置:
<!-- 引用自定义操作DLL --> <Binary Id="PluginInstallCA" SourceFile="$(var.PluginInstallActions.TargetDir)PluginInstallActions.CA.dll" /> <!-- 定义安装自定义操作:必须用deferred模式,因为要等文件安装完成后才能加载插件 --> <CustomAction Id="ExecutePluginInstall" BinaryKey="PluginInstallCA" DllEntry="InstallPlugin" Execute="deferred" Impersonate="no" Return="check" /> <!-- 定义卸载自定义操作 --> <CustomAction Id="ExecutePluginUninstall" BinaryKey="PluginInstallCA" DllEntry="UninstallPlugin" Execute="deferred" Impersonate="no" Return="check" /> <!-- 把自定义操作加入安装序列 --> <InstallExecuteSequence> <!-- 安装:在文件安装完成后执行 --> <Custom Action="ExecutePluginInstall" After="InstallFiles">NOT Installed</Custom> <!-- 卸载:在文件删除前执行 --> <Custom Action="ExecutePluginUninstall" Before="RemoveFiles">REMOVE="ALL"</Custom> </InstallExecuteSequence>
关键注意事项
- 执行模式:必须用
Execute="deferred",因为只有文件安装到目标目录后,才能加载插件程序集;同时deferred模式下自定义操作会以管理员权限运行(如果MSI是elevated启动的),避免权限不足。 - 权限设置:
Impersonate="no"确保自定义操作以系统权限执行,符合安装程序的权限要求。 - 日志记录:一定要用
session.Log()记录关键步骤和错误信息,WiX安装日志里会显示这些内容,方便排查问题。 - 异常处理:必须捕获所有异常并返回
ActionResult.Failure,否则MSI会静默失败,难以定位问题。
内容的提问来源于stack exchange,提问作者Hydrargyrum
相关产品推荐
相关产品推荐

