Return to Snippet

Revision: 17437
at August 28, 2011 13:59 by jimfred


Updated Code
Example usage:
   static void Main()
   {
      SingleInstanceCheck.Check();
      ...



Implementation:

/// <summary>
/// This checks for another instance of an app.
/// Use inside Main() by calling SingleInstanceCheck.Check();
/// Include this class as a sibling to Main's class.
/// If another instance of the app is detected, 
/// - A message box appears.
/// - 'this' instance calls Exit.
/// </summary>
/// <example>
///    static void Main()
///    {
///       MyApp.SingleInstanceCheck.Check();
///       Application.EnableVisualStyles();
///       Application.SetCompatibleTextRenderingDefault(false);
///       Application.Run(new Form1());
///    }
/// </example>
public static class SingleInstanceCheck
{
    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool SetForegroundWindow(IntPtr hWnd);
        
    static public void Check()
    {
        // http://snipplr.com/view/19272/ - C#, single-instance-check using mutex
        // http://iridescence.no/post/CreatingaSingleInstanceApplicationinC.aspx
        bool isOwnedHere = false;
        appStartMutex = new System.Threading.Mutex(
            true,
            Application.ProductName,
            out isOwnedHere
        );

        if (!isOwnedHere) // if owned by other process.
        {
            string message = string.Format("There is already a copy of the application {0} running.\n\nClick cancel to exit.", Application.ProductName);

            DialogResult x = MessageBox.Show(message, Application.ProductName + " already running", MessageBoxButtons.OKCancel);

            if (x == DialogResult.Cancel) // Cancel, but show the already-existing process.
            {
                Process me = Process.GetCurrentProcess();
                foreach (Process process in Process.GetProcessesByName(me.ProcessName)) // Debug note: Set Enable the Visual Studio Hosting Process = false.
                {
                    if (process.Id != me.Id) // If the ProcessName matches but the Id doesn't, it's another instance of mine.
                    {
                        SetForegroundWindow(process.MainWindowHandle);
                        break;
                    }
                }
                Environment.Exit(0); // This will kill my instance.
            }
        }
    }

    // volatile is intended to prevent GC. Otherwise, GC.KeepAlive(appStartMutex) might be needed.
    // This appears to be a concern in In release builds but not debug builds.
    static volatile System.Threading.Mutex appStartMutex;

}

Revision: 17436
at August 28, 2011 13:58 by jimfred


Updated Code
Example usage:
   static void Main()
   {
      SingleInstanceCheck.Check();
      ...



Implementation:

  /// <summary>
/// This checks for another instance of an app.
/// Use inside Main() by calling SingleInstanceCheck.Check();
/// Include this class as a sibling to Main's class.
/// If another instance of the app is detected, 
/// - A message box appears.
/// - 'this' instance calls Exit.
/// </summary>
/// <example>
///    static void Main()
///    {
///       Snapshot.SingleInstanceCheck.Check();
///       Application.EnableVisualStyles();
///       Application.SetCompatibleTextRenderingDefault(false);
///       Application.Run(new Form1());
///    }
/// </example>
public static class SingleInstanceCheck
{
    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool SetForegroundWindow(IntPtr hWnd);
        
    static public void Check()
    {
        // http://snipplr.com/view/19272/ - C#, single-instance-check using mutex
        // http://iridescence.no/post/CreatingaSingleInstanceApplicationinC.aspx
        bool isOwnedHere = false;
        appStartMutex = new System.Threading.Mutex(
            true,
            Application.ProductName,
            out isOwnedHere
        );

        if (!isOwnedHere) // if owned by other process.
        {
            string message = string.Format("There is already a copy of the application {0} running.\n\nClick cancel to exit.", Application.ProductName);

            DialogResult x = MessageBox.Show(message, Application.ProductName + " already running", MessageBoxButtons.OKCancel);

            if (x == DialogResult.Cancel) // Cancel, but show the already-existing process.
            {
                Process me = Process.GetCurrentProcess();
                foreach (Process process in Process.GetProcessesByName(me.ProcessName)) // Debug note: Set Enable the Visual Studio Hosting Process = false.
                {
                    if (process.Id != me.Id) // If the ProcessName matches but the Id doesn't, it's another instance of mine.
                    {
                        SetForegroundWindow(process.MainWindowHandle);
                        break;
                    }
                }
                Environment.Exit(0); // This will kill my instance.
            }
        }
    }

    // volatile is intended to prevent GC. Otherwise, GC.KeepAlive(appStartMutex) might be needed.
    // This appears to be a concern in In release builds but not debug builds.
    static volatile System.Threading.Mutex appStartMutex;

}

Revision: 17435
at March 16, 2011 09:13 by jimfred


Updated Code
Example usage:
   static void Main()
   {
      SingleInstanceCheck.Check();
      ...



Implementation:

   // This checks for another instance of an app.
   // Use inside Main() by calling SingleInstanceCheck.Check();
   // Include this class as a sibling to Main's class.
   // If another instance of the app is detected, 
   // - A message box appears.
   // - 'this' instance calls Exit.
   public static class SingleInstanceCheck
   {
      static public void Check()
      {
         // http://snipplr.com/view/19272/ - C#, single-instance-check using mutex
         bool isOwnedHere = false;
         appStartMutex = new System.Threading.Mutex(
             true,
             Application.ProductName,
             out isOwnedHere
         );

         if (!isOwnedHere) // if owned by other process.
         {
            string message = string.Format( "There is already a copy of the application {0} running.\n\nClick cancel to exit.", Application.ProductName );

            DialogResult x = MessageBox.Show( message, Application.ProductName + " already running", MessageBoxButtons.OKCancel );

            if (x == DialogResult.Cancel)
            {
               Environment.Exit(0);
            }
         }
      }

      // volatile is intended to prevent GC. Otherwise, GC.KeepAlive(appStartMutex) might be needed.
      // This appears to be a concern in In release builds but not debug builds.
      static volatile System.Threading.Mutex appStartMutex;


   }

Revision: 17434
at March 16, 2011 09:11 by jimfred


Updated Code
Example usage (in Main()):
         SingleInstanceCheck.Check();


Implementation:

   // This checks for another instance of an app.
   // Use inside Main() by calling SingleInstanceCheck.Check();
   // Include this class as a sibling to Main's class.
   // If another instance of the app is detected, 
   // - A message box appears.
   // - 'this' instance calls Exit.
   public static class SingleInstanceCheck
   {
      static public void Check()
      {
         // http://snipplr.com/view/19272/ - C#, single-instance-check using mutex
         bool isOwnedHere = false;
         appStartMutex = new System.Threading.Mutex(
             true,
             Application.ProductName,
             out isOwnedHere
         );

         if (!isOwnedHere) // if owned by other process.
         {
            string message = string.Format( "There is already a copy of the application {0} running.\n\nClick cancel to exit.", Application.ProductName );

            DialogResult x = MessageBox.Show( message, Application.ProductName + " already running", MessageBoxButtons.OKCancel );

            if (x == DialogResult.Cancel)
            {
               Environment.Exit(0);
            }
         }
      }

      // volatile is intended to prevent GC. Otherwise, GC.KeepAlive(appStartMutex) might be needed.
      // This appears to be a concern in In release builds but not debug builds.
      static volatile System.Threading.Mutex appStartMutex;


   }

Revision: 17433
at August 9, 2010 09:06 by jimfred


Updated Code
Example usage (in Main()):
         SingleInstanceCheck.Check();


Implementation:

   // This checks for another instance of an app.
   // Use inside Main() by calling SingleInstanceCheck.Check();
   // Include this class as a sibling to Main's class.
   // If another instance of the app is detected, 
   // - A message box appears.
   // - 'this' instance calls Exit.
   public static class SingleInstanceCheck
   {
      static public void Check()
      {
         // http://snipplr.com/view/19272/ - C#, single-instance-check using mutex
         bool isOwnedHere = false;
         appStartMutex = new System.Threading.Mutex(
             true,
             Application.ProductName,
             out isOwnedHere
         );

         if (!isOwnedHere) // if owned by other process.
         {

            string message =
               "There is already a copy of the application " +
               Application.ProductName +
               " running. ";

            MessageBox.Show(message);

            Environment.Exit(0);
         }
      }

      // volatile is intended to prevent GC. Otherwise, GC.KeepAlive(appStartMutex) might be needed.
      // This appears to be a concern in In release builds but not debug builds.
      static volatile System.Threading.Mutex appStartMutex;


   }

Revision: 17432
at August 9, 2010 08:58 by jimfred


Updated Code
Example usage (in Main()):
         SingleInstanceCheck.Check();


Implementation:

   // This checks for another instance of an app.
   // Use inside Main() by calling SingleInstanceCheck.Check();
   // Include this class as a sibling to Main's class.
   // If another instance of the app is detected, 
   // [1] that instance is brought to the top 
   // [2] A message box appears.
   // [3] 'this' instance calls Exit.
   public static class SingleInstanceCheck
   {
      static public void Check()
      {
         // http://snipplr.com/view/19272/ - C#, single-instance-check using mutex
         bool isOwnedHere = false;
         appStartMutex = new System.Threading.Mutex(
             true,
             Application.ProductName,
             out isOwnedHere
         );

         if (!isOwnedHere) // if owned by other process.
         {

            string message =
               "There is already a copy of the application " +
               Application.ProductName +
               " running. ";

            MessageBox.Show(message);

            // Get process by process name.
            System.Diagnostics.Process[] procs = System.Diagnostics.Process.GetProcessesByName(Application.ProductName);

            // Verify some assumptions.
            System.Diagnostics.Debug.Assert(procs.Length == 1);
            System.Diagnostics.Debug.Assert(procs[0] != System.Diagnostics.Process.GetCurrentProcess());

            // Bring to the front. 
            BringWindowToTop(procs[0].MainWindowHandle);
            // SetWindowPos(procs[0].MainWindowHandle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);
            SetWindowPos(procs[0].MainWindowHandle, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW | SWP_NOACTIVATE);

            Environment.Exit(0);
         }
      }

      // volatile is intended to prevent GC. Otherwise, GC.KeepAlive(appStartMutex) might be needed.
      // This appears to be a concern in In release builds but not debug builds.
      static volatile System.Threading.Mutex appStartMutex;

      #region pinvoke stuff.

      [System.Runtime.InteropServices.DllImport("user32.dll")]
      private static extern int SetWindowPos(
         IntPtr hwnd, 
         IntPtr hWndInsertAfter, 
         int    x, 
         int    y, 
         int    cx, 
         int    cy, 
         int    wSwpFlags);

      [System.Runtime.InteropServices.DllImport("user32.dll")]
      public static extern int BringWindowToTop(IntPtr hwnd);

      private static IntPtr HWND_TOP = (IntPtr)(0);
      private static IntPtr HWND_TOPMOST = (IntPtr)(-2);
      private static int    SWP_NOSIZE = 0x1;
      private static int    SWP_NOMOVE = 0x2;
      private static int    SWP_SHOWWINDOW = 0x0040;
      private static int    SWP_NOACTIVATE = 0x0010;
      
      #endregion

   }

Revision: 17431
at September 4, 2009 15:01 by jimfred


Initial Code
// Put inside Main() before Application.Run(new MainForm());

#region Single-Instance check

bool isOwned = false;
System.Threading.Mutex appStartMutex = new System.Threading.Mutex(
   true,
   Application.ProductName,
   out isOwned
);

if (!isOwned)
{
   string message = 
      "There is already a copy of the application " +
      Application.ProductName + 
      " running. ";

   MessageBox.Show(message);
   Environment.Exit(0);
}

#endregion

Initial URL
http://www.hanselman.com/blog/TheWeeklySourceCode31SingleInstanceWinFormsAndMicrosoftVisualBasicdll.aspx

Initial Description
Scott Hanselman describes a method of using VB libraries to handle single-instance checking to prevent multiple instances of an app from starting. A mutex seems to be a simpler solution.\r\n\r\nAdd this class as a sibling to Main and then, inside Main, call this static member: SingleInstanceCheck.Check();

Initial Title
C#, single-instance-check using mutex. Implements a static function to be called in Program::Main().

Initial Tags


Initial Language
C#