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.