• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 470
  • Last Modified:

Mutex different on debug than on release?

I have made a program that is only supposed to allow 1 copy to run at a time.  Here is the Main()

            [STAThread]
            static void Main()
            {
                  bool mutexWasCreated;

                  Mutex m = new Mutex(true, "PgrRn", out mutexWasCreated);
                  if(!mutexWasCreated)
                  {
                        //
                        // Another instance of the application already exists!
                        //
                        bool ret;
                        IntPtr hWnd = FindWindow(null, "Pgl");
                        if(hWnd != IntPtr.Zero)
                        {
                              ShowWindow(hWnd,9);
                              ret = SetForegroundWindow(hWnd);
                        }
                  }
                  else
                  {
                        Application.EnableVisualStyles();
                        Application.Run(new Form1());
                  }
            
            }

Everything works great in debug mode, but in Release, it allows more than one copy to start.  Hmm...

I'm in a bit of a hurry, so i'll put the points up to 500.

Thank you,
John Gjonola
0
publicvoid
Asked:
publicvoid
  • 2
2 Solutions
 
CeiledCommented:
Huh, now *that* is peculiar. I've never seen anything quite like it. Fortunately, Shawn A. Van Ness has, and he talks about it at http://weblogs.asp.net/savanness/archive/2003/05/23/7496.aspx.

The short version is that putting the Mutex in a using statement (or a number of other things, but this is the most convenient) solves the problem, like so:

[STAThread]
static void Main()
{
      bool mutexWasCreated;

      using (Mutex m = new Mutex(true, "PgrRn", out mutexWasCreated))
      {
            if (!mutexWasCreated)
            {
                  Console.WriteLine("Already there!");
            }
            else
            {
                  Console.WriteLine("Starting...");
                  Application.EnableVisualStyles();
                  Application.Run(new Form1());
            }
      }
}

Very odd, and it looks like it still happens in Whidbey. I'll make sure a bug gets logged over there, if they don't already have one for it.
0
 
CeiledCommented:
For the curious, I did a bit of extra research into it. It looks like what's happening is that, because the variable you created to store the Mutex never gets used after being initialized, the release version doesn't even generate a variable for it. It just creates it on the stack and lets it go away. Hence, a little while later (probably when the system comes under mild memory pressure from creating the Form), it gets GC'd, and when the next instance gets there, the mutex no longer exists.
0
 
YurichCommented:
hello,
just another way with Mutex but a bit different approach, works well with both debug and release versions:

         private static Mutex m;

          [STAThread]
          static void Main()
          {
               m = new Mutex(true, Application.ProductName );
               if(m.WaitOne( 0, false ))
               {
                    Application.EnableVisualStyles();
                    Application.Run(new Form1());
               }
              else
              {
                     // another instance of the application alredy exists,
                     // do all your API stuff to display the form or whatever...
              }
          }

and even more different approach without using Mutex at all:

using System.Diagnostic;
...

[STAThread]
static void Main()
{
      if( CheckProcesses == null )
      {
           Application.EnableVisualStyles();
           Application.Run(new Form1());
       }
       else
       {
              // another instance of the application alredy exists,
              // do all your API stuff to display the form or whatever...
        }
}

public static Process CheckProcesses()
{
     Process current = Process.GetCurrentProcess();
     Process[] processes = Process.GetProcessesByName (current.ProcessName);
 
      //Loop through the running processes with the same names
      foreach (Process process in processes)
      {  
          //Ignore the current process  
           if (process.Id != current.Id)  
          {  
               //Make sure that the process is running from the exe file.  
                if (Assembly.GetExecutingAssembly().Location.Replace("/", "\\") == current.MainModule.FileName)  
                {  
                    //Return the other process instance.  
                    return process;  
                }  
           }  
      }  
      //No other instance was found, return null.  
      return null;  
}  

regards

0
 
publicvoidAuthor Commented:
Thanks guys!  Perfect...
John G.
0

Featured Post

Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now