Utilise un Mutex pour éviter que plusieurs instances d'un même programme en cours d'exécution en sécurité?
Je suis en utilisant ce code pour éviter une deuxième instance de mon programme en cours d'exécution dans le même temps, est-il sûr?
Mutex appSingleton = new System.Threading.Mutex(false, "MyAppSingleInstnceMutx");
if (appSingleton.WaitOne(0, false)) {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
appSingleton.Close();
} else {
MessageBox.Show("Sorry, only one instance of MyApp is allowed.");
}
Je suis inquiet que si quelque chose déclenche une exception et l'application se bloque que le Mutex sera toujours tenue. Est-ce vrai?
- S'il vous plaît ajouter un lien vers stackoverflow.com/questions/229565/...
Vous devez vous connecter pour publier un commentaire.
En général oui cela fonctionnera. Cependant, le diable est dans les détails.
Tout d'abord, vous voulez fermer le mutex dans un
finally
bloc. Sinon votre processus pourrait se terminer brusquement et le laisser dans un état signalé, comme une exception. Qu'allait-il faire en sorte que les futures instances de processus ne serait pas en mesure de démarrer.Malheureusement, même avec un
finally
bloc vous devez traiter avec le potentiel qu'un processus sera terminé sans libérer le mutex. Cela peut arriver par exemple si un utilisateur supprime le processus via le gestionnaire des tâches. Il est une condition de concurrence dans votre code, ce qui permettrait une deuxième processus pour obtenir unAbandonedMutexException
dans leWaitOne
appel. Vous aurez besoin d'un programme de rétablissement pour cette.Je vous encourage à lire sur les détails de la classe Mutex. L'aide il n'est pas toujours simple.
Étendre sur la condition de la course possibilité:
La séquence suivante d'événements peuvent se produire qui serait la cause d'une deuxième instance de l'application à lancer:
WaitOne
appel.AbanonedMutexException
.Il est plus courant et facile à utiliser de Windows activités à cette fin. E. g.
Lors de votre processus s'arrête ou se termine, Windows va fermer le cas pour vous, et de le détruire si aucune poignées restent.
Ajouté: pour gérer les sessions, l'utilisation
Local\
etGlobal\
préfixes pour l'événement (ou mutex) nom. Si votre demande est par utilisateur, ajoutez simplement un appareil de déformation de l'utilisateur connecté nom le nom de l'événement.Vous pouvez utiliser un mutex, mais assurez-vous d'abord que c'est vraiment ce que vous voulez.
Parce que "en évitant de multiples instances" n'est pas clairement défini. Il peut signifier
À l'aide d'un mutex, vous êtes essentiellement en utilisant le définir le nombre 4.
J'utilise cette méthode, je crois qu'il est en sécurité parce que le Mutex est détruit si le pas de temps retenu par n'importe quelle application (et les applications sont fin si si ils ne peuvent pas créer la Mutext). Cela peut ou peut ne pas fonctionner de manière identique dans le 'domaine d'application-processus" (voir lien en bas):
Ci-dessus souffre de notes dans les autres réponses/commentaires sur les programmes malveillants d'être en mesure de s'asseoir sur un mutex. Pas une préoccupation ici. Aussi, unprefixed mutex créé en "Local" de l'espace. C'est probablement le-droit-chose ici.
Voir: http://ayende.com/Blog/archive/2008/02/28/The-mysterious-life-of-mutexes.aspx - est livré avec Jon Skeet 😉
Sur Windows, l'arrêt d'un processus a les résultats suivants:
Mutex les objets sont les objets de noyau, de sorte que tout détenu par un processus sont fermés lorsque le processus se termine (sous Windows en tout cas).
Mais, note le bit suivant de la CreateMutex() docs:
Oui, c'est sûr, je vous suggère le schéma suivant, parce que vous avez besoin pour vous assurer que le
Mutex
obtient toujours sorti.Voici l'extrait de code
Si vous souhaitez utiliser un mutex approche, vous devriez vraiment utiliser un local mutex pour restreindre l'approche de la juste de l'actuelle session de l'utilisateur de la session. Et notez aussi l'autre mise en garde importante de cette liaison sur les ressources solide et l'élimination des déchets avec le mutex approche.
Une mise en garde est que l'une basée sur les mutex approche ne permet pas d'activer la première instance de l'application lorsqu'un utilisateur tente de lancer une seconde instance.
Une alternative est de PInvoke à FindWindow suivie par SetForegroundWindow sur la première instance. Une autre alternative est de vérifier pour votre processus par nom:
De ces alternatives ont une hypothétique situation de concurrence où les deux instances de l'application pourrait être lancé en même temps et puis de détecter les uns des autres. Il est peu probable de se produire dans la pratique - en fait, pendant les tests, je ne pouvais pas y arriver.
Un autre problème avec ces deux dernières alternatives, c'est qu'ils ne fonctionnent pas lorsque vous utilisez les Services Terminal server.
Utiliser l'application avec le délai d'attente et les paramètres de sécurité en évitant AbandonedMutexException. J'ai utilisé ma classe personnalisée:
et de l'utiliser:
Voici comment j'ai abordé cette
Dans le Programme de la classe:
1. Obtenir un Système.Diagnostics.Processus de VOTRE application à l'aide de Processus.Fonction getcurrentprocess()
2. Parcourir la collection de processus avec le nom actuel de votre application à l'aide de Processus.GetProcessesByName(thisProcess.ProcessName)
3. Vérifier chaque processus.Id contre thisProcess.Id et si une instance est déjà ouvert alors au moins 1 correspondance de nom mais pas d'Id, sinon continuer à l'ouverture de l'instance
Une belle touche pour terminer ce serait de présenter le déjà ouvert instance de l'utilisateur, les chances sont qu'ils ne savaient pas que c'était ouvert, donc, nous allons leur montrer qu'il était. Pour ce faire j'utilise User32.dll pour la Diffusion d'un message dans la messagerie de Windows boucle, un message personnalisé, et j'ai mon application écouter dans la méthode WndProc, et si il reçoit ce message, il se présente à l'utilisateur, de la Forme.Show() ou autres joyeusetés