I’m writing a load balancer which is itself a web application. I want to be able to restart an instance of another web app when certain criteria are met.
However, I’m struggling. If I start an instance of a web app using a Shell, the Shell object remains the whole time the web app is running. I don’t want this, I just want the shell to launch the app and then be destroyed (go out of scope).
I also can’t use FolderItem.Launch as my balancer is a webapp and so FolderItem.Launch is not available.
How can I get my webapp to simply launch another application?
This is what I wrote to launch an app that is independent of the app that launched it. I assume it will run from a web app, as I run it from a console app:
#elseif TargetLinux then
tempShell.Execute("chmod +x " + f.ShellPath) 'Linux needs the executable bit turned on!
tempString = “nohup " + f.ShellPath + " &” 'No Hang Up. Stops the child shell being killed once the parent shell is quit
#elseif TargetMacOS then
tempShell.Execute(“chmod +x " + f.ShellPath) 'not sure if MacOS X needs the executable bit turned on after unzipping?
'tempString = “nohup " + f.ShellPath + " &” 'No Hang Up
'tempString = f.ShellPath + " &”
tempString = “open -a " + f.ShellPath + “; exit” + f.ShellPath + " &” '-a for application 'open -a Mail; exit
#endif
tempShell.Mode = 1 '0 Synchronous 1 Asynchronous
tempShell.TimeOut = 10000 'milliseconds
tempShell.Execute(tempString)
DelayMBS scriptDelay 'give the script time enough to launch the app
tempShell.Close
On Windows create a service for each instance and use the service control manager to start & stop as required. While this does require the use of a shell, the instance is short lived.
Windows Functionality Suite has this method that works in a Web application:
Function LaunchAndNotWait(extends f as FolderItem, params as String = "", deskName as String = "") As Uint32
// We want to launch the application and not wait for
// it to finish executing before we return.
dim rc As Uint32
#if TargetWin32
Soft Declare Function CreateProcessW Lib "Kernel32" ( appName as WString, params as WString, _
procAttribs as Integer, threadAttribs as Integer, inheritHandles as Boolean, flags as Integer, _
env as Integer, curDir as Integer, startupInfo as Ptr, procInfo as Ptr ) as Boolean
Soft Declare Function CreateProcessA Lib "Kernel32" ( appName as CString, params as CString, _
procAttribs as Integer, threadAttribs as Integer, inheritHandles as Boolean, flags as Integer, _
env as Integer, curDir as Integer, startupInfo as Ptr, procInfo as Ptr ) as Boolean
Soft Declare Function CloseHandle Lib "Kernel32" ( handle as Integer ) As Boolean
Soft Declare Function GetLastError Lib "Kernel32" ( ) As Uint32
dim startupInfo, procInfo as MemoryBlock
startupInfo = new MemoryBlock( 17 * 4 )
procInfo = new MemoryBlock( 16 )
dim unicodeSavvy as Boolean = System.IsFunctionAvailable( "CreateProcessW", "Kernel32" )
startupInfo.Long( 0 ) = startupInfo.Size
dim deskStr as MemoryBlock
if deskName <> "" then
if unicodeSavvy then
deskStr = ConvertEncoding( deskName + Chr( 0 ), Encodings.UTF16 )
else
deskStr = deskName + Chr( 0 )
end if
startupInfo.Ptr( 8 ) = deskStr
end if
dim ret as Boolean
if unicodeSavvy then
ret = CreateProcessW( f.AbsolutePath, params, 0, 0, false, &h10, 0, 0, startupInfo, procInfo )
else
ret = CreateProcessA( f.AbsolutePath, params, 0, 0, false, &h10, 0, 0, startupInfo, procInfo )
end if
if ret then
call CloseHandle( procInfo.Long( 0 ) )
call CloseHandle( procInfo.Long( 4 ) )
else
rc = GetLastError()
end if
#else
#pragma unused f
#pragma unused params
#pragma unused deskName
#endif
Return rc
End Function