Another experience from the field ...
Deploying applications on XenApp, You may have faced this kind of issue : an application is working fine within a published Desktop, but is not launching when published seamless.
In many cases (although it can also be related to a seamless issue), this is because the Application needs "explorer.exe" running (which is the case in a published desktop but not within a published application).
To deal with this problem, you can start explorer.exe (for example) before the application.
The problem is that if you start it, users will see a file explorer.
So you have to hide it, which is not really hard with .vbs for example.
The main problem is when the published application has exited, as your hidden explorer.exe will remain in memory, it'll prevent the session to log properly off.
If you try to kill the explorer.exe after your application has exited, you can also kill another legitimate explorer.exe instance and having the users not to be really happy.
So how to achieve this properly ?
The following script will help you ! Actually this script has been designed to launch an initial process (hidden by default) and then start another child process (by child I'm talking about a process that needs the first to be launched).
At launch, the script will grab the initial process PID.
Then, it'll wait for the child process to be finished and when it'll be (which should mean the main application has been exited) it'll kill the initial process by name and PID, to ensure only the appropriate instance is terminated.
' -------------------------------------------------------'
Const strComputer = "."
Const HIDDEN_WINDOW = 0
Const VISIBLE_WINDOW = 1
Const MyInitialProcess = "notepad.exe"
Const MyApp = "calc.exe"
Set objShell = Wscript.CreateObject("Wscript.Shell")
Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Main()
Sub Main
On Error Resume Next
Err.Clear
MyPID = StartExProcess(MyInitialProcess,False)
wscript.sleep 100
objShell.run MyApp , 1 , True
wscript.sleep 100
TerminateExProcess MyInitialProcess,MyPID
End Sub
Function StartExProcess (sProcessName,Visible)
On Error Resume Next
Err.Clear
Set objStartup = objWMIService.Get("Win32_ProcessStartup")
Set objConfig = objStartup.SpawnInstance_
Select Case Visible
Case True
objConfig.ShowWindow = VISIBLE_WINDOW
Case False
objConfig.ShowWindow = HIDDEN_WINDOW
End Select
Set objProcess = GetObject("winmgmts:root\cimv2:Win32_Process")
errReturn = objProcess.Create(sProcessName, null, objConfig, intProcessID)
StartExProcess = intProcessID
End Function
Sub TerminateExProcess(sProcessName,sProcessID)
On Error Resume Next
Err.Clear
strProcessName = Right(sProcessName, len(sProcessName) - instrrev(sProcessName, "\"))
Set colProcessList = objWMIService.ExecQuery("Select * from Win32_Process Where Name = '" & strProcessName & "'")
For Each objProcess in colProcessList
if objProcess.ProcessID = sProcessID then
objProcess.Terminate()
end if
Next
End Sub
' -------------------------------------------------------'
Another problem, another script :) This one is in the same article because the following script is derivated from the first one.
This time we're talking about publishing java .jnlp applications on Xenapp.
It has been working fine with Xenapp 4.0 but does not with 4.5 and 5.0.
Actually the only workaround for now is to install Internet Explorer 7.0 on your server(s), which is not something you may be able to do.
To deal with this issue, it's a little bit more tricky.
Actually I've found that the .jnlp was launching fine when Internet Explorer was running before starting the .jnlp.
I then decided to use the script published at the beginning of this article to launch the .jnlp using javaws.exe (JRE >=1.5) and launching iexplore.exe before and hidden.
The problem is that whatever you'll use to launch the .jnlp, only iexplore.exe or javaws.exe will work, but as soon as they've done their job, the process terminates and the only one remaining is javaw.exe (which can't be used to initially publish the .jnlp so it can't be monitored).
So big problem, because if the user can launch the application, the session won't log properly off because of a remaining process.
To overcome this issue, this script is introducing a process monitoring function so it'll be able to know when the monitored process (in our case javaw.exe) will be exited (which means the .jnlp application has exited).
When the monitored application will be exited, it'll kill the parent process so that the session will be closed properly.
' -------------------------------------------------------'
Const strComputer = "."
Const HIDDEN_WINDOW = 0
Const VISIBLE_WINDOW = 1
Const MyInitialProcess = "C:\Program Files\Internet Explorer\iexplore.exe"
Const MyProcessToMonitor = "javaw.exe"
MyApp = chr(34) & "C:\Program Files\Java\jre1.5.0_09\bin\javaws.exe" & chr(34) & Space(1) & "http://myserver:8080/JNLPLauncher/SVC.jnlp"
Set objShell = Wscript.CreateObject("Wscript.Shell")
Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Main()
Sub Main
On Error Resume Next
Err.Clear
MyPID = StartExProcess(MyInitialProcess,False)
wscript.sleep 100
objShell.run MyApp , 1 , True
wscript.sleep 30000
TerminateExProcess MyInitialProcess,MyPID
End Sub
Function StartExProcess (sProcessName,Visible)
On Error Resume Next
Err.Clear
Set objStartup = objWMIService.Get("Win32_ProcessStartup")
Set objConfig = objStartup.SpawnInstance_
Select Case Visible
Case True
objConfig.ShowWindow = VISIBLE_WINDOW
Case False
objConfig.ShowWindow = HIDDEN_WINDOW
End Select
Set objProcess = GetObject("winmgmts:root\cimv2:Win32_Process")
errReturn = objProcess.Create(sProcessName, null, objConfig, intProcessID)
StartExProcess = intProcessID
End Function
Sub TerminateExProcess(sProcessName,sProcessID)
On Error Resume Next
Err.Clear
strProcessName = Right(sProcessName, len(sProcessName) - instrrev(sProcessName, "\"))
Do while not bMustStop
Set colProcessList = objWMIService.ExecQuery("Select * from Win32_Process")
IsPresent = False
For Each objProcess in colProcessList
if lcase(objProcess.Name) = lcase(MyProcessToMonitor) then
IsPresent = True
end if
Next
If Not IsPresent then Exit Do
wscript.sleep 5000
Loop
Set colProcessList = objWMIService.ExecQuery("Select * from Win32_Process Where Name = '" & strProcessName & "'")
For Each objProcess in colProcessList
if objProcess.ProcessID = sProcessID then
objProcess.Terminate()
end if
Next
End Sub
' -------------------------------------------------------'