flobadob
flobadob

Reputation: 2872

WPF mutex for single app instance not working

I'm trying to use the mutex method for only allowing one instance of my app to run. That is - I only want a max of one instance for all users on a machine. I've read through the various other threads on this issue and the solution seems straightforward enough but in testing I can't get my second instance to not run. Here is my code...

public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        // check that there is only one instance of the control panel running...
        bool createdNew = true;
        using (Mutex instanceMutex = new Mutex(true, @"Global\ControlPanel", out createdNew))
        {
            if (!createdNew)
            {
                Application.Current.Shutdown();
                return;
            }
        }

        base.OnStartup(e);
    }
}

Upvotes: 22

Views: 18383

Answers (7)

Faizan
Faizan

Reputation: 11

I was told to implement this mutex approach on an already developed WPF application that we had. The work around to the problem with using override of the OnStart() that I found was in

App.g.cs

This file is located in

obj\x86\debug\

and contains the main() function, so you just simply put this piece of code in your main function.

bool isOnlyInstance = false;
Mutex m = new Mutex(true, @"WpfSingleInstanceApplication", out isOnlyInstance);
if (!isOnlyInstance)
{
    MessageBox.Show("Another Instance of the application is already running.", 
                    "Alert", 
                    MessageBoxButton.OK, 
                    MessageBoxImage.Exclamation);
    return;
}
GC.KeepAlive(m);

but for this you need to keep the BUILD ACTION of your app.xaml set to ApplicationDefinition

NOTE: This might not be the best way, since I'm a beginner. (please tell me if there's something I should change)

Upvotes: 1

Vildi
Vildi

Reputation: 41

As extension sample:

public static class Extension
{
    private static Mutex mutex;

    public static bool IsOneTimeLaunch(this Application application, string uniqueName = null)
    {
        var applicationName = Path.GetFileName(Assembly.GetEntryAssembly().GetName().Name);
        uniqueName = uniqueName ?? string.Format("{0}_{1}_{2}",
            Environment.MachineName,
            Environment.UserName,
            applicationName);

        application.Exit += (sender, e) => mutex.Dispose();
        bool isOneTimeLaunch;
        mutex = new Mutex(true, uniqueName, out isOneTimeLaunch);
        return isOneTimeLaunch;
    }
}

App Class:

    protected override void OnStartup(StartupEventArgs e)
    {
        if (this.IsOneTimeLaunch())
        {
            base.OnStartup(e);
        }
        else
        {
            this.Shutdown();
        }
    }

Upvotes: 4

dnxit
dnxit

Reputation: 7350

I did this from this link just add the given class and a single line in you App.Xaml.cs http://wpfsingleinstance.codeplex.com/

public partial class App : Application    
{
  protected override void OnStartup(StartupEventArgs e) 
  {
        WpfSingleInstance.Make(); //added this is the function of that class 
        base.OnStartup(e);
  }
}

Upvotes: 0

g1ga
g1ga

Reputation: 323

I can suggest a much cleaner approach that also introduce the useful concept of overriding the Main method in WPF application. Also, if using your solution you take a look at the task manager, you will notice that the new instance actually reach the execution state (you can see a new process created in the list of task) and then suddenly close. The approach proposed in the post that follows will avoid this drawback too. http://blog.clauskonrad.net/2011/04/wpf-how-to-make-your-application-single.html

Upvotes: 1

flobadob
flobadob

Reputation: 2872

Here is my new code which has the answer provided by @Willem van Rumpt (and @OJ)...

public partial class App : Application
{
    private Mutex _instanceMutex = null;

    protected override void OnStartup(StartupEventArgs e)
    {
        // check that there is only one instance of the control panel running...
        bool createdNew;
        _instanceMutex = new Mutex(true, @"Global\ControlPanel", out createdNew);
        if (!createdNew)
        {
            _instanceMutex = null;
            Application.Current.Shutdown();
            return;
        }

        base.OnStartup(e);
    }

    protected override void OnExit(ExitEventArgs e)
    {          
        if(_instanceMutex != null)
            _instanceMutex.ReleaseMutex();
        base.OnExit(e);
    }
}

Upvotes: 34

OJ.
OJ.

Reputation: 29401

You're destroying the Mutex immediately after you've created it and tested it. You need to keep the Mutex reference alive for lifetime of your application.

Make the Mutex a member/field of your Application class. Release the mutex when your application shuts down.

Upvotes: 4

Willem van Rumpt
Willem van Rumpt

Reputation: 6570

You're also disposing the mutex in the same method, so the mutex only lives for the duration of the method. Store the mutex in a static field, and keep it alive for the duration of your application.

Upvotes: 45

Related Questions