Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Cet article vous aide à résoudre le problème où l’application à instance unique se bloque si l’application utilise WindowsFormsApplicationBase.
Version du produit d’origine : Visual C#, Visual Basic.NET
Numéro de base de connaissances d’origine : 2834636
Symptômes
Vous avez une seule instance Visual Basic.NET application ou une application C# qui utilise la WindowsFormsApplicationBase classe pour rendre l’instance unique de l’application et vous exécutez l’application comme dans un environnement avec IP Virtualization activée. L’application peut se bloquer. si un débogueur est attaché à l’application, vous remarquerez que l’exception est CantStartSingleInstanceException.
Cause
Cela est dû au fait que le Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase type n’est pas conçu pour s’exécuter dans un environnement avec la virtualisation IP activée.
Résolution
Pour contourner ce problème, vous pouvez utiliser un nom mutex ou énumérer tous les processus et voir si une instance précédente de l’application est en cours d’exécution et l’active.
Exemple de code qui utilise un mutex nommé
Note
Si vous utilisez un nom mutex pour limiter votre application à une seule instance, un utilisateur malveillant peut le créer mutex avant de commencer et empêcher votre application de démarrer. Pour éviter cette situation, créez un nom aléatoire mutex et stockez le nom afin qu’il puisse uniquement être obtenu par un utilisateur autorisé. Vous pouvez également utiliser un fichier à cet effet. Pour limiter votre application à une instance par utilisateur, créez un fichier verrouillé dans le répertoire de profil de l’utilisateur.
Code Visual C#
[STAThread] public static void Main() { bool prevInstance; _ = new System.Threading.Mutex(true, "Application Name", out prevInstance); if (prevInstance == false) { MessageBox.Show("There is another instance running"); return; } Application.Run(new Form1()); }Code .NET Visual Basic
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
Exemple de code qui énumère les processus pour voir si une instance précédente est en cours d’exécution et l’active
Code Visual C#
[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 ()); }Code .NET Visual Basic
<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
Plus d’informations
Pour plus d’informations, consultez Vérifier que seule une seule instance d’une application .NET est en cours d’exécution.