Se bloquea la aplicación de instancia única
Este artículo le ayuda a resolver el problema por 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 única instancia Visual Basic aplicación.NET o una aplicación de C# que usa la WindowsFormsApplicationBase clase para que la aplicación sea una instancia única y que ejecute 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 ip activada.
Solución
Para solucionar este problema, puede usar un objeto con nombre mutex o enumerar todos los procesos y ver si se está ejecutando una instancia anterior de la aplicación 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 e impedir que se inicie la aplicación. Para evitar esta situación, cree un nombre mutex aleatorio y almacene el nombre para que solo lo pueda obtener 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#
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 código de .NET
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 ()); }Visual Basic código de .NET
<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, vea Asegurarse de que solo se está ejecutando una única instancia de una aplicación .NET.