MSI安装后运行exe文件?MSI安装后运行exe文件?(Run exe after msi ins

2019-05-08 15:16发布

使用Visual Studio 2008创建一个MSI部署我有一个安装项目计划。 我需要知道如何让微星运行刚刚安装的exe文件。 自定义操作? 如果有,请说明在何处/如何。 谢谢。

Answer 1:

这是一个常见的问题。 我不只是一个自定义操作做到这一点。 我所知道的唯一途径,是已经生成后以修改.msi。 我运行JavaScript脚本作为生成后事件做到这一点。 它插入在安装向导中一个新的对话框有一个复选框,上面写着“启动应用程序富?”。 再有就是自定义操作来运行应用程序,如果该复选框被选中。

它表现为在安装向导程序的最后一个屏幕。 是这样的:


这是我用修改MSI脚本:

// EnableLaunchApplication.js <msi-file>
// Performs a post-build fixup of an msi to launch a specific file when the install has completed

// Configurable values
var checkboxChecked = true;                     // Is the checkbox on the finished dialog checked by default?
var checkboxText = "Launch [ProductName]";      // Text for the checkbox on the finished dialog
var filename = "WindowsApplication1.exe";       // The name of the executable to launch - change this to match the file you want to launch at the end of your setup

// Constant values from Windows Installer
var msiOpenDatabaseModeTransact = 1;

var msiViewModifyInsert         = 1;
var msiViewModifyUpdate         = 2;
var msiViewModifyAssign         = 3;
var msiViewModifyReplace        = 4;
var msiViewModifyDelete         = 6;

if (WScript.Arguments.Length != 1)
{
        WScript.StdErr.WriteLine(WScript.ScriptName + " file");
        WScript.Quit(1);
}

var filespec = WScript.Arguments(0);
var installer = WScript.CreateObject("WindowsInstaller.Installer");
var database = installer.OpenDatabase(filespec, msiOpenDatabaseModeTransact);

var sql;
var view;
var record;

try
{
        var fileId = FindFileIdentifier(database, filename);
        if (!fileId)
                throw "Unable to find '" + filename + "' in File table";

        WScript.Echo("Updating the Control table...");
        // Modify the Control_Next of BannerBmp control to point to the new CheckBox
        sql = "SELECT `Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, `Attributes`, `Property`, `Text`, `Control_Next`, `Help` FROM `Control` WHERE `Dialog_`='FinishedForm' AND `Control`='BannerBmp'";
        view = database.OpenView(sql);
        view.Execute();
        record = view.Fetch();
        record.StringData(11) = "CheckboxLaunch";
        view.Modify(msiViewModifyReplace, record);
        view.Close();

        // Insert the new CheckBox control
        sql = "INSERT INTO `Control` (`Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, `Attributes`, `Property`, `Text`, `Control_Next`, `Help`) VALUES ('FinishedForm', 'CheckboxLaunch', 'CheckBox', '9', '201', '343', '12', '3', 'LAUNCHAPP', '{\\VSI_MS_Sans_Serif13.0_0_0}" + checkboxText + "', 'CloseButton', '|')";
        view = database.OpenView(sql);
        view.Execute();
        view.Close();

        WScript.Echo("Updating the ControlEvent table...");
        // Modify the Order of the EndDialog event of the FinishedForm to 1
        sql = "SELECT `Dialog_`, `Control_`, `Event`, `Argument`, `Condition`, `Ordering` FROM `ControlEvent` WHERE `Dialog_`='FinishedForm' AND `Event`='EndDialog'";
        view = database.OpenView(sql);
        view.Execute();
        record = view.Fetch();
        record.IntegerData(6) = 1;
        view.Modify(msiViewModifyReplace, record);
        view.Close();

        // Insert the Event to launch the application
        sql = "INSERT INTO `ControlEvent` (`Dialog_`, `Control_`, `Event`, `Argument`, `Condition`, `Ordering`) VALUES ('FinishedForm', 'CloseButton', 'DoAction', 'VSDCA_Launch', 'LAUNCHAPP=1', '0')";
        view = database.OpenView(sql);
        view.Execute();
        view.Close();

        WScript.Echo("Updating the CustomAction table...");
        // Insert the custom action to launch the application when finished
        sql = "INSERT INTO `CustomAction` (`Action`, `Type`, `Source`, `Target`) VALUES ('VSDCA_Launch', '210', '" + fileId + "', '')";
        view = database.OpenView(sql);
        view.Execute();
        view.Close();

        if (checkboxChecked)
        {
                WScript.Echo("Updating the Property table...");
                // Set the default value of the CheckBox
                sql = "INSERT INTO `Property` (`Property`, `Value`) VALUES ('LAUNCHAPP', '1')";
                view = database.OpenView(sql);
                view.Execute();
                view.Close();
        }

        database.Commit();
}
catch(e)
{
        WScript.StdErr.WriteLine(e);
        WScript.Quit(1);
}

function FindFileIdentifier(database, fileName)
{
        // First, try to find the exact file name
        var sql = "SELECT `File` FROM `File` WHERE `FileName`='" + fileName + "'";
        var view = database.OpenView(sql);
        view.Execute();
        var record = view.Fetch();
        if (record)
        {
                var value = record.StringData(1);
                view.Close();
                return value;
        }
        view.Close();

        // The file may be in SFN|LFN format.  Look for a filename in this case next
        sql = "SELECT `File`, `FileName` FROM `File`";
        view = database.OpenView(sql);
        view.Execute();
        record = view.Fetch();
        while (record)
        {
                if (StringEndsWith(record.StringData(2), "|" + fileName))
                {
                        var value = record.StringData(1);
                        view.Close();
                        return value;
                }

                record = view.Fetch();
        }
        view.Close();
}

function StringEndsWith(str, value)
{
        if (str.length < value.length)
                return false;

        return (str.indexOf(value, str.length - value.length) != -1);
}

我最初得到这个从亚伦Stebner的博客 ,然后修改它。

保存javascript文件到项目目录(同一目录作为包含.vdproj),将其命名为ModifyMsiToEnableLaunchApplication.js 。 对于每一个独特的设置项目,您需要修改脚本,并把正确的exe文件名到它。 然后,你需要在安装项目是这个设置生成后事件:

cscript.exe "$(ProjectDir)ModifyMsiToEnableLaunchApplication.js" "$(BuiltOuputPath)"

一定要输入宏的名称$(BuiltOuputPath)正确。 Ouput是由微软拼写错误,并Built不拼Build

这oughtta做到这一点。

另见 : 这个修改不包括上卸载“运行foo.exe的”复选框。



Answer 2:

这似乎是一个更简单的解决方案: Visual Studio安装>如何在安装程序结束时启动应用程序



Answer 3:

好!!! 下面是代码(没有2个辅助功能到底“FindFileIdentifier”和“StringEndsWith” - 使用原有的代替),其给予我们改变Ys和高地控制,与添加复选框控件能见度条件沿能力(见注释2中标记之间的 '新 - START' 至 'NEW - END'):


// EnableLaunchApplication.js 
// Performs a post-build fixup of an msi to launch a specific file when the install has completed


// Configurable values
var checkboxChecked = true;                     // Is the checkbox on the finished dialog checked by default?
var checkboxText = "Launch [ProductName]?";     // Text for the checkbox on the finished dialog
var filename = "*.exe";                     // The name of the executable to launch - change * to match the file name you want to launch at the end of your setup


// Constant values from Windows Installer
var msiOpenDatabaseModeTransact = 1;

var msiViewModifyInsert         = 1
var msiViewModifyUpdate         = 2
var msiViewModifyAssign         = 3
var msiViewModifyReplace        = 4
var msiViewModifyDelete         = 6



if (WScript.Arguments.Length != 1)
{
        WScript.StdErr.WriteLine(WScript.ScriptName + " file");
        WScript.Quit(1);
}

var filespec = WScript.Arguments(0);
var installer = WScript.CreateObject("WindowsInstaller.Installer");
var database = installer.OpenDatabase(filespec, msiOpenDatabaseModeTransact);

var sql
var view
var record

try
{
        var fileId = FindFileIdentifier(database, filename);
        if (!fileId)
                throw "Unable to find '" + filename + "' in File table";


        WScript.Echo("Updating the Control table...");
        // Modify the Control_Next of BannerBmp control to point to the new CheckBox
        sql = "SELECT `Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, `Attributes`, `Property`, `Text`, `Control_Next`, `Help` FROM `Control` WHERE `Dialog_`='FinishedForm' AND `Control`='BannerBmp'";
        view = database.OpenView(sql);
        view.Execute();
        record = view.Fetch();
        record.StringData(11) = "CheckboxLaunch";
        view.Modify(msiViewModifyReplace, record);
        view.Close();

        // NEW - START
        // Insert the new CheckBox control
        // I changed the value for Y below from 201 to 191 in order to make the checkbox more obvious to the user's eye. In order to do so, and avoid the controls 'BodyText' & 'BodyTextRemove' in the same form to
        // overlap the checkbox, I added yet 2 more sql statements that change the values of the heights for the 'BodyText' & 'BodyTextRemove' from 138 to 128. This way I can play around with the values without using
        // the Orca msi editor.
        var CheckBoxY = 191; //This was initially set to 201
        var NewHeight = 128; //This was initially set to 138
        sql = "INSERT INTO `Control` (`Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, `Attributes`, `Property`, `Text`, `Control_Next`, `Help`) VALUES ('FinishedForm', 'CheckboxLaunch', 'CheckBox', '9', '" + CheckBoxY + "', '343', '12', '3', 'LAUNCHAPP', '{\\VSI_MS_Sans_Serif13.0_0_0}" + checkboxText + "', 'CloseButton', '|')";
        view = database.OpenView(sql);
        view.Execute();
        view.Close();

        sql = "Select `Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, `Attributes`, `Property`, `Text`, `Control_Next`, `Help` FROM `Control` WHERE `Dialog_` = 'FinishedForm' AND `Control` = 'BodyText'";
        view = database.OpenView(sql);
        view.Execute();
        record = view.Fetch();
        record.IntegerData(7) = NewHeight;
        view.Modify(msiViewModifyReplace, record);
        view.Close();

        sql = "Select `Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, `Attributes`, `Property`, `Text`, `Control_Next`, `Help` FROM `Control` WHERE `Dialog_` = 'FinishedForm' AND `Control` = 'BodyTextRemove'";
        view = database.OpenView(sql);
        view.Execute();
        record = view.Fetch();
        record.IntegerData(7) = NewHeight;
        view.Modify(msiViewModifyReplace, record);
        view.Close();
        // NEW - END

        WScript.Echo("Updating the ControlEvent table...");
        // Modify the Order of the EndDialog event of the FinishedForm to 1
        sql = "SELECT `Dialog_`, `Control_`, `Event`, `Argument`, `Condition`, `Ordering` FROM `ControlEvent` WHERE `Dialog_`='FinishedForm' AND `Event`='EndDialog'";
        view = database.OpenView(sql);
        view.Execute();
        record = view.Fetch();
        record.IntegerData(6) = 1;
        view.Modify(msiViewModifyReplace, record);
        view.Close();

        // Insert the Event to launch the application
        sql = "INSERT INTO `ControlEvent` (`Dialog_`, `Control_`, `Event`, `Argument`, `Condition`, `Ordering`) VALUES ('FinishedForm', 'CloseButton', 'DoAction', 'VSDCA_Launch', 'LAUNCHAPP=1', '0')";
        view = database.OpenView(sql);
        view.Execute();
        view.Close();



        WScript.Echo("Updating the CustomAction table...");
        // Insert the custom action to launch the application when finished
        sql = "INSERT INTO `CustomAction` (`Action`, `Type`, `Source`, `Target`) VALUES ('VSDCA_Launch', '210', '" + fileId + "', '')";
        view = database.OpenView(sql);
        view.Execute();
        view.Close();

        if (checkboxChecked)
        {
                WScript.Echo("Updating the Property table...");
                // Set the default value of the CheckBox
                sql = "INSERT INTO `Property` (`Property`, `Value`) VALUES ('LAUNCHAPP', '1')";
                view = database.OpenView(sql);
                view.Execute();
                view.Close();
        }


        // NEW - START
        WScript.Echo("Updating the ControlCondition table...");
        // Insert the conditions where the Launch Application Checkbox appears
        sql = "INSERT INTO `ControlCondition` (`Dialog_`, `Control_`, `Action`, `Condition`) VALUES ('FinishedForm', 'CheckboxLaunch', 'Show', 'REMOVE=\"\"')";
        view = database.OpenView(sql);
        view.Execute();
        view.Close();

        sql = "INSERT INTO `ControlCondition` (`Dialog_`, `Control_`, `Action`, `Condition`) VALUES ('FinishedForm', 'CheckboxLaunch', 'Hide', 'REMOVE<>\"\"')";
        view = database.OpenView(sql);
        view.Execute();
        view.Close();
        //NEW - END


        database.Commit();
}
catch(e)
{
        WScript.StdErr.WriteLine(e);
        WScript.Quit(1);
}


Answer 4:

关于“隐藏复选框虫”我想通了,这是不被Cheeso的以上Muleskinner的回答解释如下:

脚本的变化(由Muleskinner提供)放置的复选框201的Y位置(我想用于控制顶部的Y象素)。 如果你修改y,比方说,151(以一种对齐在中心上下),“突然”出现的错误。 其理由是,有在MSI的控制表中的另一个控制,即“BODYTEXT”(“对话框”字段=“FinishedForm”),其它的Y设置为63并且其高度,以138即138 + 63 = 201.因此,如果您更改Y值的复选框,在“BODYTEXT”控制重叠新添加的控制,这就是为什么用户需要把他们的鼠标,以显示复选框。 如果你没有“BODYTEXT”或它的字符数足够,你可以改变小(通过使用逆戟鲸MSI编辑和我一样,或通过改变上面的脚本)的Ys和这两个控件的高度,以便能够和容纳不同的Y位置为新添加的复选框。 这同样适用于控制:“BodyTextRemove”,其中再次,我们应该改变其高度值(卸载过程中出现)

希望这可以帮助所有有同样的问题,因为我有这个“错误”的用户

尽管如此,该脚本将切实做好!

另一个问题是如何在unistallation过程使无形的复选框。 使用Orca MSI编辑,我在MSI的ControlCondition资料表中增加了以下2行:

行1(当应该显示控制):

(对话框)FinishedForm(对照)CheckboxLaunch(作用)显示(状态)REMOVE = “”

行2(当控制应该是不可见的):

(对话框)FinishedForm(对照)CheckboxLaunch(动作)隐藏(条件)REMOVE <> “”

PS我使用VS 2010,在Windows 7(64位),但我相信这应该与以前的版本工作了。



Answer 5:

关于“PostBuildEvent”失败,错误码“1”“未指定的错误”的错误,改变从PostBuildEvent

cscript.exe \"$(ProjectDir)ModifyMsiToEnableLaunchApplication.js\" \"$(BuiltOuputPath)\"

cscript.exe "$(ProjectDir)ModifyMsiToEnableLaunchApplication.js" "$(BuiltOuputPath)"

至于隐藏复选框错误 ,您可以编辑54行的脚本成为:

sql = "INSERT INTO `Control` (`Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, `Attributes`, `Property`, `Text`, `Control_Next`, `Help`) VALUES ('FinishedForm', 'CheckboxLaunch', 'CheckBox', '9', '201', '343', '12', '3', 'LAUNCHAPP', '{\\VSI_MS_Sans_Serif13.0_0_0}" + checkboxText + "', 'CloseButton', '|')";


Answer 6:

是的..我会写一个自定义操作,并在InstallExecutionSequence表的末尾坚持下去



文章来源: Run exe after msi installation?