views:

601

answers:

7

Is there a way for an .NET library to detect whether or not it is being run as a service?

My library can be run either way. But when its run as a service, developers need to call an additional method indicating that fact or certain features won't work correctly. I want my library, which handles logging, to write a warning if it is used in a service without that method being called.

+1  A: 

You should probably check that you are running in session zero (at least if you are targeting Vista). You can use WTSRegisterSessionNotification, like in this sample:

  [DllImport("kernel32.dll")]
  private static extern int WTSGetActiveConsoleSessionId();
Pierre
That's a good API call you can use to make a guess but there can be non-service apps running in session 0 as well as services.
Stephen Martin
Yes, indeed. You are right. A non-interactive executable launched by the task scheduler would land there too.
Pierre
That sounds like a good thing to me. Any of the stuff I don't wnat services to do I probably don't want non-interactive tasks doing either.
Jonathan Allen
+2  A: 

There isn't really any way to tell if your library is running in the context of a service or not though you can use Environment.UserInteractive to make a guess.

But generally a library should never depend on its application context. A library should provide services to an application and if it requires different parameters depending on how it is called it should require the application to provide those parameters.

Your library probably does not act differently strictly based on whether or not it is hosted within a service but rather there is some information about the service environment or user that your library needs to be informed of. The application should inform the library of the necessary conditions or information, the library should not guess on its own.

EDIT: I'd upvote the comments on your question if I could. Use overloaded methods if necessary and/or simply fail if all the information necessary is not provided.

Stephen Martin
Knowing in what context your app is running is relevant if you need to do work on disk and you care what your default working directory is. Although I suppose you could just hard-code the path.
Tim Keating
A: 

One way is to have a look at the user context of your application. If you see that it is running as the "SYSTEM" user, then you are running as a service (or at least with service-level permissions).

Brian
Many, if not most, services do not run (or shouldn't run) as the SYSTEM user so this wouldn't really help. Also, non-service applications can be running as the SYSTEM user.
Stephen Martin
Yes, this wouldn't work. You can, in the configuration of a Windows Service, specify an account that the service should run as.
Drew Noakes
A: 

How do you start the exe as a service?

cookre
Here is a good start to learn about Windows Serviceshttp://msdn.microsoft.com/en-us/library/y817hyb6(VS.80).aspx
kenny
+6  A: 

After much searching through intellisense, the debugger, and documentation we weren't able to find anything strictly reliable. It may be possible to get the current process Id and try to find out if that process is registered with the SCM, but while .NET provides a way to get a collection of all the services, their process Ids are not among the information available. Comparing the process name to service names is possible but not necessarily reliable.

However, there are two things that are relatively easy to check and may suffice for the distinction you need, if not exactly "Is this code running as a service?"

System.Environment.UserInteractive : (as Stephen Martin noted) If this is true, it can't be a service. And most processes which are not a service (nor a device driver) will say true. Some console apps may say false when run in non-interactive circumstances such as part of a build process.

System.Diagnostics.Process.GetCurrentProcess().SessionId : (which I think is the same thing Pierre was getting at) If this is not 0, it was not started as a service. Most normal applications will not be in session 0 (with some not-so-normal exceptions as noted by Pierre and Stephen). The biggest question is how this behaves under an older OS such as XP or before. XP and Windows 2000 apparently have services running in session 0, but normal applications will be in session 0 as well. Some configurations of XP (eg. not in a domain) allow multiple user sessions at the same time and they each get a different session id, but the first one gets session 0. So it's not as effective a check prior to Vista.

So, depending on what you actually need to distinguish, one or both of these checks might work for you.

Rob Parker
A: 

A quick and dirty way is to apply a command line switch to the entry in the registry under HKLM\System\CurrentControlSet\services\MyService\ImagePath and then check for that switch in your main function.

You then know if you were started by services.exe or not. Yeah it's a hack.

joveha
A: 

The answer by 0xA3 to this question actually contains C# code to query the SCM, much like Rob Parker describes in his answer.

Tim Keating