Normalerweise verwende ich den folgenden Code für Einzelinstanzen Windows-Formulare Anwendungen:
[STAThread]
public static void Main()
{
String assemblyName = Assembly.GetExecutingAssembly().GetName().Name;
using (Mutex mutex = new Mutex(false, assemblyName))
{
if (!mutex.WaitOne(0, false))
{
Boolean shownProcess = false;
Process currentProcess = Process.GetCurrentProcess();
foreach (Process process in Process.GetProcessesByName(currentProcess.ProcessName))
{
if (!process.Id.Equals(currentProcess.Id) && process.MainModule.FileName.Equals(currentProcess.MainModule.FileName) && !process.MainWindowHandle.Equals(IntPtr.Zero))
{
IntPtr windowHandle = process.MainWindowHandle;
if (NativeMethods.IsIconic(windowHandle))
NativeMethods.ShowWindow(windowHandle, ShowWindowCommand.Restore);
NativeMethods.SetForegroundWindow(windowHandle);
shownProcess = true;
}
}
if (!shownProcess)
MessageBox.Show(String.Format(CultureInfo.CurrentCulture, "An instance of {0} is already running!", assemblyName), assemblyName, MessageBoxButtons.OK, MessageBoxIcon.Asterisk, MessageBoxDefaultButton.Button1, (MessageBoxOptions)0);
}
else
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form());
}
}
}
Wo die einheimischen Komponenten sind:
[DllImport("User32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern Boolean IsIconic([In] IntPtr windowHandle);
[DllImport("User32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern Boolean SetForegroundWindow([In] IntPtr windowHandle);
[DllImport("User32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern Boolean ShowWindow([In] IntPtr windowHandle, [In] ShowWindowCommand command);
public enum ShowWindowCommand : int
{
Hide = 0x0,
ShowNormal = 0x1,
ShowMinimized = 0x2,
ShowMaximized = 0x3,
ShowNormalNotActive = 0x4,
Minimize = 0x6,
ShowMinimizedNotActive = 0x7,
ShowCurrentNotActive = 0x8,
Restore = 0x9,
ShowDefault = 0xA,
ForceMinimize = 0xB
}
17 Stimmen
Gibt die CLR nicht automatisch alle nicht freigegebenen Mutexe frei, wenn die Anwendung ohnehin beendet wird?
2 Stimmen
@Cocowalla: Der Finalisierer sollte die nicht verwalteten Mutexe entsorgen, es sei denn, er kann nicht wissen, ob die Mutex von der verwalteten Anwendung erstellt oder an eine bestehende angehängt wurde.
1 Stimmen
Es ist sinnvoll, nur eine Instanz Ihrer Anwendung zu haben. Aber die Übergabe von Argumenten an eine bereits existierende Anwendung erscheint mir ein wenig albern. Ich kann keinen Grund dafür sehen, dies zu tun. Wenn Sie eine Anwendung mit einer Dateierweiterung verknüpfen, sollten Sie so viele Anwendungen öffnen, wie Benutzer Dokumente öffnen wollen. Das ist das Standardverhalten, das jeder Benutzer erwarten würde.
1 Stimmen
Ich möchte nur eine Korrektur meiner vorherigen Aussage vornehmen. Die Übergabe von Argumenten an eine bestehende Anwendung bedeutet, dass Sie eine MDI (Multi-Document-Interface) durchführen wollen. Ich dachte, dass MDI war eine Art, die Microsoft war drängen aus (Word und Excel sind jetzt SDI). Aber ich habe festgestellt, dass Chrome und IE beide MDI sind. Vielleicht sind wir in Jahren, in denen MDI zurück ist? (Aber ich bevorzuge immer noch SDI gegenüber MDI)
13 Stimmen
@Cocowalla Die CLR verwaltet keine nativen Ressourcen. Wenn ein Prozess jedoch beendet wird, werden alle Handles vom System (dem Betriebssystem, nicht der CLR) freigegeben.
2 Stimmen
Ich bevorzuge die Antwort von @huseyint. Sie verwendet die Microsoft-eigene Klasse 'SingleInstance.cs', so dass man sich keine Gedanken über Mutexe und IntPtrs machen muss. Außerdem besteht keine Abhängigkeit von VisualBasic (igitt). Siehe codereview.stackexchange.com/questions/20871/ für mehr...
1 Stimmen
Ich verwende SingleInstanceApp nuget. nuget.org/packages/SingleInstanceApp Funktioniert perfekt. Benötigt keine Microsoft.VisualBasic-Referenz. Hängt nicht von der App-Version ab (in Microsoft.VisualBasic schon). Die App wird nur durch eine eindeutige Zeichenfolge identifiziert.
0 Stimmen
Es sieht so aus, als ob diese Frage und die Antworten eine Fülle von Informationen enthalten - eine wahre Goldgrube!