61

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. I am wondering how to add a button or check box that would launch the application after successful install. This would be located on the last page of the MSI Installer Package. I am using Visual Studio 2010 Ultimate.

I am needing this so that when the application does an automatic update, it auto launches the installer. I just need the installer to relaunch the app after the update.

starball
  • 20,030
  • 7
  • 43
  • 238
ThaKidd KG5ORD
  • 1,535
  • 3
  • 24
  • 38

8 Answers8

99

Warning: The application will end up running as a high privilege account, which has security and user experience implications.

To run any application after the installation is complete,

  1. Right-click on your setup project, click on Custom Actions.
  2. Then right-click on Commit, Add Custom Action, and choose the file you would like to run. (Note that it has to be in your application folder already, which shouldn't be a problem in your case since you are running your program anyway.
  3. Simply choose the output of your project.
  4. Then, click on this added .exe, and change InstallerClass to false. This is crucial because it will look for an installer program otherwise.
  5. You could even pass parameters to your .exe by adding them to the Arguments property
jbtule
  • 31,383
  • 12
  • 95
  • 128
sbenderli
  • 3,654
  • 9
  • 35
  • 48
  • Excellent..one question, would the main app be considered 'Primary output from ApplicationName (Active)'? – ThaKidd KG5ORD Jul 02 '10 at 20:55
  • 48
    One problem. The install app starts my app but never closes until I exit my app. It gets stuck on "98%" and only finishes when I exit my app. Is there a way to shutdown the installer gracefully? I ensured I set InstallerClass to False. Is there something I am missing? – ThaKidd KG5ORD Jul 03 '10 at 04:19
  • 7
    aah yes that will happen...in my case that was acceptable. what you can do instead is run a script from your installer which will in turn run your app and exit. this way, your app will run, but the script will exit which will let your installer complete also. – sbenderli Jul 03 '10 at 16:30
  • 22
    I just put "INSTALLER" in as the Arguments, and in my app entry point, did: if (args.Length == 1 && args[0] == "INSTALLER") { Process.Start(Application.ExecutablePath); return; } Note: Don't use Application.Restart(), as it passes the same arg in ;-) – Danny Tuppeny Aug 18 '11 at 19:37
  • 1
    Or, to use Danny's solution in a WPF app: First create an entry point method: http://frankmao.com/2009/05/07/control-the-entry-point-of-wpf-application/ Then add this to the method: if (e.Args.Length == 1 && e.Args[0] == "INSTALLER") { Process.Start(Assembly.GetExecutingAssembly().Location); Application.Current.Shutdown(); } – Anders Nov 02 '11 at 15:28
  • 14
    Just an FYI, the exe will end up running as a high privilege account, not the "normal" account, may or may not be a problem for you (it is for me) http://stackoverflow.com/questions/3939731/how-to-run-a-process-as-current-user-privilege-from-an-admin-process – Maurice Flanagan Dec 30 '11 at 20:37
  • When does the "commit" fire? Is it after the installation part has completed? – Urbycoz Feb 01 '12 at 09:31
  • 3
    I'm sorry but this answer is just wrong. For starters commit custom actions are only designed to cleanup rollback data. They don't execute when rollback is disabled. Then there is the security model problems discussed. – Christopher Painter Oct 10 '13 at 11:19
  • An installer built by VS2010 can't run JS scripts if you're installing on Windows 8. "A script required etc. could not be run". That's the only case I tested; for all I know it never worked under any circumstances. – 15ee8f99-57ff-4f92-890c-b56153 Mar 02 '15 at 01:44
  • As Maurice Flanagan pointed out, the exe will end up running as a high privilege account. This made my application not work correctly unless ran as an administrator. Even removing sbenderli's solution didn't fix my issue. To fix my problem I had to remove sbenderli's solution from my project, then change my product code and my upgrade code. Hope this saves someone some time. – Baddack Dec 04 '15 at 19:49
  • In my scenario, I wanted to run an executable that installed a log into the Windows event viewer before the user got a chance to use the application. I created a "Primary output from WindowsEventLogMaker" in the Custom Actions > Install folder. Be sure to check the properties on the "Primary output from WindowsEventLogMaker", specifically change the InstallerClass setting to False. [link](https://support.microsoft.com/en-us/kb/827018#bookmark-6) – LargeDachshund Sep 15 '16 at 18:34
  • Hi, Please anyone will suggest me if required to code anything in installer class for this? Because, I'm getting this problem and not able to resolve without your help. So, Please help me. Thanks in advance – dilipkumar1007 May 16 '17 at 05:44
  • I've done the same. Issue is that before click on 'ok' button at last screen during installation, application got launched. Application launch only and only when I click on ok button. Please help us – dilipkumar1007 May 16 '17 at 06:43
  • @sbenderli Hi,After completing installation of window form MSI setup, my raw files(Design and coding) are also showing at installation location. I've developed this application using visual studio 2010. Setup created successfully, but after installation that MSI this problem is happening. Please help me. Thanks in advance. – dilipkumar1007 Aug 02 '17 at 07:50
23

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 <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();

    // 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)"

JayTee
  • 1,114
  • 2
  • 11
  • 18
  • 3
    This is really the proper answer, especially considering that my app utilizes AD logon info, and installer runs as SYSTEM user. Down side is that it doesn't work with a quiet or passive install. Now to tear apart that js and see if I can figure it out. – Ricky Aug 14 '19 at 16:08
  • 4
    This didn't work for me, I got a 2810 error. Which I was able to discover this SO answer https://stackoverflow.com/a/59469922/637783 that led me to use Orca and modify the JS file where it inserts the new CheckboxLaunch control to make it's nextcontrol Line1 instead of CloseButton. Just a TIP to use Orca to debug if you have difficulties, because then the script worked perfect! – jbtule Jan 03 '20 at 21:25
  • On line 71 of the js file change from "CloseButton" to "Line1" and the error 2810 goes away as well as the form shows the checkbox with the Lauch AppName. However on windows 10 it does not seem to start the application. Any suggestions? – Rahul Kate Apr 25 '20 at 14:08
  • JayTee's script was the best solution. – David Maisonave Aug 02 '22 at 05:07
7

Warning: The application will end up running as a high privilege account, which has security and user experience implications.

In Visual Studio 2010 here it is easy...

Step1: Add a new installer class to the application project that you wish to run after install, call it what you like.

Step2: Add the following code to the Installer class you just added replcaing MyApplication.exe with the name of yours.

Public Overrides Sub Commit(ByVal savedState As System.Collections.IDictionary)

    MyBase.Commit(savedState)
    System.Diagnostics.Process.Start(System.IO.Path.GetDirectoryName(Me.Context.Parameters("AssemblyPath")) + "\MyApplication.exe")

End Sub

Compile and go...

jbtule
  • 31,383
  • 12
  • 95
  • 128
Jarrod
  • 79
  • 1
  • 1
  • After completing installation of window form MSI setup, my raw files(Design and coding) are also showing at installation location. I've developed this application using visual studio 2010. Setup created successfully, but after installation that MSI this problem is happening. Please help me. Thanks in advance. – dilipkumar1007 Aug 02 '17 at 07:51
  • 2
    Using this method will launch the new program with Admin privileges which is likely undesirable for security. – Kenneth M. Kolano May 28 '18 at 20:28
5

In my case, I was fighting with this for a while and the solution was just there. The solution provided using the custom action directly to the application primary output wasn't good for me, since the install app remains until you leave the main app. So, the issue could be solved using the next approach:

  1. Add an Install class to your project;
  2. In the new class, override the Commit method, like Jarrod talked above.

    System.Diagnostics.Process.Start(System.IO.Path.GetDirectoryName(this.Context.Parameters["AssemblyPath"]) + @"\MyApplication.exe");

  3. Now the trick: go to the "Custom Actions" pane in the Installer project and add the primary output of your project to "Commit" and "Install" folders. Don't change anything in the properties. It will work just like that. As default, it will get the installer class where you inserted the code, in the previous point;
  4. Build your setup package and install it. You should notice that the app will start at the end;
  5. Just close the successful installation warning and go for it.

To know more about this and where I got it, please visit this.

PS.: I made it using VS2017 and Framework 2.0.

Community
  • 1
  • 1
Artur Gomes
  • 84
  • 1
  • 4
  • Hi @Artur, I've done the same. Issue is that before click on 'ok' button at last screen during installation, application got launched. Application launch only and only when I click on ok button. Please help us. – dilipkumar1007 May 16 '17 at 05:54
  • 1
    Hi @dilipkumar1007. Did you try overriding the OnAfterInstall method? I'm not sure about it. If you got any results, please share. _Update: Nop... the behavior is the same..._ – Artur Gomes May 17 '17 at 09:34
  • Hi @dilipkumar1007. After my last answer, I did some searches and I think finally I got the behavior you need. I've tried the fire.eagle aproach [below](http://stackoverflow.com/a/3169056/7927227), using the steps in [this link](https://blogs.msdn.microsoft.com/astebner/2006/08/12/mailbag-how-can-i-customize-an-msi-in-the-visual-studio-setupdeployment-project/) here. In my case, I had to remove all the quotes in the PostBuildEvent script. (...) – Artur Gomes May 17 '17 at 11:22
  • (...) After that and rebuilding my setup project, installation process will have a last page to "open the application?" which will be done after you terminate the installation app. – Artur Gomes May 17 '17 at 11:24
  • Another thing. Using this method you can get rid of those "Custom Actions" and "Setup classes", since the script will do everything for you. Hope this is what you're looking for. – Artur Gomes May 17 '17 at 11:29
  • Hi @Artur Gomes, Thanks for your suggestion. But its not working. Its remain same. – dilipkumar1007 May 19 '17 at 07:09
  • Hi @Artur Gomes, I've same code in PostBuildEvent and didn't remove quotes. But, problem is same. Launched app before click on close button. – dilipkumar1007 May 19 '17 at 07:24
  • Hi @dilipkumar1007. Did you copied the file name `EnableLaunchApplication.js`to the Setup project folder? Please follow the link mentioned at the point 1 of [this article](https://blogs.msdn.microsoft.com/astebner/2006/08/12/mailbag-how-can-i-customize-an-msi-in-the-visual-studio-setupdeployment-project/). (...) – Artur Gomes May 19 '17 at 17:35
  • (...) after that, you have to replace the `var filename` in the top of the script with the name of your executable file (the file you want to run). Do not forget to fill the `PostBuildEvent` in the setup project properties with the mentioned string `cscript.exe $(ProjectDir)EnableLaunchApplication.js $(BuiltOuputPath)`. For me, it works without any quotes. With quotes it will give an error building the msi package. – Artur Gomes May 19 '17 at 17:39
  • Hi @Artur Gomes Thanks for your kind support. But would like to say that I've add same things whatever suggest by given link and also, bind PostBuildEvent script with quotes because without quotes it raise error code 1. – dilipkumar1007 May 23 '17 at 07:48
  • Hi @dilipkumar1007. No prob. Strange indeed. In my case, with quotes it gives the code 1 error. Maybe the path string you're using has any spaces or invalid chars. Also, are you spelling correctly the name of your executable at the top of the script? (asking just to be sure, sorry). Can you try build your setup project in a path without any spaces? – Artur Gomes May 23 '17 at 11:06
  • Hi @Artur Gomes, I've tried all aspects u've mentioned but didn't get any succeed. Can we converse at dkumar8807@gmail.com if you don't have any issue sir? – dilipkumar1007 May 24 '17 at 05:39
  • Hello @dilipkumar1007. Sorry i'm late answering. Did you tried the options mentioned in this [post](https://stackoverflow.com/questions/1668274/run-exe-after-msi-installation?noredirect=1&lq=1). They explain some changes on the script in order to workaround a few issues and maybe they have solved the code 1 error. – Artur Gomes May 31 '17 at 11:12
  • Hi @Artur , After completing installation of window form MSI setup, my raw files(Design and coding) are also showing at installation location. I've developed this application using visual studio 2010. Setup created successfully, but after installation that MSI this problem is happening. Please help me. Thanks in advance. – dilipkumar1007 Aug 02 '17 at 07:48
  • Hi @dilipkumar1007. Have you joined those files to the installation package? Unless you want it, you shouldn't. After all, basically you just need the primary output for your executable projects in the solution and any other extra files you gonna need in the production. Check what you've chosen to add to the installation project. – Artur Gomes Aug 03 '17 at 09:22
3

Try checking out this blog post: Link

I can't attest for if it works for 2010 or not; I'm still stuck using 2008 until my TFS server gets upgraded. Also, I use WiX for my installers. But, it's just a custom action, so I think it should still be supported.

Hope this helps!

(By the way, while practicing my googling to find this, your question was showing up on the first page of Google for this question.)

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
fire.eagle
  • 2,723
  • 1
  • 21
  • 23
1

Adding another answer because none of the previous answers address the checkbox or button question in the original post.

You'd add one of the canned dialogs to your setup project, something like CheckBoxes(A) by right-clicking the Start button in the User Interface view. Right-click the dialog after adding to move it up. You need only one checkbox for the question to ask about running the program so eliminate the others. The default property name is CHECKBOXA1, so add a condition to the custom action that fires off your code CHECKBOXA1=1 meaning it was checked.

PhilDW
  • 20,260
  • 1
  • 18
  • 28
1

first generate installer class. in that override the install method. and paste the following command.

  public override void Install(IDictionary stateSaver) {
        
    System.Diagnostics.Process.Start(System.IO.Path.GetDirectoryName(this.Context.Parameters["AssemblyPath"]) + @"\windowsAgent.exe");   
              
 }
Slava Rozhnev
  • 9,510
  • 6
  • 23
  • 39
0

JayTee's script was the best solution. However, the file name in the first line of the script is misspelled.

It should be the following: // EnableLaunchApplication.js <msi-file>

The correct name has to be use for it to work when following the instructions in the following link: customize msi

The sample-link in above link is bad.

Use the following script with the instructions in the above link.

// 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 = "TranslateFileNamesWin.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);
}
Glorfindel
  • 21,988
  • 13
  • 81
  • 109