CitrixTools.Net Articles

Current Articles | Categories | Search | Syndication

Publish and Application that needs explorer.exe

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

' -------------------------------------------------------'

posted on Wednesday, August 26, 2009 8:50 PM by Pierre Marmignon    

Previous Page | Next Page

COMMENTS

Only registered users may post comments.