visual-studio - msi安装后运行exe吗?

标签 visual-studio visual-studio-2008 windows-installer setup-project custom-action

使用 Visual Studio 2008 创建一个 msi,通过安装项目来部署我的程序。我需要知道如何让 msi 运行刚刚安装的 exe。自定义 Action ?如果是这样,请解释在哪里/如何。谢谢。

最佳答案

这是一个常见问题。我不只是使用自定义操作来完成此操作。我知道的唯一方法是在生成 .msi 后对其进行修改。我运行一个 Javascript 脚本作为构建后事件来做到这一点。它会在安装程序向导中插入一个新对话框,其中有一个复选框显示“启动应用程序 Foo?”。然后,如果选中该复选框,就会有一个自定义操作来运行应用程序。

它显示为安装向导序列中的最后一个屏幕。看起来像这样:

alt text

<小时/>

这是我用来修改 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);
}

我最初是从 Aaron Stebner's blog 得到这个的,然后修改它。

将该 Javascript 文件保存到项目目录(与包含 .vdproj 的目录相同),将其命名为 ModifyMsiToEnableLaunchApplication.js 。对于每个独特的安装项目,您需要修改该脚本并将正确的 exe 名称放入其中。然后,您需要在安装项目中将构建后事件设置为:

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

请务必正确键入宏的名称 $(BuiltOuputPath)。 Microsoft 将 Ouput 一词拼写错误,而 Built 未拼写为 Build!

应该这样做。

另请参阅:this modification其中不包括卸载时的“运行 Foo.exe”复选框。

关于visual-studio - msi安装后运行exe吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1668274/

相关文章:

c# - TFS:分割大型源代码文件而不丢失版本历史记录

visual-studio - VS 2010 Server Explorer数据库未显示表

c++ - STL 的自定义分配器仅在 Release模式下无法编译

wix - 将 WiX 安装集升级到同一文件夹

windows - MSI 上下文中的 LUA 是什么?

visual-studio - Visual Studio 2017 安装卡在 Microsoft.VisualStudio.AspNet45.Feature

c# - Xamarin Entry 底线颜色不变

c++ - 使用继承在 C++ 中调用析构函数和销毁成员变量的顺序是什么?

visual-studio-2008 - 在没有 Microsoft Visual Studio 测试版/Team Suite 的情况下运行 Web 测试

wix - 如果WiX中不存在,则复制