Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

Mutex Process Identifier

4.90/5 (9 votes)
23 Jul 2010CPOL1 min read 49.8K   536  
A simple workaround for identifying the owner process of a mutex.

Introduction

A few days ago, I was making a simple application and I needed to find a way to prevent multiple instances of it to run. Googled a bit, and found the Mutex-way. In addition, if an instance of my application was already running, I needed to "find" it in order to bring its main window to the front. The problem was that I didn't know which process represented the already-opened application instance. Finding the process that owns the opened Mutex would have solved the problem. Again, Googled a bit more, but found no solution, so I had to figure it out myself. I came up with a simple workaround, and thought it would be nice to post the solution here for whoever needs it.

Background

The attached zip, as its name suggests, contains the source of an application that illustrates the idea. The project needs to be opened with Visual Studio 2010.

Using the code

The idea is to include the PID of the running application instance in the Mutex's unique name. The Mutex's name has the format <our_unique_string>+<current_Application_PID>.

The unique string can be any string that you can think of, as long as you make sure that its uniqueness is strong enough to avoid cases in which other running applications create Mutex-es with a similar name as your application's.

So, first of all, when we open the application, we search for a Mutex that respects our format.

In order to do so, we need to get the IDs of the currently opened processes, and check if a Mutex with the name <our_unique_string>+<current_PID> was created.

Here's the code (Program.cs):

C#
[DllImport("user32.dll")]
private static extern int ShowWindow(IntPtr hWnd, int nCmdShow);
[DllImport("user32.dll")]
private static extern int SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll")]
private static extern int IsIconic(IntPtr hWnd);

[STAThread]
static void Main()
{
    Process[] runningProcesses = Process.GetProcesses();
    //get current running processes
    bool InstanceRunning = false;
    //this field will show us if an instance is already running
    long runningId = 50000;
    //here we hold the PID of the eventual running instance
    foreach (Process p in runningProcesses)
    {
        try
        {
            Mutex newinstanceMutex = 
              Mutex.OpenExisting("Global\\MUTEXPIDBYCHYROPTERON" + p.Id.ToString());
             //we check if a Mutex that respects our format is already created
            try
            {
                newinstanceMutex.ReleaseMutex();
            }
            catch { }
            InstanceRunning = true;
            //if the upper Mutex.OpenExisting succeeds, a mutex is already created, so
            //an instance signaling the searched mutex is already running
            runningId = p.Id;
            break;
        }
        catch { }
    }
    if (!InstanceRunning)
    {
        Mutex currentMutex = new Mutex(true, 
          "Global\\MUTEXPIDBYCHYROPTERON" + 
          Process.GetCurrentProcess().Id.ToString());
        //if no instance is running we create a new "signaling" Mutex
        //as you can see, the unique string that I chose
        //is "Global\\MUTEXPIDBYCHYROPTERON"
        currentMutex.ReleaseMutex();
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        MutexPID_ mainFrm = new MutexPID_();
        Application.Run(mainFrm);
    }
    else
    {
        //this code execution occurs if a running application instance was found
        IntPtr winHandle = Process.GetProcessById((int)runningId).MainWindowHandle;
        //we now bring the process with PID = runningID to front
        if (winHandle != IntPtr.Zero)
        {
            const int SW_RESTORE = 9;
            if (IsIconic(winHandle) != 0) ShowWindow(winHandle, SW_RESTORE);
            SetForegroundWindow(winHandle);
        }
        Environment.Exit(0);
    }
}

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)