Scripting Around Session 0 Isolation Print E-mail

Millions of administrators worldwide depend on the ability of a Windows Service to display a message on the user desktop for coordination of software distribution activities. Generally this involves communications such as allowing the user to defer software distribution jobs, notification that a distribution job is underway in the background or informing that a software installation is complete. The new security feature in Windows 7 known as “Session 0 Isolation” now blocks this communication from occurring. This Toolkit addition presents a reasonable secure, simple method for getting around the Session 0 barrier.

The Problem

Quick note: This script is part of our course Win7 LUA/Non-Admin Application Integration Engineer (ENG-60).

Under Windows XP all services and the interactive user logon all reside in Session 0. This architecture is what allows services configured with “Allow this service to Interact with the Desktop” to display a user interface directly to end users. This design is also susceptible to attacks on privileged services from code started by the logged on user. Figure 1 shows session 0 isolation depicted as a sort of special security boundary. In reality it is just standard operating procedure that services that display a UI will display it in the default desktop for their session, which is no longer the same session as the user in Windows 7.

Microsoft publishes several methods for allowing a service to establish a connection with the user desktop. The primary method involves designing a process that runs in the user session that can receive communication from service processes and present any necessary UI to the end user. The suggested communications mechanisms include RPC, Named Pipes, Terminal Server APIs (WTSSendMessage), mapped memory or the CreateProcessAsUser API. None of these methods are easily usable via scripting.

This Solution

Scripting is always about doing the most with the least. This solution leverages the registry as a communication mechanism between server and client processes. Since WMI allows efficient registry change notification, we can effectively design a client side process that monitors for messages from services and displays a UI in the user session and returns the response of the user via the registry as well. Using the registry also gives programming language neutrality – the service side can be written in any language. Using the registry also allows the most simplistic languages or other mechanisms to be used – where advanced programming such as RPC and calling Windows APIs requires more sophisticated programming tools.

There are really two aspects to this solution: a) the architecture of using the registry and WMI monitoring – this could be done in most any language by following the same principles, b) a feature complete VBScript solution ready for deployment – this VBScript installs the registry keys and sets their permissions, monitors the queue, can be uninstalled, shutdown, restarted, reinstalled, logs to the event log, contains debugging code and cleans up the registry keys on startup. Multiple queues can be deployed simultaneously by simply renaming the .VBS.

The architecture of passing messages back and forth between processes through an intermediary layer is known as “message queuing”. It is important not to confuse the architectural concept of “message queuing” in this solution with dedicated products and middleware that perform message queuing of database transactions.

Like this script? Subscribe to our newsletter (without loosing your place in this article).
(Please ensure that the confirmation email clears your spam filter so that you will see future mailings.)

The basic concept is displayed in Figure 1. The message queue utilizes two registry keys - “Inbox” and “Outbox”. By default these keys are located in HKCU and the server process does some queries to find out which user registry hive has a queue processor running against it. The queue can also be run out of HKLM if necessary (for simplicity of qsender processes) - in this case the queue must be installed by an administator before a regular user can run the qmonitor against it. With a little redesign the registry keys could be made even more secure by making the service completely responsible for removing anything it has put into the inbox. There are several reasons why this is probably not necessary - first, the primary communication channel is from a privileged service to the less privileged user desktop, second, the queue monitor looks only for a specific named value, third, the queue monitor can only process contents intended to be displayed with the vbscript popup method, anything else wouldn't work. is capable of being run as a service and receiving messages from the user session – this type of implementation is when more security precautions are needed.


Testing CSI-MsgQ.vbs For Sending Messages From Services to End Users
  1. It is best to rename the script when you go to deploy in production, but for testing, leave the name the same since the provided testing scripts all presume the original name and the install folder listed in the next step.
  2. Copy CSI-MsgQ.vbs and MsgQ-Tester.vbs to the folder: C:\Users\Public\CSI_MsgQ
    This allows the script to be available to all users.
  3. To emulate a regular user, open an NON-Elevated command prompt and type (use cscript to allow the many debug messages to go to the console window):
    cscript CSI-MsgQ.vbs /debug /monitor
  4. If everything goes well, the messages in the console window will indicate that the queue is being monitored. This information is also in the event log.
  5. To emulate a background service, start an ELEVATED command prompt and type:
    cscript MsgQ-Tester.vbs
  6. Answer the prompts indicating the question you would like to ask. Notice that each dialog tells you which script it is being generated by. After the final dialog (ask for the timeout value) your "user" message will be displayed. Notice that it comes from the CSI-MsgQ.vbs process.
  7. The debug output in the CSI-MsgQ.vbs console window will demonstrate that the script is hearing you.
  8. Read the notes inside MsgQ-Tester.vbs about how to make it redirect its output to the event log so you can send it through your distribution system and see it working.
  9. To see what users would see, simply do not use the /debug switch on CSI-MsgQ.vbs and double click MsgQ-Tester.vbs.

MsgQ-Tester.vbs also contains sample code that may be useful on your server side script for the following items:

  • Using WMI to monitor the registry key that will contain the response to your query (this allows you to wait indefinitely without the risk of eating up a lot of CPU cycles with a loop).
  • Using a loop so that you can timeout if necessary.
  • Use WMI to check if the queue monitor is running (if no one is logged on, it won’t be running).

TRK-60 Win7 LUA/Non-Admin Application Integration Engineer

This script is covered in more detail in our training track TRK-60 Win7 LUA/Non-Admin Application Integration Engineer. The course is designed to give you a solid background on the native Windows XP application runtime environment, bring you up to speed on the Windows 7 runtime environment and then teach you how to get applications to run on Native Windows 7 without admin rights. Even if you are planning to use application virtualization, up to 25% of your application portfolio may not be able to be virtualized. Here is the course outline.

Deployment Ready

Here are the command line options and features that make it a robust solution:

  • /INSTALL – rarely needed - only if implementing an HKLM based queue that needs public permissions - which is not need for the implementation discussed in this article. Requires admin permissions.
  • /RUNMACHINE – sets the script up to autorun using HKLM\Software\Microsoft\Windows\CurrentVersion\Run. Requires admin permissions.
  • /RUNUSER – sets the script up to autorun using HKCU\Software\Microsoft\Windows\CurrentVersion\Run.
  • /MONITOR – monitors message queue for new inbox messages.
  • /STOPQMON – sends a message to the queue monitor to shut itself down.
  • /FORCEDOWN – uses WMI to kill all instances of the message queue script.
  • /RESTARTQMON – sends a message to the queue monitor to restart itself in its current run context.
  • /UNINSTALL – stops message queue monitor and stops queue. Requires admin permissions.
  • /REINSTALL – uninstalls, stops the monitor and then installs the message queue. Helpful for when you’ve made code updates. Does not restart the queue monitor as this would need to happen in the user’s contact. Requires admin permissions.
  • /DEBUG – turns on debugging (overrides setting in script).

Other Features

  • Compatible with XP so you can implement one solution for all client types.
  • Autocreates queue registry keys whenever possible.
  • Cleans up the message queue upon startup.
  • Only allows one instance to be monitoring the queue.
  • Uses reliable methods of determining whether installation or uninstallation occurred correctly.
  • Logs to the event log.
  • Contains debugging code that can be switched on.
  • Monitor relaunches with wscript if started with cscript.
  • Supports the ability to build your own “Queue Processors” to do things other than just send messages. We can build these for you as well.

Limitations and Features

  • So far CSI-MsgQ.vbs is only designed to run on computers where one user is logged on present - not on terminal server.

Customization Services

If you wish to have this script licensed or customized for your organization, please use our Contact form to make your request.


To get your copy of this top quality script we only require that you subscribe to a list (including confirming your email address). As with all our lists you can easily unsubscribe at the bottom of any future mailing.


Updated: 11/16/10 to Version 2.3, which included these changes:

  • Since WMI queries are case sensitive, using a mixed case name as the registry queue name, but starting the script in lower case causes events to be missed.  The script now checks for uppercase characters in it's name and blocks execution if they are found.
  • Fixed bug with Execute statement
  • Fixed bug: script would try to create registry keys when running HKLM registry monitor as regular user.
  • Changed Admin Rights check routine
  • New QProcessor for inputboxes ("QProcessor_InputBox")
  • SID lookup functions now done by GetUserIDorSIDInfo() v1.1 which avoids certain rare conditions that cause errors.
  • TLHiveValue() upgraded to v1.1 which does not depend on global constants

Click here to get your copy.