Visual Studio Installer > How To Launch App at End of Installer

前端 未结 6 914
再見小時候
再見小時候 2020-11-29 17:59

This is probably a stupid question and my Googling just is not functioning today.

I have an application I added a Visual Studio Installer > Setup Wizard project to.

6条回答
  •  渐次进展
    2020-11-29 18:09

    The solution from https://blogs.msdn.microsoft.com/astebner/2006/08/12/mailbag-how-can-i-customize-an-msi-in-the-visual-studio-setupdeployment-project/ adds a checkbox at the end of the setup to choose if you want to start the application or not. You can modify the script to be checked by default...or even hide it.

    The big advantage here is, that the application won't run with elevated rights like Maurice Flanagan mentioned.

    The required script you need is:

    // EnableLaaunchApplication.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 = "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();
    
        // Resize the BodyText and BodyTextRemove controls to be reasonable
        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) = 33;
        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`='BodyText'";
        view = database.OpenView(sql);
        view.Execute();
        record = view.Fetch();
        record.IntegerData(7) = 33;
        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', '18', '117', '343', '12', '3', 'LAUNCHAPP', '{\\VSI_MS_Sans_Serif13.0_0_0}" + checkboxText + "', 'Line1', '|')";
        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)
    {
        var sql
        var view
        var record
    
        // First, try to find the exact file name
        sql = "SELECT `File` FROM `File` WHERE `FileName`='" + fileName + "'";
        view = database.OpenView(sql);
        view.Execute();
        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);
    }
    

    Edit the file to show your desired name and the name of the executable, put that file beside your .vdproj Setup project and in the postbuild add following line:

    CALL cscript.exe "$(ProjectDir)EnableLaunchApplication.js" "$(BuiltOuputPath)"

提交回复
热议问题