Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Checking for a Running Instance

0.00/5 (No votes)
4 Oct 2010 1  
How to check for a running instance

Sometimes, you may not want a user to launch multiple instances of your program, or you may have a processor or I/O intensive scheduled task that runs every few minutes and you want to make sure that if it is started again before the last instance has finished, it simply exits immediately. One way to check to see if your program is already running is to look at the list of running processes:

namespace RunningInstance
{
    using System;
    using System.Diagnostics;
    using System.Reflection;
 
    class Program
    {
        static void Main(string[] args)
        {
            if (RunningInstance())
            {
                Console.WriteLine(
                    "Another instance of this process was already running, exiting...");
                return;
            }
 
            // ...
        }
 
        static bool RunningInstance()
        {
            Process current = Process.GetCurrentProcess();
            Process[] processes = Process.GetProcessesByName(current.ProcessName);

            // Loop through the running processes in with the same name
            foreach (Process p in processes)
            {
                // Ignore the current process
                if (p.Id != current.Id)
                {
                    // Make sure that the process is running from the EXE file.
                    if (Assembly.GetExecutingAssembly().Location.Replace("/", @"\") == 
                                                                current.MainModule.FileName)
                    {
                        return true;
                    }
                }
            }

            return false;
        }
    }
}

However, suppose you have a multi function console application that accepts a dozen different command line arguments to perform different jobs, all of which run as separate scheduled tasks at overlapping intervals. If this is the case, then checking the list of running processes may well find your executable already running, but have no idea which command line argument was used to start it. I tried adding:

Console.WriteLine("Instance started with args: '{0}'", p.StartInfo.Arguments);

above the "return true" statement in RunningInstance() but it will not print the command line args used to start it. Let's suppose we add 2 classes to our project. Task1 and Task2. For the sake of simplicity, they both look something like this:

namespace RunningInstance
{
    using System;
    using System.Threading;
 
    public class Task1
    { 
        public void Start()
        {
            Console.WriteLine("Starting Task 1");
        }
    }
}

Task 2 is exactly the same, except it prints "Starting Task 2". If we keep our RunningInstance check in place, Main() now looks like this:

static void Main(string[] args)
{
    if (RunningInstance())
    {
        Console.WriteLine("An instance of this application is already running. Exiting.");
        Console.ReadLine();
        return;
    }
 
    if(args.Length < 1)
    {
        Console.WriteLine("Unrecognized Command.");
        return;
    }
 
    switch (args[0])
    {
        case "-task1":
            var t1 = new Task1();
            t1.Start();
            break;
        case "-task2":
            var t2 = new Task2();
            t2.Start();
            break;
        default:
            Console.WriteLine("Unrecognized Command.");
            break;
    }
}

Task 2 will not run, if task 1 is still running, and vice versa. However, suppose the two tasks are completely unrelated. The first is only a minor chore, that simply counts the number of items marked as "queued" in a database table and sends out an email if the number is too high, while task 2 is a much lengthier process that FTPs files. We may need both of these tasks to run as scheduled, but not want multiple instances of either task to run at the same time. How can we achieve this? We use a Mutex. Mutex is an abbreviation of "Mutual exclusion" and is traditionally used in multi threaded applications to avoid the simultaneous use of a common resource, such as a global variable. After adding a mutex to each task, our final code looks like this:

        static void Main(string[] args)
        { 
            if(args.Length < 1)
            {
                Console.WriteLine("Unrecognized Command.");
                return;
            }
 
            switch (args[0])
            {
                case "-task1":
                    var t1 = new Task1();
                    t1.Start();
                    break;
                case "-task2":
                    var t2 = new Task2();
                    t2.Start();
                    break;
                default:
                    Console.WriteLine("Unrecognized Command.");
                    break;
            }
        }

namespace RunningInstance
{
    using System;
    using System.Threading;
 
    public class Task1
    {
        /// <summary>
        /// Gets the mutex that prevents multiple instances of this code running at once.
        /// </summary>
        private static Mutex mutex1;
 
        public void Start()
        {
            bool createdNew;
            mutex1 = new Mutex(true, "RunningInstance.Task1", out createdNew);
            if (!createdNew)
            {
                // Instance already running; exit.
                Console.WriteLine("Exiting: Instance already running");
                return;
            }
 
            Console.WriteLine("Starting Task 1");
        }
    }
}
 
namespace RunningInstance
{
    using System;
    using System.Threading;
 
    public class Task2
    {
        /// <summary>
        /// Gets the mutex that prevents multiple instances of this code running at once.
        /// </summary>
        private static Mutex mutex1;
 
        public void Start()
        {
            bool createdNew;
            mutex1 = new Mutex(true, "RunningInstance.Task2", out createdNew);
            if (!createdNew)
            {
                // Instance already running; exit.
                Console.WriteLine("Exiting: Instance already running");
                return;
            }
            Console.WriteLine("Starting Task 2");
        }
    }
}

Each Task has its own Mutex, uniquely named. If the mutex already exists, then that code must already be running, so exit, otherwise, run. Couldn't be simpler. By using this particular overload of the constructor, we don't even need to worry about releasing the mutex at the end of the program.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here