How To Run A Program Via JavaScript

// Sometimes, it's necessary to run a program via JavaScript instead of directly via an MSI CA.

// For example, it might be easier to locate the program or construct the command line in JavaScript than by

// trying to craft some set of SetProperty CA's to do the same thing. Or, for example, InstallShield LE just

// won't let you. This script demonstrates how to run a program and is designed to be run as a Deferred mode CA.

var ClassName_ScriptingRuntimeShell = "WScript.Shell";

var argumentString = "";

var installDir = "";

var programToRunPathname = "";

var commandLineToRun = "";

// CustomActionData format: [INSTALLDIR]<?>

// If running in MSI, use arguments via standard CustomActionData interface, otherwise assume running outside MSI in debugger

if (DetectRunningInMSI())

argumentString = Session.Property("CustomActionData");

else

argumentString = "c:\\program files\\MyProgramDir\\";

arguments = argumentString.split("<?>");

if (arguments.length == 1)

{

installDir = arguments[0];

}

else

{

LogMessage("Argument string invalid (" +arguments.length+ "): " +argumentString);

throw 3;

}

installDir = EnsureEndsInBackslash(installDir);

programToRunPathname= installDir +"ProgramToRun.exe";

commandLineToRun = "\""+ programToRunPathname+"\" somecommand";

if (RunCommand(commandLineToRun) != 0)

{

// Critical error, fail install

throw 3;

}

function RunCommand( commandLine )

// Runs the specified command line and returns the process exit code or failure code

{

var returnVal = -1;

var shellUtil = null;

// Validate parameters

if (commandLine == "")

return -1;

shellUtil = SafeGetActiveXObject(ClassName_ScriptingRuntimeShell);

if (shellUtil != null)

{

try

{

LogMessage("RunCommand: Running "+commandLine);

returnVal = shellUtil.Run(commandLine, 0, true);

if (returnVal != 0)

LogMessage("RunCommand: Error " +returnVal+ " returned by command line "+commandLine);

}

catch (runException)

{

// 0x80070002

if (runException.number == -2147024894)

LogMessage("RunCommand: File not found error running command " +commandLine+ ": " +runException.message);

else

LogMessage("RunCommand: Error " +runException.number+ " running command " +commandLine+ ": " +runException.message);

returnVal = runException.number;

}

shellUtil = null;

}

return returnVal;

}

function LogMessage( messageString )

// Writes a line to the MSI log, or the console if running outside MSI.

{

var customActionName = "RunProgram";

if (DetectRunningInMSI())

{

var msiMessageTypeInfo = 0x04000000

var logRecord = null;

var currTime = new Date();

logRecord = Installer.CreateRecord(1);

logRecord.StringData(0) = currTime.toTimeString() +" "+ customActionName +": [1]";

logRecord.StringData(1) = messageString;

Session.Message(msiMessageTypeInfo, logRecord);

logRecord = null;

}

else

{

var currTime = new Date();

messageString = currTime.toTimeString() +" "+ customActionName +": "+ messageString;

WScript.Echo(messageString);

}

}

function DetectRunningInMSI()

// Returns TRUE if running in MSI, else FALSE

{

var returnVal = true;

var stringVal = "";

try

{

// Try to reference the Session object, which is only provided by the MSI runtime engine

stringVal = Session.Property("ProductCode");

}

catch (thisException)

{

// An exception is only thrown if the runtime couldn't resolve Session, which means

// this script is not running under MSI

returnVal = false;

}

return returnVal;

}

function SafeGetActiveXObject( className )

// Creates an instance of className and returns it, or null if an error occurs, and logs the error

{

var returnVal = null;

try

{

returnVal = new ActiveXObject(className);

}

catch (createException)

{

LogMessage("SafeGetActiveXObject: Error " +createException.number+ " creating object of class " +className+ ": " +createException.message);

}

return returnVal;

}

function EnsureEndsInBackslash( directoryPath )

// Returns directoryPath ending in a backslash if it does not already end in one.

{

var returnVal = directoryPath;

if (returnVal.substring(returnVal.length, returnVal.length-1) != "\\")

returnVal = returnVal + "\\";

return returnVal;

}