Detecting PCoIP Disconnects within the VDI Desktop

One of my customers has to an application with strict concurrency limits in its licensing.  Historically, they've worked around those concurrency limits by having a limited number of workstations from which to launch that application.  When a user needed it, they would just go to one of those workstations and do their work.  This created a serious pain point though, as users would frequently lock the workstation rather than log out of it, leaving their coworkers with one fewer workstation at that location (there are far more users then computers at these locations).

VDI allows us to very easily work around that later problem, as each user can now get their own desktop.  The location is still limited by the number of terminals that it has, however a user can now simply restart the terminal in order to connect to their own desktop without causing their coworker to lose any work.  This flexibility has introduced the pain from this particular applications concurrency limits, though.

This customer asked me to work on a launcher script for their application that would detect when a PCoIP session disconnected and would then kill that particular application.  Automatic logoff after disconnect was insufficient, as we did not want to impact any documents that might be open on the desktop.  So, I had an interesting challenge on my hands.

I thought about the problem and asked around the community.  There are nice and easy ways to run scripts on client connection and reconnection, however I was unable to find any way to trigger a script on a disconnect.  That's when I thought about the ViewClient* registry settings under HKCU:Volatile Environment.  There's a whole bunch of those registry values, which contain all sorts of useful information about the View Client that's connected to the desktop.  I knew that they are updated when a client reconnects to the desktop with information about the new client, but I wasn't sure what happened when a client disconnected from a desktop.  To figure this out, I wrote a quick and simple PowerShell script to run on a VDI desktop as it traversed from a connected state to a disconnected state:

echo "Starting..." > C:\Temp\Volatile.log
for ($i=1; $i -le 10; $i++)
{
   Start-Sleep 5
   echo "==========================" >> C:\Temp\Volatile.log
   Get-ItemProperty -Path "hkcu:volatile environment" >> C:\Temp\Volatile.log
}


I then just started this script on my VDI desktop, disconnected my session, waited about 30 seconds, then reconnected to my desktop to examine the log file that it created.  The results were awesome; when my PCoIP session was connected, all of the ViewClient* values were fully populated with the correct data.  After the PCoIP session disconnected, those values were all deleted.  When the session reconnected, they were repopulated with the correct data once more.  With this knowledge in hand, I created the following script:

param
(
   $application = "App-To-Be-Launched"
)

#Launch the application
Invoke-Item "C:\Path\To\App\$application.exe"

Start-Sleep 30
#While the application is running AND the PCoIP session is connected, loop forever
while (((Get-ItemProperty -Path "HKCU:Volatile Environment").ViewClient_Protocol) -and (get-process $application))
{
   Start-Sleep 30
}
#Quit any running instances of the application after the application closes or the PCoIP session disconnects
Get-Process $application | Foreach-Object { $_.CloseMainWindow() | Out-Null } | stop-process –force


And with that, the problem was solved.  This script will first launch the application and will then sit in a loop waiting for either the application to close or the PCoIP session to disconnect (as determined by the lack of an HKCU:Volatile Environment.ViewClient_Protocol value in the registry).  Once one of those events happens, the script checks for any running instances of the application and closes them, then completes itself.

As always, this script is provided for educational purposes.  While it worked in this particular situation, that is no guarantee that it will work in any other situation, so please test thoroughly and share any improvements that you may make!

Comments

Popular posts from this blog

PowerShell Sorting by Multiple Columns

Clone a Standard vSwitch from one ESXi Host to Another

Deleting Orphaned (AKA Zombie) VMDK Files