WiX中调用带参数C#延迟CustomAction执行SQL安装失败求助
针对Wix延迟C# CustomAction调用SQL Setup失败的解决方案
兄弟,你遇到的这个Windows Host Process (Rundll32)已停止错误,结合你的环境(Wix3.10、VS2010、Win7 x64)和SQL Server安装的高权限需求,大概率是权限配置、x86/x64兼容性或者CustomAction参数传递的问题,我给你梳理几个核心排查方向:
1. 先把延迟CustomAction的权限配置拉满
SQL Server Setup需要系统级权限,延迟动作必须关掉模拟才能拿到系统上下文,这是最容易忽略的点:
- 你的CustomAction定义必须同时加
Impersonate="no"和Execute="deferred",还要加Return="check"才能捕获错误,不然失败了都不知道为啥:
<CustomAction Id="InstallSQLInstance" BinaryKey="SQLCustomActions" DllEntry="InstallSQL" Execute="deferred" Impersonate="no" Return="check" />
- 另外,延迟动作不能直接访问Session会话属性!如果要传参数(比如SQL Setup的路径、固定参数),必须通过
CustomActionData传递,比如:
<Property Id="InstallSQLInstance" Value="/SQLPath=[SQLSETUPPATH] /Args=/q /ACTION=Install /INSTANCENAME=MyInstance" />
然后在C#代码里通过session.CustomActionData["SQLPath"]来取参数,别直接用session["SQLSETUPPATH"],延迟动作里根本拿不到这个。
2. 解决x86/x64的兼容性冲突
Wix3.10默认可能把CustomAction编译成x86的,在x64系统上跑肯定出问题:
- 把你的C# CustomAction项目的平台目标改成x64(VS2010里右键项目→属性→生成→平台目标选x64)
- 对应的WXS里的Binary元素要指定
Platform="x64",确保加载的是64位的CA.dll:
<Binary Id="SQLCustomActions" SourceFile="..\SQLCustomActions\bin\x64\Release\SQLCustomActions.CA.dll" Platform="x64" />
- 你的MSI项目也要设置成x64平台,别搞成32位MSI调用64位动作的乌龙。
3. 调试延迟动作的正确姿势
延迟动作跑在系统上下文里,普通VS调试没法直接附加,教你两个办法抓错误:
- 在C#代码的开头加一行
System.Diagnostics.Debugger.Launch();,这样执行到CustomAction的时候会弹出调试器选择框,你选VS2010就能直接调试,能看到JIT之前的具体异常 - 去Windows事件查看器的应用程序日志里找崩溃记录,里面会有Rundll32崩溃的详细原因(比如缺依赖、未处理的异常)
- 还要检查C#项目引用的
Microsoft.Deployment.WindowsInstaller版本和Wix3.10的版本是否一致,版本不匹配也会导致莫名其妙的崩溃。
4. 调用SQL Setup.exe的细节要注意
直接调用Setup.exe的时候,进程启动方式要对:
- 在C#里用
Process.Start()时,必须设UseShellExecute=false,还要指定WorkingDirectory为Setup.exe的所在路径,不然可能找不到依赖文件:
var setupPath = session.CustomActionData["SQLPath"]; var args = session.CustomActionData["Args"]; var startInfo = new ProcessStartInfo { FileName = setupPath, Arguments = args, UseShellExecute = false, WorkingDirectory = Path.GetDirectoryName(setupPath), CreateNoWindow = true, Verb = "runas" // 虽然延迟动作已经是系统权限,但加上更稳妥 }; using (var process = Process.Start(startInfo)) { process.WaitForExit(); if (process.ExitCode != 0) { throw new InstallException($"SQL安装失败,退出码:{process.ExitCode}"); } }
- 所有路径都用绝对路径,别用相对路径,延迟动作的工作目录不一定是你想的那个。
最后,检查你的InstallExecuteSequence调度,确保CustomAction放在合适的位置,比如要先把SQL Setup文件复制到目标路径再执行,所以放在InstallFiles之后:
<InstallExecuteSequence> <Custom Action="InstallSQLInstance" After="InstallFiles">NOT Installed</Custom> </InstallExecuteSequence>
内容的提问来源于stack exchange,提问作者illuminate33
相关产品推荐
相关产品推荐

