views:

189

answers:

6

I have two applications, a WinForms app and a Windows Service that will both run on the same machine. I want the WinForms app to reliably detect when the service is running. I have complete control over the design and implementation of both applications.

My first thought is to use a Mutex, instantiated by the Service and detectable by the WinForms App.

Is there a better design?

A: 

similar question [according to the answers there, you're on the right track]

laginimaineb
Similar, but that question is about two instances of the same app.
Ed Guiness
I stand corrected (though it's the same concept).
laginimaineb
+3  A: 

Mutex is the way to go. It's a lot less fragile than using process names etc.

However, you need to make sure the Mutex isn't garbage collected. In the case of a service (which is event driven rather than having a "main" method which runs to completion), the most sensible way of doing this is probably to put it in a static variable.

Dispose of the mutex when the service stops, so you don't need to wait for finalization or anything like that.

Jon Skeet
+7  A: 

K. Scott Allen has a good write up on using a Mutex for this purpose and issues you'll run into with the GC.

If I want to have only one instance of the application running across all sessions on the machine, I can put the named mutex into the global namespace with the prefix “Global\”.

[STAThread]
static void Main() 
{
   using(Mutex mutex = new Mutex(false, "Global\\" + appGuid))
   {
      if(!mutex.WaitOne(0, false))
      {
         MessageBox.Show("Instance already running");
         return;
      }

      Application.Run(new Form1());
   }
}

EDIT: Changed string literal to use escaped backslash instead of @, SO syntax highlighter didn't like the verbatim string.

Matthew Brindley
What for is the GC.Collect(); ?
tanascius
Oh, I believe he was demonstrating that even if the GC collected at that point, the mutex still wouldn't be disposed (and therefore released) - I'll edit to avoid confusion. Thanks for pointing that out.
Matthew Brindley
A good write-up about a similar (but different) problem.
Ed Guiness
A: 

As an alternative, your WinForms app can check the list of running services to see if the service is running.

Thomas L Holaday
I discounted this approach since we would need to use the volatile name of the process therefore it would be a more fragile design than the alternatives.
Ed Guiness
+1  A: 

You can implement some "Connection Test"-functionality on the service. I don't know if this will work for your requirements though. At the winforms startup, you can make a call to the service to see if it is alive. You can expose the service with a simple WCF contract.

Hope this helps...

Roel
Thanks Roel, except when the service isn't running this approach becomes more complicated than simply checking for a Mutex.
Ed Guiness
It has the possible advantage that when the service has started, created the mutex, and subsequently suffered some damage leaving it unresponsive, your WinForms app will learn the bad news promptly. Compare to ping, where the pinger does not really care exactly why the pingee is down.
Thomas L Holaday
+2  A: 

You could use a Mutex but you could also use the ServiceController class instead. This would allow you to find out if the service is installed, and if it is but isn't started then start it if applicable.

http://msdn.microsoft.com/en-us/library/system.serviceprocess.servicecontroller_members.aspx

samjudson
Nice idea. 12345
Ed Guiness