views:

108

answers:

4

I'm writing an application that is able to run as a service or standalone but I want to detect if the application was executed as a service or in a normal user session.

+2  A: 
Sorin Sbarnea
Well if you are right then EVERYTHING on my machine is a service ... everything has a SessionID of 0.
Goz
That's only going to work starting with Vista; under Windows 2000 and XP, the first interactive session is 0.
Luke
I think they changed this on Windows XP SP2.
Sorin Sbarnea
+1  A: 

I think you can query the process token for membership in the Interactive group.

From http://support.microsoft.com/kb/243330:

SID: S-1-5-4

Name: Interactive

Description: A group that includes all users that have logged on interactively. Membership is controlled by the operating system.

Call GetTokenInformation with TokenGroups to get the groups associated with the account under which the process is running, then iterate over the sids looking for the Interactive sid.

I found a nice chunk of code at http://marc.info/?l=openssl-dev&m=104401851331452&w=2

Luke
A: 

Another option would be to use System.Environment.UserInteractive http://msdn.microsoft.com/en-us/library/system.environment.userinteractive.aspx

Update: To make up for posting a .NET answer to a C++ topic, I provide a C implementation based on the .NET implementation.

BOOL IsUserInteractive()
{
   BOOL bIsUserInteractive = TRUE;

   HWINSTA hWinStation = GetProcessWindowStation();
   if (hWinStation != NULL)
   {     
     USEROBJECTFLAGS uof = {0};     
     if (GetUserObjectInformation(hWinStation, UOI_FLAGS, &uof, sizeof(USEROBJECTFLAGS), NULL) && ((uof.dwFlags & WSF_VISIBLE) == 0))
     {
       bIsUserInteractive = FALSE;
     }     
   }
   return bIsUserInteractive;
}
Chris Taylor
This is .NET :p
bogdan
@bogdan, oops sorry, a moment of identity crisis there :) BTW. the .NET implementation does something similar to what Serwood Hu suggest, except that it checks the dwFlags member of the USEROBJECTFLAGS if WSF_VISIBLE is set then it is an interactive user session.
Chris Taylor
A: 

Process in normal user session always has a window station called WinSta0.

wchar_t buffer[256] = {0};
DWORD length = 0;
GetUserObjectInformation(GetProcessWindowStation(), UOI_NAME, buffer, 256, &length);
if (!lstricmp(buffer, "WinSta0")) {
  // normal user session
} else {
  // service session
}
Sherwood Hu