Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Este artículo le ayuda a resolver el problema en el que la aplicación de instancia única se bloquea si la aplicación usa WindowsFormsApplicationBase
.
Versión original del producto: Visual C#, Visual Basic.NET
Número de KB original: 2834636
Síntomas
Tiene una aplicación de Visual Basic.NET de instancia única o una aplicación de C# que usa la WindowsFormsApplicationBase
clase para convertir la instancia única de la aplicación y está ejecutando la aplicación como en un entorno con la virtualización de IP activada. La aplicación puede bloquearse. Si un depurador está asociado a la aplicación, observará que la excepción es CantStartSingleInstanceException
.
Causa
Esto se debe a que el Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase
tipo no está diseñado para ejecutarse en un entorno con la virtualización de IP activada.
Solución
Para solucionar este problema, puede usar un denominado mutex
o enumerar todos los procesos y ver si una instancia anterior de la aplicación se está ejecutando y activarla.
Código de ejemplo que usa una exclusión mutua con nombre
Nota:
Si usa un nombre mutex
para limitar la aplicación a una sola instancia, un usuario malintencionado puede crearlo mutex
antes de hacerlo y evitar que la aplicación se inicie. Para evitar esta situación, cree un nombre mutex
aleatorio y almacene el nombre para que solo pueda obtenerlo un usuario autorizado. Como alternativa, puede usar un archivo para este propósito. Para limitar la aplicación a una instancia por usuario, cree un archivo bloqueado en el directorio de perfil del usuario.
Código de 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()); }
Código de .NET de 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
Código de ejemplo que enumera los procesos para ver si se está ejecutando una instancia anterior y la activa
Código de 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 ()); }
Código de .NET de 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
Más información
Para obtener más información, consulte Asegurarse de que solo se está ejecutando una sola instancia de una aplicación .NET.