Мьютекс WPF для одного экземпляра приложения не работает

Я пытаюсь использовать метод mutex только для запуска одного экземпляра моего приложения. То есть - я хочу только максимум одного экземпляра для всех пользователей на машине. Я прочитал различные другие темы по этой проблеме, и решение кажется достаточно простым, но при тестировании я не могу заставить мой второй экземпляр не запускаться. Вот мой код...

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);
    }
}

Ответ 1

Вы также удаляете мьютексы одним и тем же методом, поэтому мьютекс работает только на протяжении всего метода. Храните мьютекс в статическом поле и сохраняйте его в течение всего срока действия вашего приложения.

Ответ 2

Вот мой новый код, в котором есть ответ, предоставленный @Willem van Rumpt (и @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);
    }
}

Ответ 3

Вы уничтожаете Mutex сразу же после его создания и протестировали его. Вам нужно сохранить ссылку Mutex в течение всего жизненного цикла вашего приложения.

Сделать Mutex членом/полем вашего класса Application. Отпустите мьютекс, когда приложение закрывается.

Ответ 4

Как образец расширения:

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;
    }
}

Класс приложения:

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

Ответ 5

Я могу предложить гораздо более чистый подход, который также представляет полезную концепцию переопределения метода Main в приложении WPF. Кроме того, если вы используете свое решение, взгляните на диспетчер задач, вы заметите, что новый экземпляр фактически достигнет состояния выполнения (вы можете увидеть новый процесс, созданный в списке задач), а затем внезапно закрыть. Подход, предложенный в следующей статье, также позволит избежать этого недостатка. http://blog.clauskonrad.net/2011/04/wpf-how-to-make-your-application-single.html

Ответ 6

Мне сказали реализовать этот мьютексовый подход в уже разработанном WPF-приложении, которое у нас было. Работа над проблемой с использованием переопределения OnStart(), который я нашел, находится в

App.g.cs

Этот файл находится в

obj\x86\debug\

и содержит функцию main(), поэтому просто просто поместите этот фрагмент кода в свою основную функцию.

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);

но для этого вам нужно сохранить BUILD ACTION вашего app.xaml в ApplicationDefinition

ПРИМЕЧАНИЕ. Это может быть не самый лучший способ, так как я новичок. (скажите, пожалуйста, если что-то изменилось)

Ответ 7

Я сделал это по этой ссылке, просто добавлю данный класс и одну строку в вас 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);
  }
}