0

Here is the article I read http://kristofverbiest.blogspot.com/2008/11/creating-single-instance-application.html, followed the steps by the article, I have the following code, I'm almost sure it can't work and it can't:

static class Program
{
    static Mutex mutex;
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        bool alreadyRun;
        mutex = new Mutex(false, Guid.NewGuid().ToString().Replace("-", ""), out alreadyRun);
        if (!alreadyRun) return;                            
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());            
    }
}

The article says the Mutex name passed in can be random, the MyAppName is just for easy debugging (so I left it out), 'Local//' was also left out. I wonder how it can work? That constructor will succeed and turn alreadyRun true whenever the random GUID string is unique (I mean there hasn't been any Mutex with that name created before). That means, there is a very little chance for alreadyRun becoming false. In fact, I've tried the code above for many times and I could run many instances of my application as I liked.

After trying a fixed string like "unique" for the mutex name , it simply works. However this won't work if there is some another application creating another mutex with the same name. And I now ended up with this solution:

  • We can't use random string, we have to use fixed string and this string should be long and complicated, it is like your password, your id to be sure that there is little chance for any other application to use the same name. Here is an example that I'm sure to say, there is little chance for any other (even a machine) to think of: ilove.netilovejava1234forever56789thismyid_itisevenlongerlongerlonger_howlongcanitbe_maybe8000characters?_canitbeso?

Please explain about the article (looks like it is from a pro blogger) and give me any other solution using Mutex (I've been fed up with using GetProcessesByName, it's not good so far). Thanks!

King King
  • 61,710
  • 16
  • 105
  • 130
  • 1
    In the article the Guid is hardcoded, you're creating a new one each time the app is started. Created a Guid and hard code it. – RobH May 21 '13 at 12:20
  • @RobH if so, I don't need a GUID, GUID is just for generating a unique at runtime, I use the string of my own and it is even more unique than the one generated by GUID. Thanks! – King King May 21 '13 at 12:22
  • The article may be right with your explanation but if so, simply it should talk about the name of Mutex differently. For example, you should prepare yourself a complicated and long string for Mutex name, that's enough to understand, and I will know how to get that string my self. – King King May 21 '13 at 12:24
  • @KingKing It doesn't need to be long and complicated just unique per application. The reason a GUID is used is to guarantee this uniqueness. – TheKingDave May 21 '13 at 12:29
  • In VS, use Tools + Create GUID. Copy it into your source code and make it a string literal. – Hans Passant May 21 '13 at 12:34
  • Maybe I don't understand well about GUID, please explain to me a little about it, as I understand once call to Guid.NewGuid(), we will have a unique string permanently, I mean, all the calls to Guid.NewGuid() after the time called it before should generate different values from the one I got. That looks impossible because the number of characters (in GUID string) is limited. I thought, Guid.NewGuid() will generate something unique at the time of the call, after that, it can be duplicated although the chance is very little. please see my next comment... – King King May 21 '13 at 12:46
  • I think a GUID is created and saved somewhere on my computer, right? That should be so, thanks! – King King May 21 '13 at 12:49
  • "Guid.NewGuid(), we will have a unique string permanently." No this is incorrect Guid.NewGuid() generates you a brand new GUID each time as the method name suggested. It is not saved automatically see http://msdn.microsoft.com/en-us/library/system.guid.newguid.aspx – TheKingDave May 21 '13 at 12:51
  • "That looks impossible because the number of characters (in GUID string) is limited". I think you should read up on what a GUID actually is and how it is generated. It is a 128-bit number that is normally show as a string. The number of possible UUID is therefore something like 2^128. Which is a very big number indeed. – TheKingDave May 21 '13 at 12:56
  • @TheKingDave thanks, some people (above) talked about hard coding the string (a GUID as mutex name), what do you think about this context: 1. at 2 pm, I got a new GUID: 123456789 (demonstrative purpose only) 2. I hard code it as my Mutex name 3. at 2 pm of a day of 2050, can some application running on my machine get the same GUID: 123456789 ? I think, it can happen but the chance it is very little. All my comments is for a thing that: GUID can make it unique, my own string also can do. – King King May 21 '13 at 13:00
  • @KingKing This is fine as well. Just as long as the name is unique. It makes no real difference. – TheKingDave May 21 '13 at 13:03

2 Answers2

0

Reading the article you sent you are not following it correctly:

"The name of the mutex should contain a GUID, which ensures that no other application uses the same name. If you don’t know how to create a GUID, click here."

Not a new GUID for each instance. Create a GUID once making the string unique.

You could use something like

static class Program
{
    static Mutex mutex;

    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        var guid = ((System.Runtime.InteropServices.GuidAttribute)(System.Reflection.Assembly.GetEntryAssembly().GetCustomAttributes(typeof(System.Runtime.InteropServices.GuidAttribute), false).Single())).Value;

        bool alreadyRun;
        mutex = new Mutex(false, "App_Name" + guid.ToString(), out alreadyRun);
        if (!alreadyRun) return;        
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());        }
}

Then if you want another version of your app to run at the same time just give it a new GUID. You can prefix Local\ as per the article if required.

Here is an imageenter image description here

TheKingDave
  • 926
  • 1
  • 8
  • 16
  • I'm sorry to say that GUID (in your code) is associated with GUID of Assembly type, and App_Name can be duplicated between different applications. That means, the whole name (passed in) can be duplicated. For example, my application has name "SingleInstance.exe", the Assembly GUID is "1234567890" and this is fixed for all applications on the same machine. The whole name is "SingleInstance.exe1234567890", so what if there is another application using the same name "SingleInstance.exe" and the GUID of course can't be different because it's just associated with Assembly type,not Assembly instance – King King May 21 '13 at 12:35
  • ...and the applications with duplicated Mutex names may be blocked from running. I tested it and it's no way. Thanks! – King King May 21 '13 at 12:37
  • Firstly "1234567890" is not a valid GUID. I tried inputting this into VS and I get a compile error. Your GUID is not 1234567890 ... It is highly unlikely that another application will have the same GUID as yours if you want to know the probability of this see here: http://en.wikipedia.org/wiki/UUID. The assembly type GUID is generated when you first create you program. The point of a mutex is that nothing of you TYPE runs at the same time. GUIDs generated within a assembly instance will always be different. – TheKingDave May 21 '13 at 12:49
  • Also the remember the reason that the Mutex name is to distinct is so as to not collides with someone else's application. They would need to "guess" your GUID which is as unlikely as the wikipedia entry show. – TheKingDave May 21 '13 at 12:52
  • I'm sorry about the GUID but it's just an example, you want I have to post an exact GUID with correct form???? And as I said, I tested it and it didn't work. The GUID in your code is the GUID for Assembly Type not Assembly instance. Even your code calls to GetExecutingAssembly() but it's even simpler by typeof(Assembly).GUID If you don't believe, you can test the call to typeof(Assembly).GUID in some different applications and see if they are different??? – King King May 21 '13 at 12:56
  • I tried everything I posted and it works correctly. What where you trying ? The whole point is that it is for the Assembly type NOT the instance. I already tried this in different applications and it works as I have said. I'm not sure what you are doing. typeof(Assembly) it just shorthand for what I wrote so I see no different. Do you want me to show screenshots ...? – TheKingDave May 21 '13 at 13:02
  • here is what I tried: Create 2 different applications. These both require to run with an instance at a time. I suppose the app names (as App_Name in your code) are the same (why? because that's possible, the possibility is even high enough and can't be inconsiderable). Now, for my first application, after running the instance 1, every try to run the instance 2 of it will fail, OK. But here is problem: EVERY try to run ANY instance of the second application will also fail. Please review it. – King King May 21 '13 at 13:10
  • I did just exactly as you said as it works (see my screenshot). If you debug your applications what do you get for "App_Name" + Assembly.GetExecutingAssembly().GetType().GUID.ToString(). IF you get the same Assembly.GetExecutingAssembly().GetType().GUID.ToString() then what is the GUID within you AssemblyInfo.cs I believe you have COPIED you application in which case you have NOT updated the GUID within AssemblyInfo.cs. As I said before it is highly unlikely than another developer on another machine has the same GUID as yourself. – TheKingDave May 21 '13 at 13:26
  • I didn't copy, I created new projects. The GUID I see on my form is different from the one in AssemblyInfo.cs I don't know why yours is so different. My applications show the same result for GUID associated with Assembly type and of course that why it's problematic as mentioned in my previous comment. – King King May 21 '13 at 13:30
  • The GUID I found in AssemblyInfo.cs files of my applications are different. Only the GUID returned by typeof(Assembly).GUID are same. – King King May 21 '13 at 13:33
  • Just checked use the code as I have in the above application and you can't use typeof(Assembly) use the code as I have in my answer. – TheKingDave May 21 '13 at 13:47
  • See this reason http://stackoverflow.com/questions/1528287/assembly-gettype-and-typeof-return-different-types why (the first answer). – TheKingDave May 21 '13 at 13:48
  • I've not used only typeof() but used also yours (to be sure, I always do exactly what other suggests first) – King King May 21 '13 at 13:55
  • On my version Assembly.GetExecutingAssembly().GetType().GUID.ToString() is different between the two applications it is picked up from AssemblyInfo.cs typeof(Assembly) is not. As I have said multiple times now this works on my P.C. if I could I would see you the executables / source so you can check but I don't know how I would send these to you. – TheKingDave May 21 '13 at 14:02
  • Are you sure all your applications use the same .NET framework version? – King King May 21 '13 at 14:04
  • All use the same frame and the code is identical on both. (Bar the GUID within AssemblyInfo.cs). If you debug your code what is Assembly.GetExecutingAssembly().GetType().GUID.ToString() returning? – TheKingDave May 21 '13 at 14:14
  • Debugging or simply showing that value somewhere (such as Form Text/Caption) gives the same result: 28e89a9f-e67d-3028-aa1b-e5ebcde6f3c8 The GUID in AssemblyInfo.cs is different. – King King May 21 '13 at 14:28
  • I tested it, the GUID is the same to the GUID found in AssemblyInfo.cs and these GUIDs are different between applications so it works. I also tried finding how to get the GUID in AssemblyInfo.cs but didn't find a way. Looks like that's pointed out by you. However I think it's much simpler to use a fixed GUID instead. The GUID extracted in Assembly in fact is fixed, once we create a new project the GUID is fixed and can be edited at design time. Thanks! – King King May 21 '13 at 15:07
0

You don't need a name to create a mutex, but you should have one if you intend to use it across process boundaries, e.g. to signal that an instance of the application is already running.

In your code, you're creating a different name each time the application starts. This name will not match the name of any other mutexes, so the code will pass on through.

Try setting the name to something distinct but definite.

The remarks on this MSDN page explain things well.

Chris Spicer
  • 2,144
  • 1
  • 13
  • 22
  • All your words seem to be known by myself, I also posted my solution at the end of my question. Thanks! – King King May 21 '13 at 12:31