Click here to Skip to main content
15,885,309 members
Articles / Programming Languages / C#

Checking for a Running Instance

Rate me:
Please Sign up or sign in to vote.
0.00/5 (No votes)
4 Oct 2010CPOL2 min read 9.3K  
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:

C#
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:

C#
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:

C#
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:

C#
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:

C#
        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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) Salem Web Network
United States United States
Robert Williams has been programming web sites since 1996 and employed as .NET developer since its release in 2002.

Comments and Discussions

 
-- There are no messages in this forum --