Run exe after msi installation?
G

8

55

Using Visual Studio 2008 to create an msi to deploy my program with a setup project. I need to know how to make the msi run the exe it just installed. A custom action? If so please explain where/how. Thanks.

Gardener answered 3/11, 2009 at 16:3 Comment(0)
B
80

This is a common question. I don't do it with just a custom action. The only way I know, is to modify the .msi after it has been generated. I run a Javascript script as a post-build event to do exactly that. It inserts a new dialog in the installer wizard, with a checkbox that says "Launch Application Foo?". And then there is a custom action to run the app, if the checkbox is checked.

It appears as the last screen in the install Wizard sequence. Looks like this:

alt text


This is the script I use to modify the 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);
}

I originally got this from Aaron Stebner's blog, and then modified it.

Save that Javascript file to the project directory (same dir as contains .vdproj), name it ModifyMsiToEnableLaunchApplication.js . For each unique setup project, you need to modify that script and put the proper exe name into it. And then, you need to set the post-build event in the Setup project to be this:

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

Be sure to type the name of the macro $(BuiltOuputPath) correctly. The word Ouput is misspelled by Microsoft, and Built is not spelled Build !

That oughtta do it.

See also: this modification which does not include the "run Foo.exe" checkbox on UNINSTALL.

Blakeblakelee answered 5/11, 2009 at 15:48 Comment(32)
like a little bit of magic. I don't know if MS added the capability into the setup project for VS2010. I think it's also possible to do this in WiX, but I've never used Wix, so this works for me.Blakeblakelee
If the interface is hidden (msi being pushed with silent install commands) will this still work?Gardener
Sure, it will still work. Just keep the checkboxChecked var as true in the script.Blakeblakelee
I'm getting an Error: 'PostBuildEvent' failed with error code '1' 'Unspecified error'Gardener
you have to look in the build output log, to discern the problem. First things to check: did you modify the name of the EXE at the top of the Javascript file? did you name the file properly and does the post-build event reference the proper name?Blakeblakelee
Not enough storage is available?Gardener
And yes I've named the file correctly and have modified it to the proper exe.Gardener
@Cheeso: Yes, one can do this with Wix.Aalesund
Credits to the original post.. blogs.msdn.com/b/astebner/archive/2006/08/12/696833.aspxEelworm
Will this work with .bat? If so then i think i have the answer to two of my ongoing threadsExcursive
Having issues when I have some self registering COM Dll's in my setup. They just don't register in time and my app can't use these dll's; the app works perfectly when launched again from start menu. Any help?Eelworm
@Trainee4Life, sounds like you need to ask a new question.Blakeblakelee
@Cheeso: New question posted: #4423328Eelworm
I implemented this in a msi and it works perfectly. But when calling the msi as silent install: "msiexec /i setupFile.msi /qn", the application does not start after installation. And checkbox is set to true in the js. Any ideas?Cordiality
Also this adds the screen for uninstallation process as well - at the end of uninstall process.Cordiality
Thank you, this worked perfectly. It also ensures (somehow, the Type field in CustomActions?) that the exe is NOT run as elevated, which is a problem with other solutions I found. Email me or DM me @WindowTabs if you would like a free license, it's the least I can do.Sandalwood
Be sure to type the name of the macro $(BuiltOuputPath) correctly. It took me about half an hour to realize that the word Ouput is misspelled by Microsoft, and Built is not spelled Build !Pozzuoli
Yeah I was looking to do this myself and I used this guy's script which I found on his blog. I ran into an issue with it, but I resolved it. If anyone else is having issues please check here: #11404127Gaullist
My code builds and installs . But i do not see any windows to launch app (VS 2010) at the end any help?Richey
Can someone guide me how to hide 'Lanch application'checkbox in END screen of setup. I want to run post deployment scripts alwaysRadack
I know this is an old thread but I just want to ask if this can be edited to put two checkbox and run another installer?Pyrite
How to execute this script if we want to run app as administrator (as this solution doesn't work if we change app.manifest in our source code)? ThnxChrisman
@MarkLakata THANK YOU! In a million years I never would've noticed that on my ownMollee
@Mollee - I edited the answer to make this horrible gotcha more visiblePozzuoli
To avoid : "Microsoft JScript compilation error: Invalid character" and subsequent "'1' 'Unspecified error'" The file encoding for ModifyMsiToEnableLaunchApplication.js must be ANSI. (NOT UTF-8 Nor Unicode).Coop
One more: After run the application, the current directory can be a different of FOO.exe.AssemblyName.CodeBase.Coop
I can see the checkbox and it is checked but the program doesn't launch. I checked the EXE filename, even copied it from the bin folder. What may be the reason for the program not to run after installation?Pfeifer
Could it be because my app requires admin permission? <requestedExecutionLevel level="requireAdministrator" uiAccess="false" />?Pfeifer
This worked perfectly, but after some time i started getting "The installer has encountered an unexpected error installing this package. This may indicate a problem with this package. The error code is 2810." (even though the installation finishes). After logging, i found this: "DEBUG: Error 2810: On the dialog FinishedForm the next control pointers do not form a cycle.There is a pointer from both CheckboxLaunch and CancelButton to CloseButton" Any help with this?Fakir
I'm trying to modify and msi file genereated by jpackage but getting [object error] on the first view = database.OpenView(sql); line.Osteotome
cscript.exe is your setup solution name correct?Mulligan
I am using sqlite for my wpf application , and I tried to use the above steps to run the exe after the installation , but my db files are generating in the msi path, Is this something we are manipulating in js file regarding the sqllite files ? Note I have checked the db creation path , it shows the exe path still it is creating in msi file path as well @BlakeblakeleeMulligan
L
20

This seems to be a MUCH simpler solution: Visual Studio Installer > How To Launch App at End of Installer

Lick answered 27/2, 2011 at 15:28 Comment(3)
The original solution was required for VS2005 (and maybe VS2008) ?Pozzuoli
Apparently this simpler solution doesn't show the checkbox option.Lobotomy
in this solution problem is setup will stuck right before its near to complete... almost at 98% point. and it just finishes when you exit app.Barbrabarbuda
D
11

Here is the code (without the 2 auxiliary functions 'FindFileIdentifier' & 'StringEndsWith' in the end - use the original ones instead) which gives us the ability to change the Ys and Heights of the controls, along with adding the Checkbox Control Visibility Conditions (see the 2 comments that are marked between NEW - START to NEW - END):

// 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 = "*.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&#060;&#062;\"\"')";
    view = database.OpenView(sql);
    view.Execute();
    view.Close();
    //NEW - END


    database.Commit();
}
catch(e)
{
    WScript.StdErr.WriteLine(e);
    WScript.Quit(1);
}
Disoperation answered 8/6, 2010 at 15:28 Comment(2)
This fixed the launch application checkbox appearing after removing!Doriadorian
What exactly did it fix? It may just be that I am up too late, but I'm having trouble parsing what you wrote there, @Fidelis.Blakeblakelee
D
7

Concerning the "hidden checkbox bug", I figured out the following which is not explained by Cheeso's and Muleskinner's answers above:

The change of the script (provided by Muleskinner) places the Y position of the checkbox to 201 (I guess top Y pixel for the control). If you change Y to, say, 151 (in order to kind of align it in the center vertically), the bug "suddenly" appears. The reason for that is that there is another control in the Control table of the MSI, namely the 'BodyText' ('Dialog' field = 'FinishedForm'), which its Y is set to 63 and its height to 138. That, is 138 + 63 = 201. Therefore, if you change the Y value for the checkbox, the 'BodyText' control overlaps the newly added control and that's why the user needs to put their mouse over in order to show the checkbox. If you have no 'BodyText', or its number of characters is small enough you could change (by using Orca MSI editor as I do, or by altering the script above) the Ys and Heights of these 2 controls in order to be able and accommodate a different Y position for the newly added checkbox. The same applies for the control: 'BodyTextRemove' in which again we should alter its height value (which appears during uninstall).

Hopes that! this helps all the users that had the same question, as I had about this "bug".

Nevertheless, the script does a really good job!

Another question was how to make invisible the Checkbox during uninstallation procedure?

Using the Orca MSI editor, I added the following 2 rows in the ControlCondition table of the MSI:

Row 1 (When control should be shown):

(Dialog)FinishedForm
(Control)CheckboxLaunch
(Action)Show
(Condition)REMOVE=""

Row 2 (When control should be invisible):

(Dialog)FinishedForm
(Control)CheckboxLaunch
(Action)Hide
(Condition)REMOVE<>""

P.S. I am using VS 2010, on windows 7 (x64), but I believe these should work with previous versions too.

Disoperation answered 8/6, 2010 at 13:0 Comment(0)
M
6

This EnableLaunchApplication.js script has a small bug where the Control_Next tab sequence is incorrect. This will cause a error code 2810 when running the installation.

Change the following line to use the "Line1" control instead of "CloseButton" so that the tab sequence of the controls are all connected.

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',
   '|')";
Middlesworth answered 9/1, 2020 at 0:52 Comment(0)
K
4

Regarding the 'PostBuildEvent' failed with error code '1' 'Unspecified error' error, change the PostBuildEvent from

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

to

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

Regarding the hidden checkbox bug you can edit line 54 of the script to become:

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', '|')";
Karylkarylin answered 8/1, 2010 at 13:2 Comment(0)
A
3

After referred user3349200's suggestion, here is a completed JS script without setup error 2810.

// post-build-script: CALL cscript.exe "$(ProjectDir)EnableLaunchApplication.js" "$(BuiltOuputPath)"
// 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 = "YourApp.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);
}
Amaranthine answered 24/1, 2020 at 0:33 Comment(4)
I'm trying to use this script, but it still seems to have the issue where the run checkbox still appears during the uninstall phase. Also, I seem to be having a problem where my application doesn't actually run once the installer is finished.Stigmatism
Correction, I is running my application (I just had an unexpected error), however the checkbox still does appear during the uninstall phase.Stigmatism
for me it's work , I am able to see the checkbox but app is not auto launched after installationMulligan
This script saved my day.Jennifferjennilee
F
2

Yes.. I would write a custom action, and stick it at the end of the InstallExecutionSequence table

Flotow answered 4/11, 2009 at 2:21 Comment(4)
I don't see an InstallExecutionSequence table? Under custom actions I see Install, Commit, Rollback and uninstall. Would the custom action point to the output of the main program?Gardener
The InstallExecutionSequence table is internal to the MSI and not exposed via Visual Studio. You will need an MSI editor like Orca to edit it. Hand-editing MSIs is not a trivial task.Mcalpine
I agree - hand-editing MSIs is not easy. Not is it easy or trivial using Orca. You can use the script I provided below to automate the task. Quick and easy, tested and proven.Blakeblakelee
I know the question is for VS2008 but for VS2010 it looks fairly easy to create a custom Commit action. msdn.microsoft.com/en-us/library/d9k65z2d.aspxWind

© 2022 - 2024 — McMap. All rights reserved.