17

I have seen at least three distinct methods on StackOverflow for achieving this.

  1. Using a MUTEX: Accepted answer to this SO question

  2. Using the Microsoft.VisualBasic library's WindowsFormsApplicationBase: Second highest voted answer to this SO question

  3. Using Process.GetProcessNames to check if your application is running: Method here was posted as an answer to this SO question

I'm sure there are more ways to do this as well.

I'm simply wondering if one of these is preferred and what the consequences might be if I pick the "wrong" one.

Andrew Morton
  • 24,203
  • 9
  • 60
  • 84
Michael Mankus
  • 4,628
  • 9
  • 37
  • 63
  • 1
    Such subjective or opinion-based questions aren't appropriate for SO. – Servy Dec 31 '12 at 18:34
  • 1
    The correct one is the one that works for your specific circumstances. – Oded Dec 31 '12 at 18:35
  • 5
    @Servy - But is it opinion based? The OP is asking if there's a method that's favored by Microsoft. That's pretty specific. – System Down Dec 31 '12 at 18:35
  • Is there a better StackExchange site for this? Which would you suggest? – Michael Mankus Dec 31 '12 at 18:35
  • 6
    `Process.GetProcessNames` is not a good choice, as a renamed `.exe` will get the new name in the process list. – Oded Dec 31 '12 at 18:35
  • 3
    @SystemDown - Then MS should answer it, on the MS forums. – Oded Dec 31 '12 at 18:36
  • 1
    @SystemDown Since this isn't Microsoft, you'd need to ask them what they prefer. Asking here is essentially asking what they prefer, which is subjective. – Servy Dec 31 '12 at 18:36
  • @michael.mankus There is no SE site for which this question is appropriate. – Servy Dec 31 '12 at 18:36
  • I'd rethink the problem. Do you really need single instance? What if the process is borked and not responding? Another instance will never fire up. – Michael Todd Dec 31 '12 at 18:38
  • @MichaelTodd The user can always kill a process. Sometimes you just can't have multiple instances of certain processes running. – Michael Mankus Dec 31 '12 at 18:41
  • @Oded Thank you for the tip about `Process.GetProcessNames`. Won't be using that. – Michael Mankus Dec 31 '12 at 18:42
  • There are multiple good ways to do this. I'd recommend picking one, test it to make sure it works, and move on. – Erik Philips Dec 31 '12 at 18:46
  • 1
    I would just go with @jonskeet - http://csharpindepth.com/Articles/General/Singleton.aspx – Hogan Dec 31 '12 at 19:10
  • 3
    @Hogan That is something very different entirely. Jon is talking about a Singleton (which allows just one instance of a class), but I'm asking about a single instance of an entire application. – Michael Mankus Dec 31 '12 at 19:14
  • What does it mean for an application to be single instance? If multiple users have logged on on the same server, can only one user start the application? If so, if a load balancer is used to split the sessions to two different servers, the situation becomes pretty much undetectable. If not, at least some of the suggested answers are just plain wrong. –  Dec 31 '12 at 19:31
  • The user could also not understand _why_ they would have to kill an instance (or even how to do so); all they see is that the app isn't starting. It's happened numerous times with in-house apps where I used a mutex to prevent multiple instances. – Michael Todd Dec 31 '12 at 19:38

3 Answers3

17

When in doubt, always prefer an implementation that's included in the .NET framework. You can have high expectations that such an implementation is tested by hundreds of thousands of programmers, has been carefully reviewed for security and usability and will be maintained for years to come.

The mutex approach is an easy one to get going. It however suffers from a pretty severe security problem. A denial of service attack is very simple to get going, you cannot keep the name of your mutex a secret and anybody can trivially create a mutex with the same name and prevent your program from ever starting up.

The process name approach is deeply flawed for the same reason. There is no guarantee that a process name is unique. Not just easy to exploit but easily triggered by accident.

WindowsFormsApplicationBase has an image problem in the eyes of C# programmers. They choke at the namespace name and assume that their program will somehow be infected with vb-isms. That's nonsense, it is just a plain .NET class that's useable in any language.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • Good point about the well-known named mutex... (grr hit save too soon) - I wonder if there's a way one could effectively prevent such a mutex-based DoS attack? – JerKimball Dec 31 '12 at 19:18
  • 1
    Forgive my ignorance, but how would someone figure out my Mutex name? – Michael Mankus Dec 31 '12 at 19:22
  • 2
    Simple to do with SysInternals' WinObj utility for example. – Hans Passant Dec 31 '12 at 19:24
  • 2
    The more important question is why would anyone attack your application? If anything they would want to start more than one instance, not prevent it from starting at all. – LeffeBrune Dec 31 '12 at 19:24
  • @HansPassant Does the WindowsFormsApplicationBase suffer from the same vulnerablity? I'm not uncomfortable using it at all. And I don't like the idea of someone spoofing my Mutex name. – Michael Mankus Dec 31 '12 at 19:26
  • @LeffeBrune - It's a very slim possibility somebody would ever do something like this, granted, but let's invent a scenario: say I've got some bizarre licensing scheme where it depends on a singleton credentials server running alongside my app. If that server fails to boot, tho, I use some other mechanism that is easier to circumvent. Preventing that server from ever launching by binding up the Mutex would cause a security hole. A contrived example, to be sure, but definitely a problem. – JerKimball Dec 31 '12 at 19:29
  • @michael.mankus - What would be the worst-case scenario if somebody *did* start two instances of this application? – JerKimball Dec 31 '12 at 19:34
  • @LeffeBrune - your competitor will find a good use for a DoS attack. They'll get away with it too, claiming the name collision was accidental or that they tried to solve a known compatibility problem. – Hans Passant Dec 31 '12 at 19:41
  • 1
    Your competitor can kill your app as soon as it starts just as easy, or maybe even delete it, or prevent your from installing it. I think you really should not waste your time and effort trying to defend against hypothetical scenarios. – LeffeBrune Dec 31 '12 at 19:45
  • @JerKimball I'm doing client/node communications over a network. And I'm hard coding the ports I want to use for the various network streams. Say a user on the node side opens two instances. The second instance does not grab hold of the ports because the first is already listening on them. Now the user intends to connect to the second instance but can't. I'd rather keep things simple for the user and just prevent two instances. So if an instance is already running, I set `TopMost = true;` so that it becomes visible (in case it's minimized or covered). – Michael Mankus Dec 31 '12 at 19:46
  • @JerKimball Not to mention the fact that I'm using the GreatMaps library (GMap.NET) for mapping and it doesn't favor being run by two seperate instances. – Michael Mankus Dec 31 '12 at 19:48
  • Better solution is to use Windows Events for this purpose: http://stackoverflow.com/a/646500/296924 – Thracx Feb 03 '15 at 20:16
  • It of course has the exact same problem as Mutex. – Hans Passant Feb 03 '15 at 23:07
5

Why nobody mentioned ticking this checkbox?

enter image description here

Community
  • 1
  • 1
Victor Zakharov
  • 25,801
  • 18
  • 85
  • 151
  • 4
    Cuz that only exists for VB apps - under the hood it's relying on the aforementioned VisualBasic forms apps dll. – JerKimball Dec 31 '12 at 20:09
  • 2
    @JerKimball: Interesting... `WindowsFormsApplicationBase` you mean? Looks like C# is flawed in ease-of-use aspect. Would be interesting to know why Microsoft would keep it complicated, if it's really that simple. And not only in this function. But thanks for the heads up! – Victor Zakharov Dec 31 '12 at 20:15
  • That's the one (can never recall the name on demand) - as for why it only exists in the VB space, I have no insight; would have to ask somebody on the VS team for that one. All told, there's a lot of "neat" stuff in that namespace, but being all internally implemented, doesn't leave for any customization. – JerKimball Dec 31 '12 at 20:27
  • Yes, I also noticed this issue. The checkbox of *Make single instance application* only available for vb WinForm project but not available for C# WinForm project. – sky91 Jul 05 '17 at 04:19
0

It's really a matter of taste, but I favor the Mutex approach, simply due to it not requiring a dependency on the VisualBasic libaries, and using Process.GetProcessNames is a non-ideal solution (as mentioned, process names aren't always going to map to what you think they might)

JerKimball
  • 16,584
  • 3
  • 43
  • 55