¿Cuál es la forma correcta de crear una aplicación de instancia única?

Usando C # y WPF bajo .NET (en lugar de Windows Forms o consola), ¿cuál es la forma correcta de crear una aplicación que solo se puede ejecutar como una sola instancia?

Sé que tiene algo que ver con algo mítico llamado mutex, rara vez puedo encontrar a alguien que se moleste en detenerse y explicarme cuál es.

El código también debe informar a la instancia en ejecución que el usuario intentó iniciar una segunda, y tal vez también pasar cualquier argumento de la línea de comandos si existiera.

Aquí hay un artículo muy bueno sobre la solución Mutex. El enfoque descrito por el artículo es ventajoso por dos razones.

Primero, no requiere una dependencia en el ensamblado Microsoft.VisualBasic. Si mi proyecto ya tenía una dependencia en esa asamblea, probablemente recomendaría usar el enfoque que se muestra en la respuesta aceptada. Pero tal como están las cosas, no uso el ensamblado Microsoft.VisualBasic, y prefiero no agregar una dependencia innecesaria a mi proyecto.

En segundo lugar, el artículo muestra cómo llevar la instancia existente de la aplicación al primer plano cuando el usuario intenta iniciar otra instancia. Es un toque muy agradable que las otras soluciones Mutex descritas aquí no abordan.


ACTUALIZAR

A partir del 8/1/2014, el artículo que he vinculado anteriormente todavía está activo, pero el blog no se ha actualizado desde hace tiempo. Eso me preocupa que eventualmente desaparezca, y con eso, la solución recomendada. Estoy reproduciendo el contenido del artículo aquí para la posteridad. Las palabras pertenecen únicamente al propietario del blog en Sanity Free Coding .

Hoy quería refacturar algunos códigos que prohibían que mi aplicación ejecutara varias instancias de sí mismo.

Anteriormente había usado System.Diagnostics.Process para buscar una instancia de my myapp.exe en la lista de procesos. Mientras esto funciona, genera muchos gastos generales y quería algo más limpio.

Sabiendo que podría usar un mutex para esto (pero nunca lo había hecho antes) me propuse reducir mi código y simplificar mi vida.

En la clase de mi aplicación principal, creé una estática llamada Mutex :

static class Program { static Mutex mutex = new Mutex(true, "{8F6F0AC4-B9A1-45fd-A8CF-72F04E6BDE8F}"); [STAThread] ... } 

Tener un mutex con nombre nos permite astackr la sincronización a través de múltiples hilos y procesos, que es la magia que estoy buscando.

Mutex.WaitOne tiene una sobrecarga que especifica una cantidad de tiempo para que esperemos. Como en realidad no queremos sincronizar nuestro código (más solo verifique si está actualmente en uso) usamos la sobrecarga con dos parámetros: Mutex.WaitOne (Timespan timeout, bool exitContext) . Wait one devuelve true si es capaz de ingresar, y false si no es así. En este caso, no queremos esperar; Si se utiliza nuestro mutex, sáltelo y continúe, entonces pasamos en TimeSpan.Zero (espere 0 milisegundos) y establecemos el exitContext en verdadero para poder salir del contexto de sincronización antes de tratar de obtener un locking. Al usar esto, envolvemos nuestro código Application.Run dentro de algo como esto:

 static class Program { static Mutex mutex = new Mutex(true, "{8F6F0AC4-B9A1-45fd-A8CF-72F04E6BDE8F}"); [STAThread] static void Main() { if(mutex.WaitOne(TimeSpan.Zero, true)) { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form1()); mutex.ReleaseMutex(); } else { MessageBox.Show("only one instance at a time"); } } } 

Por lo tanto, si nuestra aplicación se está ejecutando, WaitOne devolverá falso y obtendremos un cuadro de mensaje.

En lugar de mostrar un cuadro de mensaje, opté por utilizar un pequeño Win32 para notificar a mi instancia en ejecución que alguien olvidó que ya se estaba ejecutando (al colocarse en la parte superior de todas las otras ventanas). Para lograr esto, utilicé PostMessage para transmitir un mensaje personalizado a cada ventana (el mensaje personalizado fue registrado con RegisterWindowMessage por mi aplicación en ejecución, lo que significa que solo mi aplicación sabe de qué se trata) y luego sale mi segunda instancia. La instancia de la aplicación en ejecución recibiría esa notificación y la procesaría. Para hacer eso, superé WndProc en mi formulario principal y escuché mi notificación personalizada. Cuando recibí esa notificación, establecí la propiedad TopMost del formulario en verdadero para que aparezca en la parte superior.

Aquí es a lo que terminé:

  • Program.cs
 static class Program { static Mutex mutex = new Mutex(true, "{8F6F0AC4-B9A1-45fd-A8CF-72F04E6BDE8F}"); [STAThread] static void Main() { if(mutex.WaitOne(TimeSpan.Zero, true)) { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form1()); mutex.ReleaseMutex(); } else { // send our Win32 message to make the currently running instance // jump on top of all the other windows NativeMethods.PostMessage( (IntPtr)NativeMethods.HWND_BROADCAST, NativeMethods.WM_SHOWME, IntPtr.Zero, IntPtr.Zero); } } } 
  • NativeMethods.cs
 // this class just wraps some Win32 stuff that we're going to use internal class NativeMethods { public const int HWND_BROADCAST = 0xffff; public static readonly int WM_SHOWME = RegisterWindowMessage("WM_SHOWME"); [DllImport("user32")] public static extern bool PostMessage(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam); [DllImport("user32")] public static extern int RegisterWindowMessage(string message); } 
  • Form1.cs (parte frontal parcial)
 public partial class Form1 : Form { public Form1() { InitializeComponent(); } protected override void WndProc(ref Message m) { if(m.Msg == NativeMethods.WM_SHOWME) { ShowMe(); } base.WndProc(ref m); } private void ShowMe() { if(WindowState == FormWindowState.Minimized) { WindowState = FormWindowState.Normal; } // get our current "TopMost" value (ours will always be false though) bool top = TopMost; // make our form jump to the top of everything TopMost = true; // set it back to whatever it was TopMost = top; } } 

Podría usar la clase Mutex, pero pronto descubrirá que necesitará implementar el código para pasar los argumentos y usted mismo. Bueno, aprendí un truco al progtwigr en WinForms cuando leo el libro de Chris Sell . Este truco usa la lógica que ya está disponible para nosotros en el marco. No sé ustedes, pero cuando aprendo cosas que puedo reutilizar en el marco, esa es generalmente la ruta que tomo en lugar de reinventar la rueda. A menos, por supuesto, que no haga todo lo que quiero.

Cuando ingresé a WPF, se me ocurrió una manera de usar el mismo código, pero en una aplicación WPF. Esta solución debe satisfacer sus necesidades en función de su pregunta.

Primero, necesitamos crear nuestra clase de aplicación. En esta clase vamos a sobreescribir el evento OnStartup y crear un método llamado Activar, que se usará más adelante.

 public class SingleInstanceApplication : System.Windows.Application { protected override void OnStartup(System.Windows.StartupEventArgs e) { // Call the OnStartup event on our base class base.OnStartup(e); // Create our MainWindow and show it MainWindow window = new MainWindow(); window.Show(); } public void Activate() { // Reactivate the main window MainWindow.Activate(); } } 

Segundo, necesitaremos crear una clase que pueda administrar nuestras instancias. Antes de pasar por eso, de hecho vamos a reutilizar algún código que está en el ensamblado Microsoft.VisualBasic. Como, estoy usando C # en este ejemplo, tuve que hacer una referencia al ensamblaje. Si está usando VB.NET, no tiene que hacer nada. La clase que vamos a usar es WindowsFormsApplicationBase y heredaremos nuestro administrador de instancias y luego aprovecharemos las propiedades y eventos para manejar la instancia única.

 public class SingleInstanceManager : Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase { private SingleInstanceApplication _application; private System.Collections.ObjectModel.ReadOnlyCollection _commandLine; public SingleInstanceManager() { IsSingleInstance = true; } protected override bool OnStartup(Microsoft.VisualBasic.ApplicationServices.StartupEventArgs eventArgs) { // First time _application is launched _commandLine = eventArgs.CommandLine; _application = new SingleInstanceApplication(); _application.Run(); return false; } protected override void OnStartupNextInstance(StartupNextInstanceEventArgs eventArgs) { // Subsequent launches base.OnStartupNextInstance(eventArgs); _commandLine = eventArgs.CommandLine; _application.Activate(); } } 

Básicamente, estamos utilizando los bits VB para detectar instancias únicas y procesar en consecuencia. OnStartup se disparará cuando se cargue la primera instancia. OnStartupNextInstance se activa cuando la aplicación se vuelve a ejecutar nuevamente. Como puede ver, puedo acceder a lo que pasó en la línea de comando a través de los argumentos del evento. Establecí el valor en un campo de instancia. Puede analizar la línea de comando aquí, o puede pasarla a su aplicación a través del constructor y la llamada al método Activar.

En tercer lugar, es hora de crear nuestro EntryPoint. En lugar de actualizar la aplicación como lo haría normalmente, vamos a aprovechar nuestro SingleInstanceManager.

 public class EntryPoint { [STAThread] public static void Main(string[] args) { SingleInstanceManager manager = new SingleInstanceManager(); manager.Run(args); } } 

Bueno, espero que puedas seguir todo y poder utilizar esta implementación y hacerla tuya.

Desde aquí .

Un uso común para un Mutex de proceso cruzado es garantizar que solo la instancia de un progtwig pueda ejecutarse a la vez. Así es como se hace:

 class OneAtATimePlease { // Use a name unique to the application (eg include your company URL) static Mutex mutex = new Mutex (false, "oreilly.com OneAtATimeDemo"); static void Main() { // Wait 5 seconds if contended – in case another instance // of the program is in the process of shutting down. if (!mutex.WaitOne(TimeSpan.FromSeconds (5), false)) { Console.WriteLine("Another instance of the app is running. Bye!"); return; } try { Console.WriteLine("Running - press Enter to exit"); Console.ReadLine(); } finally { mutex.ReleaseMutex(); } } } 

Una buena característica de Mutex es que si la aplicación finaliza sin que se llame a ReleaseMutex, la CLR lanzará el Mutex automáticamente.

MSDN en realidad tiene una aplicación de ejemplo para C # y VB para hacer exactamente esto: http://msdn.microsoft.com/en-us/library/ms771662(v=VS.90).aspx

La técnica más común y confiable para desarrollar la detección de instancia única es utilizar la infraestructura remota Microsoft .NET Framework (System.Remoting). Microsoft .NET Framework (versión 2.0) incluye un tipo, WindowsFormsApplicationBase, que encapsula la funcionalidad de comunicación remota requerida. Para incorporar este tipo en una aplicación de WPF, se debe derivar un tipo de este, y se debe usar como un ajuste entre el método del punto de entrada estático de la aplicación, Main y el tipo de aplicación de la aplicación WPF. El shim detecta cuándo se lanza una aplicación por primera vez, y cuándo se intentan lanzamientos posteriores, y los rendimientos controlan el tipo de aplicación de WPF para determinar cómo procesar los lanzamientos.

  • Para la gente de C # solo respire profundo y olvídese del todo ‘No quiero incluir VisualBasic DLL’. Por esto y lo que dice Scott Hanselman y el hecho de que esta es la solución más limpia al problema y está diseñada por personas que saben mucho más sobre el marco que usted.
  • Desde el punto de vista de la usabilidad, el hecho es si su usuario está cargando una aplicación y ya está abierta y le está dando un mensaje de error como 'Another instance of the app is running. Bye' 'Another instance of the app is running. Bye' entonces no van a ser un usuario muy feliz. Simplemente DEBE (en una aplicación de GUI) cambiar a esa aplicación y pasar los argumentos proporcionados – o si los parámetros de la línea de comando no tienen significado, entonces debe abrir la aplicación que puede haber sido minimizada.

El framework ya tiene soporte para esto, es solo que un idiota llamado el DLL Microsoft.VisualBasic y no se puso en Microsoft.ApplicationUtils o algo así. Superarlo o abrir Reflector.

Consejo: si usa este enfoque exactamente como está, y ya tiene un App.xaml con recursos, etc. también querrá echar un vistazo a esto .

Este código debe ir al método principal. Mire aquí para obtener más información sobre el método principal en WPF.

 [DllImport("user32.dll")] private static extern Boolean ShowWindow(IntPtr hWnd, Int32 nCmdShow); private const int SW_SHOWMAXIMIZED = 3; static void Main() { Process currentProcess = Process.GetCurrentProcess(); var runningProcess = (from process in Process.GetProcesses() where process.Id != currentProcess.Id && process.ProcessName.Equals( currentProcess.ProcessName, StringComparison.Ordinal) select process).FirstOrDefault(); if (runningProcess != null) { ShowWindow(runningProcess.MainWindowHandle, SW_SHOWMAXIMIZED); return; } } 

Método 2

 static void Main() { string procName = Process.GetCurrentProcess().ProcessName; // get the list of all processes by that name Process[] processes=Process.GetProcessesByName(procName); if (processes.Length > 1) { MessageBox.Show(procName + " already running"); return; } else { // Application.Run(...); } } 

Nota: los métodos anteriores suponen que su proceso / aplicación tiene un nombre único. Porque usa el nombre del proceso para encontrar si hay procesadores existentes. Por lo tanto, si su aplicación tiene un nombre muy común (es decir, el Bloc de notas), el enfoque anterior no funcionará.

Bueno, tengo una Clase desechable para esto que funciona fácilmente para la mayoría de los casos de uso:

Úselo así:

 static void Main() { using (SingleInstanceMutex sim = new SingleInstanceMutex()) { if (sim.IsOtherInstanceRunning) { Application.Exit(); } // Initialize program here. } } 

Aquí está:

 ///  /// Represents a  class. ///  public partial class SingleInstanceMutex : IDisposable { #region Fields ///  /// Indicator whether another instance of this application is running or not. ///  private bool isNoOtherInstanceRunning; ///  /// The  used to ask for other instances of this application. ///  private Mutex singleInstanceMutex = null; ///  /// An indicator whether this object is beeing actively disposed or not. ///  private bool disposed; #endregion #region Constructor ///  /// Initializes a new instance of the  class. ///  public SingleInstanceMutex() { this.singleInstanceMutex = new Mutex(true, Assembly.GetCallingAssembly().FullName, out this.isNoOtherInstanceRunning); } #endregion #region Properties ///  /// Gets an indicator whether another instance of the application is running or not. ///  public bool IsOtherInstanceRunning { get { return !this.isNoOtherInstanceRunning; } } #endregion #region Methods ///  /// Closes the . ///  public void Close() { this.ThrowIfDisposed(); this.singleInstanceMutex.Close(); } public void Dispose() { this.Dispose(true); GC.SuppressFinalize(this); } private void Dispose(bool disposing) { if (!this.disposed) { /* Release unmanaged ressources */ if (disposing) { /* Release managed ressources */ this.Close(); } this.disposed = true; } } ///  /// Throws an exception if something is tried to be done with an already disposed object. ///  ///  /// All public methods of the class must first call this. ///  public void ThrowIfDisposed() { if (this.disposed) { throw new ObjectDisposedException(this.GetType().Name); } } #endregion } 

Una nueva que usa material Mutex e IPC, y también pasa cualquier argumento de línea de comando a la instancia en ejecución, es la aplicación de instancia única de WPF .

Aquí hay un ejemplo que le permite tener una sola instancia de una aplicación. Cuando se cargan nuevas instancias, pasan sus argumentos a la instancia principal que se está ejecutando.

 public partial class App : Application { private static Mutex SingleMutex; public static uint MessageId; private void Application_Startup(object sender, StartupEventArgs e) { IntPtr Result; IntPtr SendOk; Win32.COPYDATASTRUCT CopyData; string[] Args; IntPtr CopyDataMem; bool AllowMultipleInstances = false; Args = Environment.GetCommandLineArgs(); // TODO: Replace {00000000-0000-0000-0000-000000000000} with your application's GUID MessageId = Win32.RegisterWindowMessage("{00000000-0000-0000-0000-000000000000}"); SingleMutex = new Mutex(false, "AppName"); if ((AllowMultipleInstances) || (!AllowMultipleInstances && SingleMutex.WaitOne(1, true))) { new Main(); } else if (Args.Length > 1) { foreach (Process Proc in Process.GetProcesses()) { SendOk = Win32.SendMessageTimeout(Proc.MainWindowHandle, MessageId, IntPtr.Zero, IntPtr.Zero, Win32.SendMessageTimeoutFlags.SMTO_BLOCK | Win32.SendMessageTimeoutFlags.SMTO_ABORTIFHUNG, 2000, out Result); if (SendOk == IntPtr.Zero) continue; if ((uint)Result != MessageId) continue; CopyDataMem = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Win32.COPYDATASTRUCT))); CopyData.dwData = IntPtr.Zero; CopyData.cbData = Args[1].Length*2; CopyData.lpData = Marshal.StringToHGlobalUni(Args[1]); Marshal.StructureToPtr(CopyData, CopyDataMem, false); Win32.SendMessageTimeout(Proc.MainWindowHandle, Win32.WM_COPYDATA, IntPtr.Zero, CopyDataMem, Win32.SendMessageTimeoutFlags.SMTO_BLOCK | Win32.SendMessageTimeoutFlags.SMTO_ABORTIFHUNG, 5000, out Result); Marshal.FreeHGlobal(CopyData.lpData); Marshal.FreeHGlobal(CopyDataMem); } Shutdown(0); } } } public partial class Main : Window { private void Window_Loaded(object sender, RoutedEventArgs e) { HwndSource Source; Source = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle); Source.AddHook(new HwndSourceHook(Window_Proc)); } private IntPtr Window_Proc(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam, ref bool Handled) { Win32.COPYDATASTRUCT CopyData; string Path; if (Msg == Win32.WM_COPYDATA) { CopyData = (Win32.COPYDATASTRUCT)Marshal.PtrToStructure(lParam, typeof(Win32.COPYDATASTRUCT)); Path = Marshal.PtrToStringUni(CopyData.lpData, CopyData.cbData / 2); if (WindowState == WindowState.Minimized) { // Restore window from tray } // Do whatever we want with information Activate(); Focus(); } if (Msg == App.MessageId) { Handled = true; return new IntPtr(App.MessageId); } return IntPtr.Zero; } } public class Win32 { public const uint WM_COPYDATA = 0x004A; public struct COPYDATASTRUCT { public IntPtr dwData; public int cbData; public IntPtr lpData; } [Flags] public enum SendMessageTimeoutFlags : uint { SMTO_NORMAL = 0x0000, SMTO_BLOCK = 0x0001, SMTO_ABORTIFHUNG = 0x0002, SMTO_NOTIMEOUTIFNOTHUNG = 0x0008 } [DllImport("user32.dll", SetLastError=true, CharSet=CharSet.Auto)] public static extern uint RegisterWindowMessage(string lpString); [DllImport("user32.dll")] public static extern IntPtr SendMessageTimeout( IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam, SendMessageTimeoutFlags fuFlags, uint uTimeout, out IntPtr lpdwResult); } 

Solo algunos pensamientos: hay casos en que se requiere que solo una instancia de una aplicación no sea “coja”, como algunos quisieran hacer creer. Las aplicaciones de bases de datos, etc. son más difíciles en un orden de magnitud si se permiten múltiples instancias de la aplicación para que un solo usuario acceda a una base de datos (ya sabes, todo eso actualizando todos los registros abiertos en múltiples instancias de la aplicación en los usuarios) máquina, etc.). En primer lugar, para el tema de “colisión de nombres”, no use un nombre legible por humanos: use un GUID en su lugar o, mejor aún, un GUID + el nombre humano legible. Las posibilidades de colisión de nombres simplemente desaparecieron del radar y al Mutex no le importa Como alguien señaló, un ataque DOS apestaría, pero si la persona maliciosa se ha tomado la molestia de obtener el nombre mutex e incorporarlo en su aplicación, de todos modos es un objective y tendrá que hacer MUCHO más para proteger usted mismo que simplemente virar un nombre mutex. Además, si uno usa la variante de: nuevo Mutex (verdadero, “algún GUID más nombre”, fuera AIsFirstInstance), ya tiene su indicador en cuanto a si el Mutex es o no la primera instancia.

El código C # .NET Aplicación de instancia única que es la referencia para la respuesta marcada es un gran comienzo.

Sin embargo, encontré que no maneja muy bien los casos en que la instancia que ya existe tiene un cuadro de diálogo modal abierto, si ese diálogo es uno administrado (como otro formulario como un cuadro sobre) o no administrado (como el OpenFileDialog incluso cuando se usa la clase .NET estándar). Con el código original, el formulario principal se activa, pero el modal permanece inactivo, lo que parece extraño, además el usuario debe hacer clic en él para seguir usando la aplicación.

Por lo tanto, he creado una clase de utilidad SingleInstance para manejar todo esto de manera muy automática para las aplicaciones Winforms y WPF.

Winforms :

1) modificar la clase del progtwig de esta manera:

 static class Program { public static readonly SingleInstance Singleton = new SingleInstance(typeof(Program).FullName); [STAThread] static void Main(string[] args) { // NOTE: if this always return false, close & restart Visual Studio // this is probably due to the vshost.exe thing Singleton.RunFirstInstance(() => { SingleInstanceMain(args); }); } public static void SingleInstanceMain(string[] args) { // standard code that was in Main now goes here Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form1()); } } 

2) modificar la clase de ventana principal de esta manera:

 public partial class Form1 : Form { public Form1() { InitializeComponent(); } protected override void WndProc(ref Message m) { // if needed, the singleton will restre this window Program.Singleton.OnWndProc(this, m, true); // TODO: handle specific messages here if needed base.WndProc(ref m); } } 

WPF:

1) modifique la página de la aplicación como esta (y asegúrese de establecer su acción de comstackción en la página para poder redefinir el método principal):

 public partial class App : Application { public static readonly SingleInstance Singleton = new SingleInstance(typeof(App).FullName); [STAThread] public static void Main(string[] args) { // NOTE: if this always return false, close & restart Visual Studio // this is probably due to the vshost.exe thing Singleton.RunFirstInstance(() => { SingleInstanceMain(args); }); } public static void SingleInstanceMain(string[] args) { // standard code that was in Main now goes here App app = new App(); app.InitializeComponent(); app.Run(); } } 

2) modificar la clase de ventana principal de esta manera:

 public partial class MainWindow : Window { private HwndSource _source; public MainWindow() { InitializeComponent(); } protected override void OnSourceInitialized(EventArgs e) { base.OnSourceInitialized(e); _source = (HwndSource)PresentationSource.FromVisual(this); _source.AddHook(HwndSourceHook); } protected virtual IntPtr HwndSourceHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) { // if needed, the singleton will restre this window App.Singleton.OnWndProc(hwnd, msg, wParam, lParam, true, true); // TODO: handle other specific message return IntPtr.Zero; } 

Y aquí está la clase de utilidad:

 using System; using System.ComponentModel; using System.Runtime.InteropServices; using System.Threading; namespace SingleInstanceUtilities { public sealed class SingleInstance { private const int HWND_BROADCAST = 0xFFFF; [DllImport("user32.dll")] private static extern bool PostMessage(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam); [DllImport("user32.dll", CharSet = CharSet.Unicode)] private static extern int RegisterWindowMessage(string message); [DllImport("user32.dll")] private static extern bool SetForegroundWindow(IntPtr hWnd); public SingleInstance(string uniqueName) { if (uniqueName == null) throw new ArgumentNullException("uniqueName"); Mutex = new Mutex(true, uniqueName); Message = RegisterWindowMessage("WM_" + uniqueName); } public Mutex Mutex { get; private set; } public int Message { get; private set; } public void RunFirstInstance(Action action) { RunFirstInstance(action, IntPtr.Zero, IntPtr.Zero); } // NOTE: if this always return false, close & restart Visual Studio // this is probably due to the vshost.exe thing public void RunFirstInstance(Action action, IntPtr wParam, IntPtr lParam) { if (action == null) throw new ArgumentNullException("action"); if (WaitForMutext(wParam, lParam)) { try { action(); } finally { ReleaseMutex(); } } } public static void ActivateWindow(IntPtr hwnd) { if (hwnd == IntPtr.Zero) return; FormUtilities.ActivateWindow(FormUtilities.GetModalWindow(hwnd)); } public void OnWndProc(IntPtr hwnd, int m, IntPtr wParam, IntPtr lParam, bool restrePlacement, bool activate) { if (m == Message) { if (restrePlacement) { WindowPlacement placement = WindowPlacement.GetPlacement(hwnd, false); if (placement.IsValid && placement.IsMinimized) { const int SW_SHOWNORMAL = 1; placement.ShowCmd = SW_SHOWNORMAL; placement.SetPlacement(hwnd); } } if (activate) { SetForegroundWindow(hwnd); FormUtilities.ActivateWindow(FormUtilities.GetModalWindow(hwnd)); } } } #if WINFORMS // define this for Winforms apps public void OnWndProc(System.Windows.Forms.Form form, int m, IntPtr wParam, IntPtr lParam, bool activate) { if (form == null) throw new ArgumentNullException("form"); if (m == Message) { if (activate) { if (form.WindowState == System.Windows.Forms.FormWindowState.Minimized) { form.WindowState = System.Windows.Forms.FormWindowState.Normal; } form.Activate(); FormUtilities.ActivateWindow(FormUtilities.GetModalWindow(form.Handle)); } } } public void OnWndProc(System.Windows.Forms.Form form, System.Windows.Forms.Message m, bool activate) { if (form == null) throw new ArgumentNullException("form"); OnWndProc(form, m.Msg, m.WParam, m.LParam, activate); } #endif public void ReleaseMutex() { Mutex.ReleaseMutex(); } public bool WaitForMutext(bool force, IntPtr wParam, IntPtr lParam) { bool b = PrivateWaitForMutext(force); if (!b) { PostMessage((IntPtr)HWND_BROADCAST, Message, wParam, lParam); } return b; } public bool WaitForMutext(IntPtr wParam, IntPtr lParam) { return WaitForMutext(false, wParam, lParam); } private bool PrivateWaitForMutext(bool force) { if (force) return true; try { return Mutex.WaitOne(TimeSpan.Zero, true); } catch (AbandonedMutexException) { return true; } } } // NOTE: don't add any field or public get/set property, as this must exactly map to Windows' WINDOWPLACEMENT structure [StructLayout(LayoutKind.Sequential)] public struct WindowPlacement { public int Length { get; set; } public int Flags { get; set; } public int ShowCmd { get; set; } public int MinPositionX { get; set; } public int MinPositionY { get; set; } public int MaxPositionX { get; set; } public int MaxPositionY { get; set; } public int NormalPositionLeft { get; set; } public int NormalPositionTop { get; set; } public int NormalPositionRight { get; set; } public int NormalPositionBottom { get; set; } [DllImport("user32.dll", SetLastError = true)] private static extern bool SetWindowPlacement(IntPtr hWnd, ref WindowPlacement lpwndpl); [DllImport("user32.dll", SetLastError = true)] private static extern bool GetWindowPlacement(IntPtr hWnd, ref WindowPlacement lpwndpl); private const int SW_SHOWMINIMIZED = 2; public bool IsMinimized { get { return ShowCmd == SW_SHOWMINIMIZED; } } public bool IsValid { get { return Length == Marshal.SizeOf(typeof(WindowPlacement)); } } public void SetPlacement(IntPtr windowHandle) { SetWindowPlacement(windowHandle, ref this); } public static WindowPlacement GetPlacement(IntPtr windowHandle, bool throwOnError) { WindowPlacement placement = new WindowPlacement(); if (windowHandle == IntPtr.Zero) return placement; placement.Length = Marshal.SizeOf(typeof(WindowPlacement)); if (!GetWindowPlacement(windowHandle, ref placement)) { if (throwOnError) throw new Win32Exception(Marshal.GetLastWin32Error()); return new WindowPlacement(); } return placement; } } public static class FormUtilities { [DllImport("user32.dll")] private static extern IntPtr GetWindow(IntPtr hWnd, int uCmd); [DllImport("user32.dll", SetLastError = true)] private static extern IntPtr SetActiveWindow(IntPtr hWnd); [DllImport("user32.dll")] private static extern bool IsWindowVisible(IntPtr hWnd); [DllImport("kernel32.dll")] public static extern int GetCurrentThreadId(); private delegate bool EnumChildrenCallback(IntPtr hwnd, IntPtr lParam); [DllImport("user32.dll")] private static extern bool EnumThreadWindows(int dwThreadId, EnumChildrenCallback lpEnumFunc, IntPtr lParam); private class ModalWindowUtil { private const int GW_OWNER = 4; private int _maxOwnershipLevel; private IntPtr _maxOwnershipHandle; private bool EnumChildren(IntPtr hwnd, IntPtr lParam) { int level = 1; if (IsWindowVisible(hwnd) && IsOwned(lParam, hwnd, ref level)) { if (level > _maxOwnershipLevel) { _maxOwnershipHandle = hwnd; _maxOwnershipLevel = level; } } return true; } private static bool IsOwned(IntPtr owner, IntPtr hwnd, ref int level) { IntPtr o = GetWindow(hwnd, GW_OWNER); if (o == IntPtr.Zero) return false; if (o == owner) return true; level++; return IsOwned(owner, o, ref level); } public static void ActivateWindow(IntPtr hwnd) { if (hwnd != IntPtr.Zero) { SetActiveWindow(hwnd); } } public static IntPtr GetModalWindow(IntPtr owner) { ModalWindowUtil util = new ModalWindowUtil(); EnumThreadWindows(GetCurrentThreadId(), util.EnumChildren, owner); return util._maxOwnershipHandle; // may be IntPtr.Zero } } public static void ActivateWindow(IntPtr hwnd) { ModalWindowUtil.ActivateWindow(hwnd); } public static IntPtr GetModalWindow(IntPtr owner) { return ModalWindowUtil.GetModalWindow(owner); } } } 

So many answers to such a seemingly simple question. Just to shake things up a little bit here is my solution to this problem.

Creating a Mutex can be troublesome because the JIT-er only sees you using it for a small portion of your code and wants to mark it as ready for garbage collection. It pretty much wants to out-smart you thinking you are not going to be using that Mutex for that long. In reality you want to hang onto this Mutex for as long as your application is running. The best way to tell the garbage collector to leave you Mutex alone is to tell it to keep it alive though out the different generations of garage collection. Ejemplo:

 var m = new Mutex(...); ... GC.KeepAlive(m); 

I lifted the idea from this page: http://www.ai.uga.edu/~mc/SingleInstance.html

It looks like there is a really good way to handle this:

WPF Single Instance Application

This provides a class you can add that manages all the mutex and messaging cruff to simplify the your implementation to the point where it’s simply trivial.

The following code is my WCF named pipes solution to register a single-instance application. It’s nice because it also raises an event when another instance attempts to start, and receives the command line of the other instance.

It’s geared toward WPF because it uses the System.Windows.StartupEventHandler class, but this could be easily modified.

This code requires a reference to PresentationFramework , and System.ServiceModel .

Uso:

 class Program { static void Main() { var applicationId = new Guid("b54f7b0d-87f9-4df9-9686-4d8fd76066dc"); if (SingleInstanceManager.VerifySingleInstance(applicationId)) { SingleInstanceManager.OtherInstanceStarted += OnOtherInstanceStarted; // Start the application } } static void OnOtherInstanceStarted(object sender, StartupEventArgs e) { // Do something in response to another instance starting up. } } 

Source Code:

 ///  /// A class to use for single-instance applications. ///  public static class SingleInstanceManager { ///  /// Raised when another instance attempts to start up. ///  public static event StartupEventHandler OtherInstanceStarted; ///  /// Checks to see if this instance is the first instance running on this machine. If it is not, this method will /// send the main instance this instance's startup information. ///  /// The application's unique identifier. /// True if this instance is the main instance. public static bool VerifySingleInstace(Guid guid) { if (!AttemptPublishService(guid)) { NotifyMainInstance(guid); return false; } return true; } ///  /// Attempts to publish the service. ///  /// The application's unique identifier. /// True if the service was published successfully. private static bool AttemptPublishService(Guid guid) { try { ServiceHost serviceHost = new ServiceHost(typeof(SingleInstance)); NetNamedPipeBinding binding = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None); serviceHost.AddServiceEndpoint(typeof(ISingleInstance), binding, CreateAddress(guid)); serviceHost.Open(); return true; } catch { return false; } } ///  /// Notifies the main instance that this instance is attempting to start up. ///  /// The application's unique identifier. private static void NotifyMainInstance(Guid guid) { NetNamedPipeBinding binding = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None); EndpointAddress remoteAddress = new EndpointAddress(CreateAddress(guid)); using (ChannelFactory factory = new ChannelFactory(binding, remoteAddress)) { ISingleInstance singleInstance = factory.CreateChannel(); singleInstance.NotifyMainInstance(Environment.GetCommandLineArgs()); } } ///  /// Creates an address to publish/contact the service at based on a globally unique identifier. ///  /// The identifier for the application. /// The address to publish/contact the service. private static string CreateAddress(Guid guid) { return string.Format(CultureInfo.CurrentCulture, "net.pipe://localhost/{0}", guid); } ///  /// The interface that describes the single instance service. ///  [ServiceContract] private interface ISingleInstance { ///  /// Notifies the main instance that another instance of the application attempted to start. ///  /// The other instance's command-line arguments. [OperationContract] void NotifyMainInstance(string[] args); } ///  /// The implementation of the single instance service interface. ///  private class SingleInstance : ISingleInstance { ///  /// Notifies the main instance that another instance of the application attempted to start. ///  /// The other instance's command-line arguments. public void NotifyMainInstance(string[] args) { if (OtherInstanceStarted != null) { Type type = typeof(StartupEventArgs); ConstructorInfo constructor = type.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, Type.EmptyTypes, null); StartupEventArgs e = (StartupEventArgs)constructor.Invoke(null); FieldInfo argsField = type.GetField("_args", BindingFlags.Instance | BindingFlags.NonPublic); Debug.Assert(argsField != null); argsField.SetValue(e, args); OtherInstanceStarted(null, e); } } } } 

You should never use a named mutex to implement a single-instance application (or at least not for production code). Malicious code can easily DoS ( Denial of Service ) your ass…

Here is what I use. It combined process enumeration to perform switching and mutex to safeguard from “active clickers”:

 public partial class App { [DllImport("user32")] private static extern int OpenIcon(IntPtr hWnd); [DllImport("user32.dll")] private static extern bool SetForegroundWindow(IntPtr hWnd); protected override void OnStartup(StartupEventArgs e) { base.OnStartup(e); var p = Process .GetProcessesByName(Process.GetCurrentProcess().ProcessName); foreach (var t in p.Where(t => t.MainWindowHandle != IntPtr.Zero)) { OpenIcon(t.MainWindowHandle); SetForegroundWindow(t.MainWindowHandle); Current.Shutdown(); return; } // there is a chance the user tries to click on the icon repeatedly // and the process cannot be discovered yet bool createdNew; var mutex = new Mutex(true, "MyAwesomeApp", out createdNew); // must be a variable, though it is unused - // we just need a bit of time until the process shows up if (!createdNew) { Current.Shutdown(); return; } new Bootstrapper().Run(); } } 

I found the simpler solution, similar to Dale Ragan’s, but slightly modified. It does practically everything you need and based on the standard Microsoft WindowsFormsApplicationBase class.

Firstly, you create SingleInstanceController class, which you can use in all other single-instance applications, which use Windows Forms:

 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows.Forms; using Microsoft.VisualBasic.ApplicationServices; namespace SingleInstanceController_NET { public class SingleInstanceController : WindowsFormsApplicationBase { public delegate Form CreateMainForm(); public delegate void StartNextInstanceDelegate(Form mainWindow); CreateMainForm formCreation; StartNextInstanceDelegate onStartNextInstance; public SingleInstanceController(CreateMainForm formCreation, StartNextInstanceDelegate onStartNextInstance) { // Set whether the application is single instance this.formCreation = formCreation; this.onStartNextInstance = onStartNextInstance; this.IsSingleInstance = true; this.StartupNextInstance += new StartupNextInstanceEventHandler(this_StartupNextInstance); } void this_StartupNextInstance(object sender, StartupNextInstanceEventArgs e) { if (onStartNextInstance != null) { onStartNextInstance(this.MainForm); // This code will be executed when the user tries to start the running program again, // for example, by clicking on the exe file. } // This code can determine how to re-activate the existing main window of the running application. } protected override void OnCreateMainForm() { // Instantiate your main application form this.MainForm = formCreation(); } public void Run() { string[] commandLine = new string[0]; base.Run(commandLine); } } } 

Then you can use it in your program as follows:

 using System; using System.Collections.Generic; using System.Linq; using System.Windows.Forms; using SingleInstanceController_NET; namespace SingleInstance { static class Program { ///  /// The main entry point for the application. ///  static Form CreateForm() { return new Form1(); // Form1 is used for the main window. } static void OnStartNextInstance(Form mainWindow) // When the user tries to restart the application again, // the main window is activated again. { mainWindow.WindowState = FormWindowState.Maximized; } [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); SingleInstanceController controller = new SingleInstanceController(CreateForm, OnStartNextInstance); controller.Run(); } } } 

Both the program and the SingleInstanceController_NET solution should reference Microsoft.VisualBasic . If you just want to reactivate the running application as a normal window when the user tries to restart the running program, the second parameter in the SingleInstanceController can be null. In the given example, the window is maximized.

Look at the folllowing code. It is a great and simple solution to prevent multiple instances of a WPF application.

 private void Application_Startup(object sender, StartupEventArgs e) { Process thisProc = Process.GetCurrentProcess(); if (Process.GetProcessesByName(thisProc.ProcessName).Length > 1) { MessageBox.Show("Application running"); Application.Current.Shutdown(); return; } var wLogin = new LoginWindow(); if (wLogin.ShowDialog() == true) { var wMain = new Main(); wMain.WindowState = WindowState.Maximized; wMain.Show(); } else { Application.Current.Shutdown(); } } 

Not using Mutex though, simple answer:

 System.Diagnostics; ... string thisprocessname = Process.GetCurrentProcess().ProcessName; if (Process.GetProcesses().Count(p => p.ProcessName == thisprocessname) > 1) return; 

Put it inside the Program.Main() .
Ejemplo :

 using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using System.Windows.Forms; using System.Diagnostics; namespace Sample { static class Program { ///  /// The main entry point for the application. ///  [STAThread] static void Main() { //simple add Diagnostics namespace, and these 3 lines below string thisprocessname = Process.GetCurrentProcess().ProcessName; if (Process.GetProcesses().Count(p => p.ProcessName == thisprocessname) > 1) return; Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Sample()); } } } 

You can add MessageBox.Show to the if -statement and put “Application already running”.
This might be helpful to someone.

Update 2017-01-25. After trying few things, I decided to go with VisualBasic.dll it is easier and works better (at least for me). I let my previous answer just as reference…

Just as reference, this is how I did without passing arguments (which I can’t find any reason to do so… I mean a single app with arguments that as to be passed out from one instance to another one). If file association is required, then an app should (per users standard expectation) be instanciated for each doc. If you have to pass args to existing app, I think I would used vb dll.

Not passing args (just single instance app), I prefer not registering a new Window message and not override the message loop as defined in Matt Davis Solution. Although it’s not a big deal to add a VisualBasic dll, but I prefer not add a new reference just to do single instance app. Also, I do prefer instanciate a new class with Main instead of calling Shutdown from App.Startup override to ensure to exit as soon as possible.

In hope that anybody will like it… or will inspire a little bit 🙂

Project startup class should be set as ‘SingleInstanceApp’.

 public class SingleInstanceApp { [STAThread] public static void Main(string[] args) { Mutex _mutexSingleInstance = new Mutex(true, "MonitorMeSingleInstance"); if (_mutexSingleInstance.WaitOne(TimeSpan.Zero, true)) { try { var app = new App(); app.InitializeComponent(); app.Run(); } finally { _mutexSingleInstance.ReleaseMutex(); _mutexSingleInstance.Close(); } } else { MessageBox.Show("One instance is already running."); var processes = Process.GetProcessesByName(Assembly.GetEntryAssembly().GetName().Name); { if (processes.Length > 1) { foreach (var process in processes) { if (process.Id != Process.GetCurrentProcess().Id) { WindowHelper.SetForegroundWindow(process.MainWindowHandle); } } } } } } } 

WindowHelper:

 using System; using System.Runtime.InteropServices; using System.Windows; using System.Windows.Interop; using System.Windows.Threading; namespace HQ.Util.Unmanaged { public class WindowHelper { [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool SetForegroundWindow(IntPtr hWnd); 

I cant’t find a short Solution here soooo I hope someone will like this:

(Btw. put the code in you’re “Program.cs” )

  using System.Diagnostics; static void Main() { Process ThisProcess = Process.GetCurrentProcess(); Process[] AllProcesses = Process.GetProcessesByName(ThisProcess.ProcessName); if (AllProcesses.Length > 1) { //You could use a MessageBox but then the user could spam this MessageBox. So I just Use: return; } //Following Code is default code: Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new MainForm()); } 

Use mutex solution:

 using System; using System.Windows.Forms; using System.Threading; namespace OneAndOnlyOne { static class Program { static String _mutexID = " // generate guid" ///  /// The main entry point for the application. ///  [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Boolean _isNotRunning; using (Mutex _mutex = new Mutex(true, _mutexID, out _isNotRunning)) { if (_isNotRunning) { Application.Run(new Form1()); } else { MessageBox.Show("An instance is already running."); return; } } } } } 

Here’s a lightweight solution I use which allows the application to bring an already existing window to the foreground without resorting to custom windows messages or blindly searching process names.

 [DllImport("user32.dll")] static extern bool SetForegroundWindow(IntPtr hWnd); static readonly string guid = ""; static void Main() { Mutex mutex = null; if (!CreateMutex(out mutex)) return; // Application startup code. Environment.SetEnvironmentVariable(guid, null, EnvironmentVariableTarget.User); } static bool CreateMutex(out Mutex mutex) { bool createdNew = false; mutex = new Mutex(false, guid, out createdNew); if (createdNew) { Process process = Process.GetCurrentProcess(); string value = process.Id.ToString(); Environment.SetEnvironmentVariable(guid, value, EnvironmentVariableTarget.User); } else { string value = Environment.GetEnvironmentVariable(guid, EnvironmentVariableTarget.User); Process process = null; int processId = -1; if (int.TryParse(value, out processId)) process = Process.GetProcessById(processId); if (process == null || !SetForegroundWindow(process.MainWindowHandle)) MessageBox.Show("Unable to start application. An instance of this application is already running."); } return createdNew; } 

Edit: You can also store and initialize mutex and createdNew statically, but you’ll need to explicitly dispose/release the mutex once you’re done with it. Personally, I prefer keeping the mutex local as it will be automatically disposed of even if the application closes without ever reaching the end of Main.

You can also use the CodeFluent Runtime which is free set of tools. It provides a SingleInstance class to implement a single instance application.

Here’s the same thing implemented via Event.

 public enum ApplicationSingleInstanceMode { CurrentUserSession, AllSessionsOfCurrentUser, Pc } public class ApplicationSingleInstancePerUser: IDisposable { private readonly EventWaitHandle _event; ///  /// Shows if the current instance of ghost is the first ///  public bool FirstInstance { get; private set; } ///  /// Initializes ///  /// The application name /// The single mode public ApplicationSingleInstancePerUser(string applicationName, ApplicationSingleInstanceMode mode = ApplicationSingleInstanceMode.CurrentUserSession) { string name; if (mode == ApplicationSingleInstanceMode.CurrentUserSession) name = $"Local\\{applicationName}"; else if (mode == ApplicationSingleInstanceMode.AllSessionsOfCurrentUser) name = $"Global\\{applicationName}{Environment.UserDomainName}"; else name = $"Global\\{applicationName}"; try { bool created; _event = new EventWaitHandle(false, EventResetMode.ManualReset, name, out created); FirstInstance = created; } catch { } } public void Dispose() { _event.Dispose(); } } 

I added a sendMessage Method to the NativeMethods Class.

Apparently the postmessage method dosent work, if the application is not show in the taskbar, however using the sendmessage method solves this.

 class NativeMethods { public const int HWND_BROADCAST = 0xffff; public static readonly int WM_SHOWME = RegisterWindowMessage("WM_SHOWME"); [DllImport("user32")] public static extern bool PostMessage(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam); [DllImport("user32.dll", CharSet = CharSet.Auto)] public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam); [DllImport("user32")] public static extern int RegisterWindowMessage(string message); } 

Usually whenever we execute an .exe, every time it creates a separate windows process with its own address space, resources and so on. But we do not want this criteria as this would prevent us from creating single process. Single instance applications can be created using the Mutex in C# which is discussed in this article

Moreover if we want to bring the application on top we can do it using

  [DllImport("user32")] static extern IntPtr SetForegroundWindow(IntPtr hWnd); 

Normally, this is the code I use for single-instance Windows Forms applications:

 [STAThread] public static void Main() { String assemblyName = Assembly.GetExecutingAssembly().GetName().Name; using (Mutex mutex = new Mutex(false, assemblyName)) { if (!mutex.WaitOne(0, false)) { Boolean shownProcess = false; Process currentProcess = Process.GetCurrentProcess(); foreach (Process process in Process.GetProcessesByName(currentProcess.ProcessName)) { if (!process.Id.Equals(currentProcess.Id) && process.MainModule.FileName.Equals(currentProcess.MainModule.FileName) && !process.MainWindowHandle.Equals(IntPtr.Zero)) { IntPtr windowHandle = process.MainWindowHandle; if (NativeMethods.IsIconic(windowHandle)) NativeMethods.ShowWindow(windowHandle, ShowWindowCommand.Restore); NativeMethods.SetForegroundWindow(windowHandle); shownProcess = true; } } if (!shownProcess) MessageBox.Show(String.Format(CultureInfo.CurrentCulture, "An instance of {0} is already running!", assemblyName), assemblyName, MessageBoxButtons.OK, MessageBoxIcon.Asterisk, MessageBoxDefaultButton.Button1, (MessageBoxOptions)0); } else { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form()); } } } 

Where native components are:

 [DllImport("User32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static extern Boolean IsIconic([In] IntPtr windowHandle); [DllImport("User32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static extern Boolean SetForegroundWindow([In] IntPtr windowHandle); [DllImport("User32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static extern Boolean ShowWindow([In] IntPtr windowHandle, [In] ShowWindowCommand command); public enum ShowWindowCommand : int { Hide = 0x0, ShowNormal = 0x1, ShowMinimized = 0x2, ShowMaximized = 0x3, ShowNormalNotActive = 0x4, Minimize = 0x6, ShowMinimizedNotActive = 0x7, ShowCurrentNotActive = 0x8, Restore = 0x9, ShowDefault = 0xA, ForceMinimize = 0xB } 

Here is a solution:

 Protected Overrides Sub OnStartup(e As StartupEventArgs) Const appName As String = "TestApp" Dim createdNew As Boolean _mutex = New Mutex(True, appName, createdNew) If Not createdNew Then 'app is already running! Exiting the application MessageBox.Show("Application is already running.") Application.Current.Shutdown() End If MyBase.OnStartup(e) End Sub 

This is how I ended up taking care of this issue. Note that debug code is still in there for testing. This code is within the OnStartup in the App.xaml.cs file. (WPF)

  // Process already running ? if (Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName).Length > 1) { // Show your error message MessageBox.Show("xxx is already running. \r\n\r\nIf the original process is hung up you may need to restart your computer, or kill the current xxx process using the task manager.", "xxx is already running!", MessageBoxButton.OK, MessageBoxImage.Exclamation); // This process Process currentProcess = Process.GetCurrentProcess(); // Get all processes running on the local computer. Process[] localAll = Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName); // ID of this process... int temp = currentProcess.Id; MessageBox.Show("This Process ID: " + temp.ToString()); for (int i = 0; i < localAll.Length; i++) { // Find the other process if (localAll[i].Id != currentProcess.Id) { MessageBox.Show("Original Process ID (Switching to): " + localAll[i].Id.ToString()); // Switch to it... SetForegroundWindow(localAll[i].MainWindowHandle); } } Application.Current.Shutdown(); } 

This may have issues that I have not caught yet. If I run into any I'll update my answer.

Here is my 2 cents

  static class Program { [STAThread] static void Main() { bool createdNew; using (new Mutex(true, "MyApp", out createdNew)) { if (createdNew) { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); var mainClass = new SynGesturesLogic(); Application.ApplicationExit += mainClass.tray_exit; Application.Run(); } else { var current = Process.GetCurrentProcess(); foreach (var process in Process.GetProcessesByName(current.ProcessName).Where(process => process.Id != current.Id)) { NativeMethods.SetForegroundWindow(process.MainWindowHandle); break; } } } } }