Paul Laudeman

Sponsors

The Lounge

Wicked Cool Jobs

News

  • I'm test-driven!
    TestDriven.NET

    MSN Messenger: plaudeman at hotmail dot com

Advertisement

Images in this post missing? We recently lost them in a site migration. We're working to restore these as you read this. Should you need an image in an emergency, please contact us at imagehelp@codebetter.com
Windows Forms Tip: Ensure only one instance of your application is running at a time

In some scenarios, you may wish to ensure that a user can run only one instance of your application at a time. Besides ensuring that only a single instance of your application is running, you may also want to bring the instance already running to the front and restore it, if it is minimized.

First, to ensure that only one instance of your application is running at a time, the best method I've found is to create a mutex that is held by the operating system (thanks to Michael Covington). This will put a request to the operating system that a mutex be created if one does not already exist. Only one mutex can ever be created at a time, so if you request a new one and it cannot be created, you can safely assume that your application is already running.

using System.Threading
using System.Runtime.InteropServices;

public class Form1 : Form
{
     [STAThread]
    
static void Main()
     {
          bool createdNew;

          Mutex m = new Mutex(true, "YourAppName", out createdNew);

          if (! createdNew)
         
{
               // app is already running...
               MessageBox.Show("Only one instance of this application is allowed at a time.");
               return;

          }

          Application.Run(new Form1());

          // keep the mutex reference alive until the normal termination of the program
          GC.KeepAlive(m);
     }
}

The above code will work for the vast majority of your needs. It will also run under scenarios where your code is executing with less than FullTrust permissions (see Code Access Security in MSDN for further information).

If your application can run with Full Trust permissions, we can take this a step further and find the window of the application instnace already running and bring it to the front for the user:

public class Form1 : Form
{
     [STAThread]
    
static void Main()
     {
          bool createdNew;

          System.Threading.Mutex m = new System.Threading.Mutex(true, "YourAppName", out createdNew);

          if (! createdNew)
         
{
               // see if we can find the other app and Bring it to front
              
IntPtr hWnd = FindWindow("WindowsForms10.Window.8.app3", "YourAppName");

               if(hWnd != IntPtr.Zero)
               {
                
   Form1.WINDOWPLACEMENT placement = new Form1.WINDOWPLACEMENT();
                    placement.length = Marshal.SizeOf(placement);

                    GetWindowPlacement(hWnd, ref placement);

                    if(placement.showCmd != SW_NORMAL)
                    {
                         placement.showCmd = SW_RESTORE;

                         SetWindowPlacement(hWnd, ref placement);
                         SetForegroundWindow(hWnd); 

                    }
               }

               return;
          }

          Application.Run(new Form1());

          // keep the mutex reference alive until the normal termination of the program
          GC.KeepAlive(m);
     }

     private const int SW_NORMAL = 1; // see WinUser.h for definitions
     private const int SW_RESTORE = 9;

     [DllImport("User32",EntryPoint="FindWindow")]
     static extern IntPtr FindWindow(string className, string windowName);

     [DllImport("User32",EntryPoint="SendMessage")]
     private static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

     [DllImport("User32",EntryPoint="SetForegroundWindow")]
     private static extern bool SetForegroundWindow(IntPtr hWnd);

     [DllImport("User32",EntryPoint="SetWindowPlacement")]
     private static extern bool SetWindowPlacement(IntPtr hWnd, [In] ref WINDOWPLACEMENT lpwndpl);

     [DllImport("User32",EntryPoint="GetWindowPlacement")]
     private static extern bool GetWindowPlacement(IntPtr hWnd, [In] ref WINDOWPLACEMENT lpwndpl);

     private struct POINTAPI
     {
         
public int x;
         
public int y;
     }

     private struct RECT
     {
          public int left;
         
public int top;
         
public int right;
          public int bottom;
     }

     private struct WINDOWPLACEMENT
     {
          public int length;
          public int flags;
          public int showCmd;
          public POINTAPI ptMinPosition;
          public POINTAPI ptMaxPosition;
          public RECT rcNormalPosition;
     }
}

As you can see, with minimal effort, you can easily add a polished touch to your application. This might even help you avoid some extra legwork in ensuring that there are no issues with running multiple instances of your app at the same time that you might have to address.

For more information about the Platform Invoke mechanisms to call Win32 API functions, I recommend that you check out .NET Framework Solutions: In Search of the Lost Win32 API by John Mueller and Charles Petzold's seminal classic Programming Windows.

Until Longhorn comes out and more of the Windows platform becomes managed, platform invokes and interop will remain a key technology to understand and use to your advantage to fill the gaps left by the Windows Forms framework.

UPDATE:
Visual Studio .NET 2005 (aka. “Whidbey”) will let you specify Single Instance behavior for Visual Basic .NET projects through the Project Properties page. Curious as to why this option is available for VB projects and not for C# projects, as this seems to instruct the runtime or some framework library not to load more than one instance.

Technorati Tags: ,  


Posted Sat, Jul 17 2004 9:15 AM by paul.laudeman
Filed under:

[Advertisement]

Comments

Mark Bonafe wrote re: Windows Forms Tip: Ensure only one instance of your application is running at a time
on Sat, Jul 17 2004 3:04 PM
Nice job Paul! I'll have to mark this page in my favorites list.

But "minimal effort??" <sigh> It's code like this that makes me long for the real minimal effort of:

if App.PrevInstance() then
MsgBox("No can do!")
... code to find and open previous instance
return
endif

hmmm - guess I'm giving away my VB roots.

Seriously, though. Well done! This is a keeper.
Darrell wrote re: Windows Forms Tip: Ensure only one instance of your application is running at a time
on Mon, Jul 19 2004 6:27 AM
This works great for our little client app we all have running.
Michael Weinhardt wrote re: Windows Forms Tip: Ensure only one instance of your application is running at a time
on Mon, Jul 19 2004 11:43 AM
This is a great piece. Thanks for writing it up!
Paul Laudeman wrote re: Windows Forms Tip: Ensure only one instance of your application is running at a time
on Mon, Jul 19 2004 11:46 AM
Hi Michael, thanks for the comment! I've enjoyed reading many of your posts and articles, too!
farn-yu wrote re: Windows Forms Tip: Ensure only one instance of your application is running at a time
on Thu, Aug 12 2004 10:24 AM
Paul, thanks for the article.

In your code, you hardcorded "WindowsForms10.Window.8.app3". Some forms have class name of "WindowsForms10.Window.8.app4".

Do know you know how to check what class a Form is?

Thanks for your help.
Farn-Yu
farn_yu@yahoo.com
Vijay wrote re: Windows Forms Tip: Ensure only one instance of your application is running at a time
on Wed, Jan 5 2005 12:25 PM
Thank you!!! This is a great tip...
David M. Kean wrote re: Windows Forms Tip: Ensure only one instance of your application is running at a time
on Wed, Feb 2 2005 10:50 PM
The reason only VB has single instance behaviour in 2005 is because it is built into the the WindowsApplicationBase class contained in the Microsoft.VisualBasic.dll, C# users could reference it, however it doesn't something similar to what you have done, except that it also uses remoting to pass the command-line arguments to the other instance.
Paul wrote re: Windows Forms Tip: Ensure only one instance of your application is running at a time
on Thu, Feb 3 2005 7:21 AM
David - thanks for the tip! I'll start poking around more in the compatibility library to find the specifics.
Joe wrote re: Windows Forms Tip: Ensure only one instance of your application is running at a time
on Sat, Feb 12 2005 8:10 AM
This is almost exactly what I've been looking for. All that missing is a .net way of bringing the previous instance to the front. The Platform Invoke methods aren't an option in a lot of circumstances, and will tie the code to the Windows platform. I don't really care for the remoting method either as it requires the application to act as a server and listen for messages on an open TCP port. The System.Messaging library is another option if you have MSMQ installed on the PC. There just doesn't seem to be a pure .net way of doing it.
sano the super geek wrote Windows Forms Tip: Ensure only one instance of your application is running at a time
on Wed, Jun 22 2005 1:10 PM
via&amp;nbsp;Paul Laudeman: Ensure that an user can run only one instance of your application at a time.
Abhinaba Basu wrote re: Windows Forms Tip: Ensure only one instance of your application is running at a time
on Thu, Jun 23 2005 12:05 AM
I think a simpler solution would be to do a PInvoke of SendMessage of any custom message after getting the handle and that message handler can bring up the Window to the front. This reduced the number of Win32 APi's used to 2. FindWindow and SendMessage.
Toto wrote hum
on Fri, Jul 29 2005 6:05 AM
DY wrote Problems on Mutex
on Fri, Sep 9 2005 1:32 PM
for this line:
Mutex m = new Mutex(true, "YourAppName", out createdNew);

Does "createdNew" always returns false when a previous mutex was created. My code works ok on WinXP Pro, but when migrated to Win server 2003, it seemd that "createdNew" returns true even on subsequent activation of my winform.
Gaby wrote thanks
on Fri, Sep 16 2005 5:50 PM
Thank you for the info!
Mark wrote re: Windows Forms Tip: Ensure only one instance of your application is running at a time
on Tue, Apr 4 2006 7:03 PM
What about command line arguments? Is there some way to pass those to the running application?
Steve Naughton wrote re: Windows Forms Tip: Ensure only one instance of your application is running at a time
on Tue, Aug 29 2006 4:41 PM

You can also move SetForegroundWindow(hWnd) to outside the if block.  This brings the app to the front whether or not it's normally sized.

Sven wrote re: Windows Forms Tip: Ensure only one instance of your application is running at a time
on Mon, Dec 4 2006 8:51 AM

Hello,

this is gonna not working on CF.

Do you have a solution for Compact Framework 2.0?

Regards

Sven

mehdi wrote re: Windows Forms Tip: Ensure only one instance of your application is running at a time
on Sat, Aug 2 2008 6:21 AM

thanks

frauhotelmann wrote re: Windows Forms Tip: Ensure only one instance of your application is running at a time
on Mon, Aug 18 2008 6:17 AM

For C# in VS2008 I had to modify the first method a little bit. It's still pretty short:

static void Main()

           {

           bool createdNew;

           System.Threading.Mutex m = new System.Threading.Mutex(true, "Your App here", out createdNew);

       if (!createdNew)

       {

           MessageBox.Show("Another instance is already running.");

           return;

       }

       {

           Application.EnableVisualStyles();

           Application.SetCompatibleTextRenderingDefault(false);

           Application.Run(new Form1());

       } GC.KeepAlive(m);                // important!

   }

Works pretty good!

Devlicio.us