Anwendung mit einer instanz stürzt ab
Dieser Artikel hilft Ihnen bei der Behebung des Problems, bei dem eine Einzelne-Instanz-Anwendung abstürzt, wenn die Anwendung verwendet WindowsFormsApplicationBase.
Originalversion des Produkts: Visual C#, Visual Basic.NET
Ursprüngliche KB-Nummer: 2834636
Problembeschreibung
Sie haben eine einzelne Instanz Visual Basic.NET-Anwendung oder eine C#-Anwendung, die die WindowsFormsApplicationBase Klasse verwendet, um die Anwendung zu einer einzelnen Instanz zu machen, und Sie führen die Anwendung wie in einer Umgebung aus, in der IP-Virtualisierung aktiviert ist. Die Anwendung kann abstürzen. Wenn ein Debugger an die Anwendung angefügt ist, werden Sie feststellen, dass die Ausnahme ist CantStartSingleInstanceException.
Ursache
Dies liegt daran, dass der Typ nicht für die Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase Ausführung in einer Umgebung mit aktivierter IP-Virtualisierung konzipiert ist.
Lösung
Um dieses Problem zu umgehen, können Sie einen benannten mutex Prozess verwenden oder alle Prozesse auflisten und überprüfen, ob eine frühere Instanz der Anwendung ausgeführt wird, und ihn aktivieren.
Beispielcode, der einen benannten Mutex verwendet
Hinweis
Wenn Sie einen Benannten mutex verwenden, um Ihre Anwendung auf eine einzelne Instanz zu beschränken, kann ein böswilliger Benutzer dies mutex erstellen, bevor Sie dies tun, und verhindern, dass Ihre Anwendung gestartet wird. Um dies zu verhindern, erstellen Sie einen nach dem Zufallsprinzip benannten Namen mutex , und speichern Sie den Namen so, dass er nur von einem autorisierten Benutzer abgerufen werden kann. Alternativ können Sie eine Datei für diesen Zweck verwenden. Um Ihre Anwendung auf eine Instanz pro Benutzer zu beschränken, erstellen Sie eine gesperrte Datei im Profilverzeichnis des Benutzers.
Visual C#-Code
public System.Threading.Mutex mutex; public void main () { bool prevInstance = false; mutex = new System.Threading.Mutex (true, 'Application Name', prevInstance); if ((prevInstance == false)) { MessageBox.Show ('There is another instance running'); return; } Application.Run (new Form1 ()); }Visual Basic .NET-Code
Public mutex As System.Threading.Mutex Public Sub main() Dim prevInstance As Boolean mutex = New System.Threading.Mutex(True, "Application Name", prevInstance) If (prevInstance = False) Then MessageBox.Show("There is another instance running") Return End If Application.Run(New Form1()) End Sub
Beispielcode, der Prozesse aufzählt, um festzustellen, ob eine vorherige Instanz ausgeführt wird, und diese aktiviert
Visual C#-Code
[DllImport ("user32.dll")] private static extern int ShowWindow (IntPtr hWnd, int nCmdShow); [DllImport ("user32.dll")] private static extern int SetForegroundWindow (IntPtr hWnd); [DllImport ("user32.dll")] private static extern int IsIconic (IntPtr hWnd); private const int SW_RESTORE = 9; /// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main () { var processes = System.Diagnostics.Process.GetProcessesByName ("WindowsFormsApplication1"); foreach (System.Diagnostics.Process p in processes) { //Is this the current process? if (System.Diagnostics.Process.GetCurrentProcess ().Id == p.Id) continue; //if the other process is running, we need to activate it and... if (null != p.MainWindowHandle) { if (IsIconic (p.MainWindowHandle) != 0) { ShowWindow (p.MainWindowHandle, SW_RESTORE); } SetForegroundWindow (p.MainWindowHandle); } //...exit this instance. return; } Application.EnableVisualStyles (); Application.SetCompatibleTextRenderingDefault (false); Application.Run (new Form1 ()); }Visual Basic .NET-Code
<DllImport("user32.dll")> _ Private Function ShowWindow(hWnd As IntPtr, nCmdShow As Integer) As Integer End Function <DllImport("user32.dll")> _ Private Function SetForegroundWindow(hWnd As IntPtr) As Integer End Function <DllImport("user32.dll")> _ Private Function IsIconic(hWnd As IntPtr) As Integer End Function Private Const SW_RESTORE As Integer = 9 ''' <summary> ''' The main entry point for the application. ''' </summary> <STAThread> _ Public Sub Main() Dim processes = System.Diagnostics.Process.GetProcessesByName("WindowsApplication1") For Each p As System.Diagnostics.Process In processes 'Is this the current process? If System.Diagnostics.Process.GetCurrentProcess().Id = p.Id Then Continue For End If 'if the other process is running, we need to activate it and... If p.MainWindowHandle = Nothing Then If IsIconic(p.MainWindowHandle) <> 0 Then ShowWindow(p.MainWindowHandle, SW_RESTORE) End If SetForegroundWindow(p.MainWindowHandle) End If '...exit this instance. Return Next Application.EnableVisualStyles() Application.SetCompatibleTextRenderingDefault(False) Application.Run(New Form1()) End Sub
Weitere Informationen
Weitere Informationen finden Sie unter Sicherstellen, dass nur eine einzelne Instanz einer .NET-Anwendung ausgeführt wird.