What is the best way to prevent multiple instance?

G

Guest

Hello, friends,

In c#.net, what is the best way to prevent users from creating multiple
instances of an app? I found a few ways, but not sure which one is the best.

(I know in VB6, we do something like: If App.PrevInstance Then End)

Thanks.
 
P

Peter Duniho

In c#.net, what is the best way to prevent users from creating multiple
instances of an app? I found a few ways, but not sure which one is the
best.

Named mutex.
 
G

Guest

what about this one?

System.Threading.Mutex mut = new System.Threading.Mutex(false,
Application.ProductName);
bool running = !mut.WaitOne(0, false);
if (running)
{
Application.ExitThread();
return;
}
 
J

Jon Skeet [C# MVP]

Andrew said:
what about this one?

System.Threading.Mutex mut = new System.Threading.Mutex(false,
Application.ProductName);
bool running = !mut.WaitOne(0, false);
if (running)
{
Application.ExitThread();
return;
}

No, that won't do it. The point is to be the one to *create* the mutex,
which is nice and atomic. There's also the problem that with the above
code that the mutex can then be garbage collected before your
application terminates.
 
P

Peter Duniho

No, that won't do it. The point is to be the one to *create* the mutex,
which is nice and atomic. There's also the problem that with the above
code that the mutex can then be garbage collected before your
application terminates.

While I agree that given that creation of the mutex provides "first in
line" semantics and is perfectly sufficient, I'm curious as to why there's
a problem with using the acquisition of the mutux as the exclusiveness
test.

That is, assuming the problem with the possibility of the mutex being
garbage collected is addressed (fixed with a GC.KeepAlive(), no?).
Provided you ensure that the mutex really does maintain its lifetime
during execution of the code it's meant to protect, I would think that
failing to acquire the mutux would be equally sufficient, at least with
respect to ensuring a single running instance.

I'm not trying to argue that one *should* do it that way. After all, why
bother to do the second test, when the mere act of creating the mutex
gives you all the information you need. I'm just curious as to why "that
won't do it" (the idea, not the specific code posted, since it does have a
bug :) ).

Pete
 
J

Jon Skeet [C# MVP]

Peter Duniho said:
While I agree that given that creation of the mutex provides "first in
line" semantics and is perfectly sufficient, I'm curious as to why there's
a problem with using the acquisition of the mutux as the exclusiveness
test.

<snip>

You're right - I think I looked too quickly. It probably would be okay.
I was overly suspicious of a variation of the "normal" mechanism.

That's the trouble with posting in a hurry :(
 
G

Guest

Thanks, guys, then, what about this one?

Process current = Process.GetCurrentProcess();
Process[] processes =
Process.GetProcessesByName(current.ProcessName);

foreach (Process process in processes)
{
if (process.Id != current.Id)
{
if
(Assembly.GetExecutingAssembly().Location.Replace("/", "\\") ==
current.MainModule.FileName)
{
this.Close();
Application.Exit();
}
}
}
 
P

Peter Duniho

Thanks, guys, then, what about this one?

What about it? Seems like the general idea would work, but why go to all
that trouble?

Though, as long as you're asking...

Why are you comparing the results from "GetExecutingAssembly()" with the
"current" process? Shouldn't that be the "process" process? And why use
GetExecutingAssembly() at all? Why not just compare the
"MainModule.FileName" properties for both processes (assuming you care
about that...if you really don't want two instances running, I'd suggest
you probably don't). And if you must use GetExecutingAssembly(), why do
the string replace in each loop iteration, rather than doing it once and
saving the result to use within the loop?

I suppose if there are good answers to the above questions, and you really
prefer to use that method rather than a named mutex, that's fine. But I
honestly don't see any advantage in the code you posted over the named
mutex, and in fact feel that the named mutex method is simpler, easier,
and just as reliable (and if you really only want to exclude multiple
instances executing from the same exact file location, you can use the
file location in the name of the mutex).

Pete
 
J

Jon Skeet [C# MVP]

Andrew said:
Thanks, guys, then, what about this one?

Process current = Process.GetCurrentProcess();
Process[] processes =
Process.GetProcessesByName(current.ProcessName);

That's much slower than using a mutex - it can take quite a long time
to get the list of current processes.
 
G

Guest

Thanks again, but just wonder why MS didn't keep App.PreInstance in .net....

Jon Skeet said:
Andrew said:
Thanks, guys, then, what about this one?

Process current = Process.GetCurrentProcess();
Process[] processes =
Process.GetProcessesByName(current.ProcessName);

That's much slower than using a mutex - it can take quite a long time
to get the list of current processes.
 
M

Michael D. Ober

In VB 2005 winforms applications, you can configure an event to fire if you
start a second instance of a process. In general, however, the global,
named mutex is the best solution as it is quick and will work across
multiple development environments, as long as they can get to the Win32 API.

Mike.

Andrew said:
Thanks again, but just wonder why MS didn't keep App.PreInstance in
.net....

Jon Skeet said:
Andrew said:
Thanks, guys, then, what about this one?

Process current = Process.GetCurrentProcess();
Process[] processes =
Process.GetProcessesByName(current.ProcessName);

That's much slower than using a mutex - it can take quite a long time
to get the list of current processes.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top