10

I have a console application that is server based. I only want 1 instance of it running at once for a particular server (this is regardless of the user who might be running it).

I need to add a check to make sure only 1 instance of it is running, I can already do this by checking the running processes on the server, but is this best practice?

Since I am constantly looking for ways to improve coding styles and stay up to date, is there a better way to do this lately? If you're thinking - "If it ain't broke don't fix it", Maybe you're right, but I want to take more advantage of framework built in functionality.

I am using .net v3.5, and this is a console application.

Thanks in advance

Roman Boiko
  • 3,576
  • 1
  • 25
  • 41
JL.
  • 78,954
  • 126
  • 311
  • 459

4 Answers4

14

You should use Mutex class, like explained here: C# .NET Single Instance Application

Rubens Farias
  • 57,174
  • 8
  • 131
  • 162
  • +1 and accepted answer, not sure if you can get a better answer than this. tyvm! – JL. Dec 04 '09 at 12:29
  • Well that took a whole 2 minutes to implement :) – JL. Dec 04 '09 at 12:34
  • One thing I would like to add, I notice the mutex has a guid, does this mean that if a stubborn admin renames the executing exe, it still wont run because the mutex guid is the same in both applications, even the renamed one? – JL. Dec 04 '09 at 12:36
  • That's basically just a string identification code you pick, it can be a guid, or the original full name of your project, or whatever, it just has to be unique so that you won't collide with other applications. – Lasse V. Karlsen Dec 04 '09 at 13:57
4

Took a lot of assembling bits and pieces of code from everywhere, but I finally found the magic sauce that conceptually creates a singleton console app that can also continue to receive command line arguments. So the first time this is ran, it processes its command line params and then waits. When you try to run this again, if the first is still running, those command line arguments are passed to the first process for handling, and the second process dies.

using System;
using System.IO;
using System.IO.Pipes;
using System.Threading;
using System.Threading.Tasks;

namespace SingletonConsoleApp
{
    class Program 
    {
        const string InterprocessID = "{D2D6725E-79C3-4988-8475-4446549B6E6D}"; // can be anything that's unique
        static Mutex appSingletonMaker = new Mutex(true, InterprocessID);

        static void Main(string[] args)
        {
            if (appSingletonMaker.WaitOne(TimeSpan.Zero, true))
            {
                var argHandler = new Action<string[]>((arguments =>
                {
                    Console.WriteLine(String.Join(" ", arguments));
                }));
                Task.Run(() =>
                {
                    using (var server = new NamedPipeServerStream(InterprocessID))
                    {
                        using (var reader = new StreamReader(server))
                        {
                            using (var writer = new StreamWriter(server))
                            {
                                while (true)
                                {
                                    server.WaitForConnection();
                                    var incomingArgs = reader.ReadLine().Split('\t');
                                    writer.WriteLine("done");
                                    writer.Flush();
                                    server.Disconnect();
                                    argHandler(incomingArgs);
                                }
                            }
                        }
                    }
                });
                argHandler(args);
                Console.ReadKey();
                appSingletonMaker.ReleaseMutex();
            }
            else
            {
                if (args.Length > 0)
                {
                    using (var client = new NamedPipeClientStream(InterprocessID))
                    {
                        client.Connect();
                        var writer = new StreamWriter(client);
                        using (var reader = new StreamReader(client))
                        {
                            writer.WriteLine(String.Join("\t", args));
                            writer.Flush();
                            reader.ReadLine();
                        }
                    }
                }
            }
        }
    }
}
Sean
  • 2,531
  • 2
  • 17
  • 17
2

What is the correct way to create a single instance application has some ways to do this, including the article mentioned above

Community
  • 1
  • 1
SwDevMan81
  • 48,814
  • 22
  • 151
  • 184
-1

Check this minimalistic console app project

Yordan Georgiev
  • 5,114
  • 1
  • 56
  • 53