Using a startup script to monitor for connected Citrix Sessions

Published on
10,435 Points
1 Endorsement
Last Modified:
The idea here is that a user has a Windows embedded type terminal used to connect a user to Citrix session, and log them off if they are not connected.

So, the logical question is why does this matter?

The answer is that the Citrix Online Plugin or Receiver can automatically reconnect a user with cached credentials.  In an environment with a generic user login (as most of the terminal based environments have), this means that if User A logs in and gets disconnected, then walks away, User B can reconnect to User A's session, without authentication (default configuration).   In kiosk scenarios, this can range from slightly undesirable, to a major security threat.

Here is the script:
dim bFirstResults, bLastResults, wshShell
dim oWMI, cProcesses

bFirstResults = vbFalse
bLaterResults = vbTrue

'First pass - we do this on the first login to make sure the user has a chance to get logged in.
'The first loop runs until it sees wfica32.exe
'The second loop runs until it *doesn't* see wfica32.exe

Do Until bFirstResults = vbTrue
     bFirstResults = FirstPass()

     bLaterResults = LaterPass()
Loop Until bLaterResults = vbFalse

Set wshShell = CreateObject("WScript.Shell")
wshShell.Run "logoff.exe", 0, vbFalse

Function FirstPass( ) 
     Set oWMI= GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
     Set cProcesses = oWMI.ExecQuery ("SELECT * FROM Win32_Process WHERE Name = 'notepad.exe'")

     If cProcesses.Count=0 Then
          bFirstResults = vbFalse
          bFirstResults = vbTrue
     End if
     FirstPass = bFirstResults 
End Function

Function LaterPass( )
     Set oWMI= GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
     Set cProcesses = oWMI.ExecQuery ("SELECT * FROM Win32_Process WHERE Name = 'notepad.exe'")

     If cProcesses.Count=0 Then
          bLaterResults = vbFalse
          bLaterResults = vbTrue
     End if
	wscript.echo "Later Pass"
     LaterPass = bLaterResults 
End Function 

Open in new window

Now, an explanation of how this works.

First - the user needs time to get logged in.  We start out by assuming they have not logged in:
bFirstResults = vbFalse

Open in new window

If we didn't give them that, they would be stuck in an endless reboot loop, because they couldn't get logged in quickly enough.  With this in mind, the script checks every 10 seconds to see if the wfica32.exe is running (this is Citrix's runtime executable for live ICA connections).  If the user has not logged in, it will continue to loop and check every 10 seconds to see if it is there. By doing this, we are preventing needless reboot cycles.

The key to this is the WMI query. We create a WMI object, and use it to query the running processes to look for wfica32.exe. By using the WHERE clause, we are filtering the list of running processes, and do not need to process the entire list.  

Note: Any running ICA connection will count. The script does not look for a specific wfica32.exe process -- it looks for any wfica32.exe process. Make sure your ICA connections end cleanly!

Once the FirstPass() completes successfully, then we move on to the LaterPass() loop. It is effectively the same loop, and it continues indefinitely. The difference is that now we assume that the user is running a connection
bLaterResults = vbTrue

Open in new window

and when the connection fails, we will log them out of the terminal. The script is configured to check every 5 seconds, but this can be tuned to handle your environment. Once the check fails, we move on to the next line of the script which runs logoff.exe.  With no switches, this automatically logs the user out.

With this, the ideal placement of the script is to make it a startup script for the user account, either by GPO for domain machines, or placing a shortcut to the script in the user's startup directory:
[for Windows 7/2008R2 - %appdata%\microsoft\windows\start menu\programs\startup]
[For Windows XP/2003 - %userprofile%\Start Menu\Programs\Startup]

By placing it in this location, we are exempting the local administrator account from being affected.  

In a domain situation, this script could also be placed by a Group Policy Object as a user level login script.  

Because this script is merely checking to see if a process is running, it can be adapted to any number of other scenarios where a user should be running a process and an action should be taken if they are not.
Ask questions about what you read
If you have a question about something within an article, you can receive help directly from the article author. Experts Exchange article authors are available to answer questions and further the discussion.
Get 7 days free