Afin de n'autoriser qu'une seule instance d'une application en cours d'exécution, j'utilise mutex. Le code est donné ci-dessous. Est-ce que c'est la bonne façon de le faire? Y a-t-il des défauts dans le code?
Comment afficher l'application déjà en cours d'exécution lorsque l'utilisateur essaie d'ouvrir l'application la deuxième fois. À l'heure actuelle (dans le code ci-dessous), j'affiche simplement un message qu'une autre instance est déjà en cours d'exécution.
static void Main(string[] args)
{
Mutex _mut = null;
try
{
_mut = Mutex.OpenExisting(AppDomain.CurrentDomain.FriendlyName);
}
catch
{
//handler to be written
}
if (_mut == null)
{
_mut = new Mutex(false, AppDomain.CurrentDomain.FriendlyName);
}
else
{
_mut.Close();
MessageBox.Show("Instance already running");
}
}
Je l'ai fait de cette façon une fois, j'espère que ça aide:
bool createdNew;
Mutex m = new Mutex(true, "myApp", out createdNew);
if (!createdNew)
{
// myApp is already running...
MessageBox.Show("myApp is already running!", "Multiple Instances");
return;
}
static void Main()
{
using(Mutex mutex = new Mutex(false, @"Global\" + appGuid))
{
if(!mutex.WaitOne(0, false))
{
MessageBox.Show("Instance already running");
return;
}
GC.Collect();
Application.Run(new Form1());
}
}
Source: http://odetocode.com/Blogs/scott/archive/2004/08/20/401.aspx
J'utilise ceci:
private static Mutex _mutex;
private static bool IsSingleInstance()
{
_mutex = new Mutex(false, _mutexName);
// keep the mutex reference alive until the normal
//termination of the program
GC.KeepAlive(_mutex);
try
{
return _mutex.WaitOne(0, false);
}
catch (AbandonedMutexException)
{
// if one thread acquires a Mutex object
//that another thread has abandoned
//by exiting without releasing it
_mutex.ReleaseMutex();
return _mutex.WaitOne(0, false);
}
}
public Form1()
{
if (!isSingleInstance())
{
MessageBox.Show("Instance already running");
this.Close();
return;
}
//program body here
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (_mutex != null)
{
_mutex.ReleaseMutex();
}
}
Utilisez l'application avec des paramètres de délai d'attente et de sécurité. J'ai utilisé ma classe personnalisée:
private class SingleAppMutexControl : IDisposable
{
private readonly Mutex _mutex;
private readonly bool _hasHandle;
public SingleAppMutexControl(string appGuid, int waitmillisecondsTimeout = 5000)
{
bool createdNew;
var allowEveryoneRule = new MutexAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null),
MutexRights.FullControl, AccessControlType.Allow);
var securitySettings = new MutexSecurity();
securitySettings.AddAccessRule(allowEveryoneRule);
_mutex = new Mutex(false, "Global\\" + appGuid, out createdNew, securitySettings);
_hasHandle = false;
try
{
_hasHandle = _mutex.WaitOne(waitmillisecondsTimeout, false);
if (_hasHandle == false)
throw new System.TimeoutException();
}
catch (AbandonedMutexException)
{
_hasHandle = true;
}
}
public void Dispose()
{
if (_mutex != null)
{
if (_hasHandle)
_mutex.ReleaseMutex();
_mutex.Dispose();
}
}
}
et l'utiliser:
private static void Main(string[] args)
{
try
{
const string appguid = "{xxxxxxxx-xxxxxxxx}";
using (new SingleAppMutexControl(appguid))
{
Console.ReadLine();
}
}
catch (System.TimeoutException)
{
Log.Warn("Application already runned");
}
catch (Exception ex)
{
Log.Fatal(ex, "Fatal Error on running");
}
}
Jetez un oeil à cette question
Il y a un lien vers cet article: le mutex incompris où l'utilisation d'un mutex est expliquée.
Découvrez l'exemple de code affiché sur cette page
En bref, vous utilisez la surcharge Mutex ctor(bool, string, out bool)
qui vous indique, via un paramètre out, si vous avez obtenu la propriété du mutex nommé. Si vous êtes la première instance, ce paramètre de sortie contiendrait true après l'appel du ctor - auquel cas vous procédez comme d'habitude. Si ce paramètre est faux, cela signifie qu'une autre instance a déjà obtenu la propriété/est en cours d'exécution, auquel cas vous affichez un message d'erreur "Une autre instance est déjà en cours d'exécution." puis quittez gracieusement.