Accessing the Application Desktop from a Service

This article was previously published under Q115825
This article has been archived. It is offered "as is" and will no longer be updated.
Under Windows NT, version 3.1, if you want a service to have access to theapplication desktop, you must run the service in the LocalSystem account. Aservice process running in the LocalSystem account (or a process startedfrom such a service) can display message boxes, windows, and dialog boxes.Processes that are running in the LocalSystem account are not terminated bythe system during logoff. A number of changes were made to Windows NT,version 3.5, that affect the way Windows NT interacts with these services.In addition, Windows NT 3.51 has a richer set of desktop APIs.

NOTE: Running interactive services under the system account is a VERYdangerous practice. This is especially true of the command processor andbatch files. A user who wants to control the system can just hit CTRL+Cto get an interactive system command prompt.
The following are new features of Windows NT, version 3.5, that affectservices:
  • The account of the logged in user is the only account granted access to the application desktop. The LocalSystem no longer has access. Therefore, it is possible to get access to the desktop by impersonating the user before making any USER or GDI calls.
  • Console and GUI applications started from a service process during a particular logon session are run on an invisible window station and desktop that are unique to that session. The window station and desktop are created automatically when the first application in the session starts; they are destroyed when the last application exits. There is no way to make these invisible desktops visible.
  • If you want a service in the localsystem account to interact with the logged-on user, specify the SERVICE_INTERACTIVE_PROCESS flag in the call to CreateService(). For example:
          schService = CreateService(         schSCManager,         serviceName,         serviceName,         SERVICE_ALL_ACCESS,         SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS,         SERVICE_DEMAND_START,         SERVICE_ERROR_NORMAL,         lpszBinaryPathName,         NULL,         NULL,         NULL,         NULL,         NULL );						
    If you specify an account other than localsystem when using SERVICE_INTERACTIVE_PROCESS, you will get error INVALID_PARAMETER (87).
  • If you use CreateProcess() to launch your process and you want your service to log onto the users desktop, assign the lpdesktop parameter of the STARTUPINFO struct with "WinSta0\\Default".
  • Services that simply need a visible user notification can do this by calling MessageBox() with the MB_SERVICE_NOTIFICATION flag. Using the MB_DEFAULT_DESKTOP_ONLY flag works as well, but only if the user's desktop is active. If the workstation is locked or a screen saver is running, the call will fail.

    NOTE: If you are writing code for an application that can be run as either a service or an executable, you can't use MB_SERVICE_NOTIFICATION as well as a non-NULL hwndOwner.
  • Any output done to a window is not displayed or made available to the application in any way. Attempts to read bits from the display results in a failure.
  • GUI services do not receive WM_QUERYENDSESSION/WM_ENDSESSION messages at logoff and shutdown; instead, they receive CTRL_LOGOFF_EVENT and CTRL_SHUTDOWN_EVENT events. These services are not terminated by the system at logoff.

Article ID: 115825 - Last Review: 02/28/2014 07:55:07 - Revision: 2.1

Microsoft Win32 Application Programming Interface

  • kbnosurvey kbarchive KB115825