You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让MSI安装完成后启动多个EXE?无需多按钮/控件方案

MSI安装完成后启动多个EXE的问题

已有成熟方案让MSI在安装结束时启动单个EXE:开发者创建Javascript文件,作为生成MSI的.vdproj项目的POST-BUILD-EVENT由Visual Studio执行,脚本会修改.vdproj生成的MSI。

微软文档提到:"用于对绑定到同一控件的多个事件进行排序的整数,必须为非负数,该字段可留空",这意味着安装最终对话框中的单个控件可触发多个事件。

我据此修改代码,试图启动两个EXE,但始终只有第二个EXE被启动。希望实现无需两个按钮即可启动两个EXE,甚至能否不使用任何控件来启动EXE?

相关代码

WScript.Echo("Inserting events to launch the applications...");
// Insert the Event to launch the application
sql = "INSERT INTO `ControlEvent` (`Dialog_`, `Control_`, `Event`, `Argument`, `Condition`, `Ordering`) VALUES ('FinishedForm', 'CloseButton', 'DoAction', 'VSDCA_Launch0', 'LAUNCHAPPS=1', '0')";
sql = "INSERT INTO `ControlEvent` (`Dialog_`, `Control_`, `Event`, `Argument`, `Condition`, `Ordering`) VALUES ('FinishedForm', 'CloseButton', 'DoAction', 'VSDCA_Launch1', 'LAUNCHAPPS=1', '1')";

view = database.OpenView(sql);
view.Execute();
view.Close();



WScript.Echo("Updating the CustomAction table...");
// Insert the custom actions to launch the applications when finished
sql = "INSERT INTO `CustomAction` (`Action`, `Type`, `Source`, `Target`) VALUES ('VSDCA_Launch0', '210', '" + fileId1 + "', '')";
sql = "INSERT INTO `CustomAction` (`Action`, `Type`, `Source`, `Target`) VALUES ('VSDCA_Launch1', '210', '" + fileId2 + "', '')";
view = database.OpenView(sql);
view.Execute();
view.Close();

日志信息(仅执行了第二个EXE)

我原本期望能启动两个EXE,以下是相关日志内容:

    MSI (c) (1C:E8) [08:49:24:280]: 执行动作: FinishedForm
    动作 8:49:24: FinishedForm. 
    动作开始 8:49:24: FinishedForm.
    MSI (c) (1C:E8) [08:49:24:280]: 注意: 1: 2235 2:  3: ExtendedType 4: SELECT `Action`,`Type`,`Source`,`Target`, NULL, `ExtendedType` FROM `CustomAction` WHERE `Action` = 'FinishedForm' 
    MSI (c) (1C:84) [08:49:24:280]: 注意: 1: 2262 2: Error 3: -2147287038 
    DEBUG: 错误 2826:  对话框 FinishedForm 上的控件 Line1 向右超出对话框边界 3 像素
    安装程序在安装此软件包时遇到意外错误。这可能表明此软件包存在问题。错误代码是 2826。参数为: FinishedForm, Line1, to the right
    MSI (c) (1C:84) [08:49:24:280]: 注意: 1: 2262 2: Error 3: -2147287038 
    DEBUG: 错误 2826:  对话框 FinishedForm 上的控件 Line2 向右超出对话框边界 3 像素
    安装程序在安装此软件包时遇到意外错误。这可能表明此软件包存在问题。错误代码是 2826。参数为: FinishedForm, Line2, to the right
    MSI (c) (1C:84) [08:49:24:296]: 注意: 1: 2262 2: Error 3: -2147287038 
    DEBUG: 错误 2826:  对话框 FinishedForm 上的控件 BannerBmp 向右超出对话框边界 3 像素
    安装程序在安装此软件包时遇到意外错误。这可能表明此软件包存在问题。错误代码是 2826。参数为: FinishedForm, BannerBmp, to the right
    MSI (c) (1C:84) [08:49:24:296]: 注意: 1: 2262 2: CheckBox 3: -2147287038 
    动作 8:49:24: FinishedForm. 创建对话框
    MSI (c) (1C:84) [08:49:28:499]: 执行动作: VSDCA_Launch1
    动作 8:49:28: VSDCA_Launch1. 
    动作开始 8:49:28: VSDCA_Launch1.
    MSI (c) (1C:84) [08:49:28:499]: 注意: 1: 2235 2:  3: ExtendedType 4: SELECT `Action`,`Type`,`Source`,`Target`, NULL, `ExtendedType` FROM `CustomAction` WHERE `Action` = 'VSDCA_Launch1' 
    动作结束 8:49:28: FinishedForm. 返回值 1.
    动作结束 8:49:28: INSTALL. 返回值 1.
    动作结束 8:49:28: VSDCA_Launch1. 返回值 0.

问题分析与解决方案

为什么只执行了第二个EXE?

代码存在核心错误:每次赋值sql = "INSERT..."时,都会直接覆盖之前的sql变量,导致最终只有最后一条INSERT语句被执行。不管是ControlEvent表还是CustomAction表,都只插入了第二条记录,第一条被完全覆盖。

修复代码(实现单个按钮启动两个EXE)

需要分别执行每条INSERT语句,不能覆盖sql变量:

WScript.Echo("Inserting events to launch the applications...");
// 插入第一个启动事件
sql = "INSERT INTO `ControlEvent` (`Dialog_`, `Control_`, `Event`, `Argument`, `Condition`, `Ordering`) VALUES ('FinishedForm', 'CloseButton', 'DoAction', 'VSDCA_Launch0', 'LAUNCHAPPS=1', '0')";
view = database.OpenView(sql);
view.Execute();
view.Close();

// 插入第二个启动事件
sql = "INSERT INTO `ControlEvent` (`Dialog_`, `Control_`, `Event`, `Argument`, `Condition`, `Ordering`) VALUES ('FinishedForm', 'CloseButton', 'DoAction', 'VSDCA_Launch1', 'LAUNCHAPPS=1', '1')";
view = database.OpenView(sql);
view.Execute();
view.Close();

WScript.Echo("Updating the CustomAction table...");
// 插入第一个自定义动作
sql = "INSERT INTO `CustomAction` (`Action`, `Type`, `Source`, `Target`) VALUES ('VSDCA_Launch0', '210', '" + fileId1 + "', '')";
view = database.OpenView(sql);
view.Execute();
view.Close();

// 插入第二个自定义动作
sql = "INSERT INTO `CustomAction` (`Action`, `Type`, `Source`, `Target`) VALUES ('VSDCA_Launch1', '210', '" + fileId2 + "', '')";
view = database.OpenView(sql);
view.Execute();
view.Close();

无需控件启动EXE的方案

如果不想依赖对话框控件触发,可以直接将自定义动作绑定到安装序列的末尾,在InstallFinalize之后执行:

  1. 确保自定义动作类型为210(同步执行,需等待程序退出)或3090(异步执行,适合启动外部程序,不阻塞安装流程)
  2. 将自定义动作添加到InstallExecuteSequence表中,设置在InstallFinalize之后执行:
// 为VSDCA_Launch0添加序列
sql = "INSERT INTO `InstallExecuteSequence` (`Action`, `Condition`, `Sequence`) VALUES ('VSDCA_Launch0', 'LAUNCHAPPS=1', 6601)";
view = database.OpenView(sql);
view.Execute();
view.Close();

// 为VSDCA_Launch1添加序列
sql = "INSERT INTO `InstallExecuteSequence` (`Action`, `Condition`, `Sequence`) VALUES ('VSDCA_Launch1', 'LAUNCHAPPS=1', 6602)";
view = database.OpenView(sql);
view.Execute();
view.Close();

注:InstallFinalize的默认序列值是6600,设置为6601和6602可确保在安装完成后执行。推荐使用3090类型,避免因启动的程序未退出导致安装流程阻塞。


内容的提问来源于stack exchange,提问作者HackTheStack

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 04:11:07