Results 1 to 15 of 15

Thread: Creating a Single Instance of your Application

  1. #1

    Thread Starter
    KrisSiegel.com Kasracer's Avatar
    Join Date
    Jul 2003
    Location
    USA, Maryland
    Posts
    4,985

    Cool Creating a Single Instance of your Application

    In VB.Net 2005, there is a simple property to accomplish this. Unfortunately, C# has no such property.

    Now there are many ways to approach this.

    Using a file to determine if the application is running
    Pro: This is very simple. You could simply use a SteamWriter to write something as simple as "true" or "false" to a text file and just parse it on load.
    Con: What happens if your application crashes? You can enclose the entire app in try and catch statements and change the file in a catch or finally block. But what if that crashes? You'd have to impliment some sort of timeout feature which would inevitably lead to bugs in your application where the program thinks its not running when it is and vice versa.

    Checking the list of processes for your application
    Pro: This is one of the most used methods. Basically loading the list of all of the currently running processes and comparing the items in the list to your application's process to count the instances. You can also attempt to get the amount of processes with the name of your application.
    Con: The problem with retrieving all of the running processes is, it can be quite a lot and it usually hurts an application's startup performance. Also, if you get the processes by name, it can be very inaccurate as I can rename every executable on my machine to "MyApp.exe" and in the process list, if I attempt to launch 20 of them, you'll see 20 "MyApp.exe" instances even though none of them are the same application!

    Creating a singleton design
    Pro: This method is outlined on MSDN blogs and works quite well.
    Con: Requires redesign if you're already working on your application and required more time to get working than adding a simple piece of code at the beginning of your project.

    Where does this leave us? MUTEX!
    Pro: A Mutex is a way to share a piece of data amongst threads. With a few lines of code it will accurately let you know if there is more than 1 version of your application running.
    VB Code:
    1. bool firstInstance;
    2. System.Threading.Mutex mutex = new System.Threading.Mutex(false, "Local\\MyAppName", out firstInstance);
    3. if (!firstInstance)
    4. {
    5.     Application.Exit();
    6. }

    I honestly can't find any cons with this code. It's a good idea to declare the mutex as static outside of your Main() method. We need it during the entire running of the application so it stays accurate. Normally you want to release Mutexes but since we need it throughout our entire application, you don't need to worry about it since it'll get cleaned up when your application exists.
    Last edited by Kasracer; Dec 24th, 2007 at 12:49 PM.
    KrisSiegel.com - My Personal Website with my blog and portfolio
    Don't Forget to Rate Posts!

    Free Icons: FamFamFam, VBCorner, VBAccelerator
    Useful Links: System.Security.SecureString Managed DPAPI Overview Part 1 Managed DPAPI Overview Part 2 MSDN, MSDN2, Comparing the Timer Classes

  2. #2
    Software Carpenter dee-u's Avatar
    Join Date
    Feb 2005
    Location
    Pinas
    Posts
    11,123

    Re: Creating a Single Instance of your Application

    Thanks for the code, I can't check it for now and I have a question. For example my exe's name kasracer and ran an instance of it, then renames the exe to deeu and tries to ran it again, does your code handle such scenarios?

    Thanks!
    Regards,


    As a gesture of gratitude please consider rating helpful posts. c",)

    Some stuffs: Mouse Hotkey | Compress file using SQL Server! | WPF - Rounded Combobox | WPF - Notify Icon and Balloon | NetVerser - a WPF chatting system

  3. #3

    Thread Starter
    KrisSiegel.com Kasracer's Avatar
    Join Date
    Jul 2003
    Location
    USA, Maryland
    Posts
    4,985

    Re: Creating a Single Instance of your Application

    Quote Originally Posted by dee-u
    Thanks for the code, I can't check it for now and I have a question. For example my exe's name kasracer and ran an instance of it, then renames the exe to deeu and tries to ran it again, does your code handle such scenarios?

    Thanks!
    Yes it will work correctly if the executables have been renamed. I just tested it to double check and it worked flawlessly
    KrisSiegel.com - My Personal Website with my blog and portfolio
    Don't Forget to Rate Posts!

    Free Icons: FamFamFam, VBCorner, VBAccelerator
    Useful Links: System.Security.SecureString Managed DPAPI Overview Part 1 Managed DPAPI Overview Part 2 MSDN, MSDN2, Comparing the Timer Classes

  4. #4
    Software Carpenter dee-u's Avatar
    Join Date
    Feb 2005
    Location
    Pinas
    Posts
    11,123

    Re: Creating a Single Instance of your Application

    Thanks, I think I tried to play a similar code sometime ago but was unsuccessful when the exe is renamed...
    Regards,


    As a gesture of gratitude please consider rating helpful posts. c",)

    Some stuffs: Mouse Hotkey | Compress file using SQL Server! | WPF - Rounded Combobox | WPF - Notify Icon and Balloon | NetVerser - a WPF chatting system

  5. #5
    Member
    Join Date
    Dec 2004
    Posts
    59

    Re: Creating a Single Instance of your Application

    the mutex concept is correct. but i've put the piece of code at the start in my static void main(), it doesnt seems to work. i still able to open multiple instances. and i've declare the mutex variable as static variable.

  6. #6

    Thread Starter
    KrisSiegel.com Kasracer's Avatar
    Join Date
    Jul 2003
    Location
    USA, Maryland
    Posts
    4,985

    Re: Creating a Single Instance of your Application

    Quote Originally Posted by pelican
    the mutex concept is correct. but i've put the piece of code at the start in my static void main(), it doesnt seems to work. i still able to open multiple instances. and i've declare the mutex variable as static variable.
    You have to declare it outside of Main() as a public static variable (as well as the firstInstance boolean). Then assign it in the Main() method and check firstInstance.
    KrisSiegel.com - My Personal Website with my blog and portfolio
    Don't Forget to Rate Posts!

    Free Icons: FamFamFam, VBCorner, VBAccelerator
    Useful Links: System.Security.SecureString Managed DPAPI Overview Part 1 Managed DPAPI Overview Part 2 MSDN, MSDN2, Comparing the Timer Classes

  7. #7
    Hyperactive Member
    Join Date
    May 2001
    Location
    Köln
    Posts
    395

    Re: Creating a Single Instance of your Application

    Hi

    found this peace of code some time ago.
    works perfect for me

    in Main

    VB Code:
    1. [STAThread]
    2.         static void Main()
    3.         {
    4.             // pass Versionstext into a  static member called m_sApplicationTitle
    5.             Version ver = new Version(Application.ProductVersion);
    6.             m_sApplicationTitle = String.Format("HoRSt .Net 2006 C#{0:#}.{1:#}.{2:#}.", ver.Major, ver.Minor, ver.Build);
    7.            
    8.             // Check if app is runing already
    9.             if (ClassProcessUtils.ThisProcessIsAlreadyRunning())
    10.             {
    11.                 // app is runing therefore set focus on the existing app.
    12.                 ClassProcessUtils.SetFocusToPreviousInstance(m_sApplicationTitle);
    13.             }
    14.             else
    15.             {
    16.                 // Default by VS2005
    17.                 Application.EnableVisualStyles();
    18.                 Application.SetCompatibleTextRenderingDefault(false);
    19.  
    20.                 Application.Run(new FormMain());
    21.             }
    22.         }

    and the following in a new class called ClassProcessUtils

    VB Code:
    1. using System;
    2. using System.Diagnostics;
    3. using System.Threading;
    4. using System.Windows.Forms;
    5. using System.Runtime.InteropServices;
    6.  
    7. namespace HoRSt2006V3
    8. {
    9.     class ClassProcessUtils
    10.     {
    11.         private static Mutex mutex = null;
    12.  
    13.         /// Determine if the current process is already running
    14.         public static bool ThisProcessIsAlreadyRunning()
    15.         {
    16.             // Only want to call this method once, at startup.
    17.             Debug.Assert(mutex == null);
    18.  
    19.             // createdNew needs to be false in .Net 2.0, otherwise, if another instance of
    20.             // this program is running, the Mutex constructor will block, and then throw
    21.             // an exception if the other instance is shut down.
    22.             bool createdNew = false;
    23.  
    24.             mutex = new Mutex(false, Application.ProductName, out createdNew);
    25.  
    26.             Debug.Assert(mutex != null);
    27.  
    28.             return !createdNew;
    29.         }
    30.  
    31.         [DllImport("user32.dll", SetLastError = true)]
    32.         static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
    33.  
    34.         [DllImport("user32.dll")]
    35.         [return: MarshalAs(UnmanagedType.Bool)]
    36.         static extern bool SetForegroundWindow(IntPtr hWnd);
    37.  
    38.         [DllImport("user32.dll")]
    39.         static extern bool IsIconic(IntPtr hWnd);
    40.  
    41.         [DllImport("user32.dll")]
    42.         static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
    43.  
    44.         const int SW_RESTORE = 9;
    45.  
    46.         [DllImport("user32.dll")]
    47.         static extern IntPtr GetLastActivePopup(IntPtr hWnd);
    48.  
    49.         [DllImport("user32.dll")]
    50.         static extern bool IsWindowEnabled(IntPtr hWnd);
    51.  
    52.         /// Set focus to the previous instance of the specified program.
    53.         public static void SetFocusToPreviousInstance(string windowCaption)
    54.         {
    55.             // Look for previous instance of this program.
    56.             IntPtr hWnd = FindWindow(null, windowCaption);
    57.  
    58.             // If a previous instance of this program was found...
    59.             if (hWnd != null)
    60.             {
    61.                 // Is it displaying a popup window?
    62.                 IntPtr hPopupWnd = GetLastActivePopup(hWnd);
    63.  
    64.                 // If so, set focus to the popup window. Otherwise set focus
    65.                 // to the program's main window.
    66.                 if (hPopupWnd != null && IsWindowEnabled(hPopupWnd))
    67.                 {
    68.                     hWnd = hPopupWnd;
    69.                 }
    70.  
    71.                 SetForegroundWindow(hWnd);
    72.  
    73.                 // If program is minimized, restore it.
    74.                 if (IsIconic(hWnd))
    75.                 {
    76.                     ShowWindow(hWnd, SW_RESTORE);
    77.                 }
    78.             }
    79.         }
    80.     }
    81. }

  8. #8

    Thread Starter
    KrisSiegel.com Kasracer's Avatar
    Join Date
    Jul 2003
    Location
    USA, Maryland
    Posts
    4,985

    Re: Creating a Single Instance of your Application

    Bongo, that uses the same technique as I posted, it just puts everything in a class that also declares lots of API functions which I was trying to avoid.

    Still, good snippet though
    KrisSiegel.com - My Personal Website with my blog and portfolio
    Don't Forget to Rate Posts!

    Free Icons: FamFamFam, VBCorner, VBAccelerator
    Useful Links: System.Security.SecureString Managed DPAPI Overview Part 1 Managed DPAPI Overview Part 2 MSDN, MSDN2, Comparing the Timer Classes

  9. #9
    Member
    Join Date
    Jul 2006
    Posts
    41

    Re: Creating a Single Instance of your Application

    tHX for the code.

  10. #10
    New Member
    Join Date
    Jun 2007
    Posts
    1

    Cool Re: Creating a Single Instance of your Application

    Thanks for the code examples!!!

    Works like a charm!!!

  11. #11
    Interweb adm/o/distrator Paul M's Avatar
    Join Date
    Nov 2006
    Location
    Australia, Melbourne
    Posts
    2,306

    Allowing only once instance of your application

    This will only allow one instance of your application, i use this code for a couple of my programs/services...

    Make sure you maker a reference to the System.Management class

    C# Code:
    1. static void Main()
    2.         {
    3.             Application.EnableVisualStyles();
    4.             Application.SetCompatibleTextRenderingDefault(false);
    5.            
    6.             int count = CheckForRunningInstances();
    7.  
    8.             if (count <= 1)
    9.             {
    10.                 Application.Run(new Form1());
    11.             }
    12.             else
    13.             {
    14.                 System.Windows.Forms.MessageBox.Show("Another instance of this program is already running.  Two instances cannot run at the same time", "Already running", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
    15.                 Application.Exit();
    16.             }
    17.  
    18.         }
    19.         private static int CheckForRunningInstances()
    20.         {
    21.  
    22.             string[] parts = System.Reflection.Assembly.GetExecutingAssembly().Location.Split("\\".ToCharArray());
    23.             string appName = parts[parts.Length - 1];
    24.  
    25.             string query = "select name from CIM_Process where name = '" + appName + "'";
    26.  
    27.             System.Management.ManagementObjectSearcher searcher = new System.Management.ManagementObjectSearcher(query);
    28.  
    29.             int hInstCount = 0;
    30.  
    31.             foreach (System.Management.ManagementObject item in searcher.Get())
    32.             {
    33.                 hInstCount++;
    34.                 if (hInstCount > 1) break;
    35.             }
    36.             return hInstCount;
    37.         }
    Last edited by Paul M; Sep 11th, 2007 at 01:40 AM.

  12. #12
    I'm about to be a PowerPoster! kleinma's Avatar
    Join Date
    Nov 2001
    Location
    NJ - USA (Near NYC)
    Posts
    23,373

    Re: Creating a Single Instance of your Application

    kasracer,

    Have you ever looked at any code that does this, but also can send any command line arguments from the second instance that is terminated, to the first instance that was already running?

    It would exist in the "app already open, user double clicks file in windows that is associated with said app, about to be terminated instance needs to tell already open instance to handle the file" category.

    I will go about figuring it out, as I have a need to do this, however I figured I would ask you first since you have this codebank entry.

    In VB 2005, setting the "single instance application" checkbox accomplishes this well, however there is a nasty bug that has to do with that feature and firewall software that I need to try to eliminate. They use .NET remoting to accomplish this in VB 2005, which would not be an option to avoid the bug.

    In 2008 you can used named pipe classes to do this, however the project it is for is not moving to a new framework anytime soon.

    I have also seen some heavy API-centric methods of doing this that basically date back to VB6 but were ported to .NET before the whole single instance checkbox feature existed, however I was looking for a more managed code way first before I resort to direct calls to the Windows API.

  13. #13

    Thread Starter
    KrisSiegel.com Kasracer's Avatar
    Join Date
    Jul 2003
    Location
    USA, Maryland
    Posts
    4,985

    Re: Creating a Single Instance of your Application

    Quote Originally Posted by kleinma
    Have you ever looked at any code that does this, but also can send any command line arguments from the second instance that is terminated, to the first instance that was already running?

    It would exist in the "app already open, user double clicks file in windows that is associated with said app, about to be terminated instance needs to tell already open instance to handle the file" category.

    I will go about figuring it out, as I have a need to do this, however I figured I would ask you first since you have this codebank entry.
    I have not seen any code that can do that. I've looked into it but haven't found an easy way to do so. If you come up with a way or find a way that allows sending of commands to the already opened application without the use of APIs then please share
    KrisSiegel.com - My Personal Website with my blog and portfolio
    Don't Forget to Rate Posts!

    Free Icons: FamFamFam, VBCorner, VBAccelerator
    Useful Links: System.Security.SecureString Managed DPAPI Overview Part 1 Managed DPAPI Overview Part 2 MSDN, MSDN2, Comparing the Timer Classes

  14. #14
    I'm about to be a PowerPoster! kleinma's Avatar
    Join Date
    Nov 2001
    Location
    NJ - USA (Near NYC)
    Posts
    23,373

    Re: Creating a Single Instance of your Application

    Reason I ask, is because there is a bug in the .NET 2.0 framework when using the "single instance application" framework when certain common firewalls are on the system. I have filed a bug with MS about this, and they have confirmed it, but have yet to issue a fix. This is because the framework makes use of remoting to accomplish the single instance application that also can forward command line args from instance to instance. Remoting can be affected by firewalls, even when the remoting is all done locally.

    Bill McCarthy did up a nice example after he saw my bug (he was even nice enough to reference me and the bug), using named pipes to accomplish the same objective, however these new classes are in the .NET 3.5 framework and Visual Studio 2008.

    I have a need for this in .NET 2.0/VS 2005, as I am not migrating these applications anytime soon because they are commercial release, and I had a hard enough time getting everyone up to speed with .NET 2.0

  15. #15

    Thread Starter
    KrisSiegel.com Kasracer's Avatar
    Join Date
    Jul 2003
    Location
    USA, Maryland
    Posts
    4,985

    Re: Creating a Single Instance of your Application

    Quote Originally Posted by kleinma
    Bill McCarthy did up a nice example after he saw my bug (he was even nice enough to reference me and the bug), using named pipes to accomplish the same objective, however these new classes are in the .NET 3.5 framework and Visual Studio 2008.
    Wow, that's a pretty cool way to do this. Thanks for the article!
    Quote Originally Posted by kleinma
    I have a need for this in .NET 2.0/VS 2005, as I am not migrating these applications anytime soon because they are commercial release, and I had a hard enough time getting everyone up to speed with .NET 2.0
    I hear ya. I am in a similar boat as I need my application be to a single instance but still receive arguments.

    The only other option I can think of other than using some Win32 APIs is basically writing a temporary file with the arguments and using something like a FileSystemWatcher to execute those in the single instance application. Unfortunately that creates some extra IO overhead but that's all I can think of for now.
    KrisSiegel.com - My Personal Website with my blog and portfolio
    Don't Forget to Rate Posts!

    Free Icons: FamFamFam, VBCorner, VBAccelerator
    Useful Links: System.Security.SecureString Managed DPAPI Overview Part 1 Managed DPAPI Overview Part 2 MSDN, MSDN2, Comparing the Timer Classes

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width