Discussion:
Forcing Single Instance Of Application
(too old to reply)
none
2012-06-22 09:09:53 UTC
Permalink
I have an MFC application that accepts command-line parameters when
launched. The parameter is just a filename, which allows me to associate a
file type in Windows and then just double-clicking a file will launch my
application.

But, I really need to make sure that there is always only one instance of
the application running. So, if the user double-clicks an associated file
and the app is already running, I need to detect that and somehow tell the
running application to load the file.

I remember, way back in the day, that WinAmp used to do this (I guess it
still does). It used something called "DDE". I looked over the MSDN
documentation on DDE and it looks horribly overcomplicated for something
this simple. Is there an easier way?
David Lowndes
2012-06-22 11:23:13 UTC
Permalink
Post by none
But, I really need to make sure that there is always only one instance of
the application running. So, if the user double-clicks an associated file
and the app is already running, I need to detect that and somehow tell the
running application to load the file.
If you want to limit your application to a single instance, probably
the simplest method is to use CreateMutex like this:

bool bFound = false;

hMutexOneInstance = CreateMutex( NULL, TRUE,
_T("MyUniqueGuidHere") );
if(GetLastError() == ERROR_ALREADY_EXISTS)
bFound = true;
if(hMutexOneInstance)
ReleaseMutex(hMutexOneInstance);

Dave
ScottMcP [MVP]
2012-06-22 13:26:57 UTC
Permalink
Post by none
I looked over the MSDN
documentation on DDE and it looks horribly overcomplicated for something
this simple. Is there an easier way?
To send the file name to the original instance of your app an easier way is to use the WM_COPYDATA message. The FindWindow API will get the HWND of the app's main window. Then use ::SendMessage(hwnd, WM_COPYDATA, ...). The app can receive the message by putting ON_MESSAGE into the main window's message map.
none
2012-06-22 22:29:35 UTC
Permalink
Post by ScottMcP [MVP]
To send the file name to the original instance of your app an easier
way is to use the WM_COPYDATA message. The FindWindow API will get the
HWND of the app's main window. Then use ::SendMessage(hwnd,
WM_COPYDATA, ...). The app can receive the message by putting
ON_MESSAGE into the main window's message map.
This works perfectly. Thanks, because I was headed down the road of
creating a named pipe or something else overly complicated.

I use EnumWindow() to find the other window. If not found, process the
command line normally and start the app. If found, send WM_COPYDATA to the
other app with the command line.
ScottMcP [MVP]
2012-06-23 00:53:39 UTC
Permalink
Post by none
This works perfectly.
It doesn't, really. The mutex approach suggested by David is a better way to detect another instance, then WM_COPYDATA is great for sending the parameter.

But a mad mouse clicker can possibly launch several instances of your app before the first windows are displayed, so using EnumWindow is not the best way to detect another instance. Using CreateMutex right at the beginning of execution largely eliminates this vulnerable time interval.
none
2012-06-24 18:54:24 UTC
Permalink
Post by ScottMcP [MVP]
Post by none
This works perfectly.
It doesn't, really. The mutex approach suggested by David is a better
way to detect another instance, then WM_COPYDATA is great for sending
the parameter.
But a mad mouse clicker can possibly launch several instances of your
app before the first windows are displayed, so using EnumWindow is not
the best way to detect another instance. Using CreateMutex right at
the beginning of execution largely eliminates this vulnerable time
interval.
You're right, but getting a little philosophical for an MFC thread, I
usually lean toward the notion of "You get what you deserve" in situations
like that. I used to be completely OCD about my code and try to idiot-
proof everything to death. As we all know here, nature will always build a
better idiot.

Someone could write a script to launch multiple instances before your mutex
code is reached, right? :)
ScottMcP [MVP]
2012-06-24 22:09:35 UTC
Permalink
Post by none
Post by ScottMcP [MVP]
Post by none
This works perfectly.
It doesn't, really. The mutex approach suggested by David is a better
way to detect another instance, then WM_COPYDATA is great for sending
the parameter.
But a mad mouse clicker can possibly launch several instances of your
app before the first windows are displayed, so using EnumWindow is not
the best way to detect another instance. Using CreateMutex right at
the beginning of execution largely eliminates this vulnerable time
interval.
You're right, but getting a little philosophical for an MFC thread, I
usually lean toward the notion of "You get what you deserve" in situations
like that. I used to be completely OCD about my code and try to idiot-
proof everything to death. As we all know here, nature will always build a
better idiot.
Someone could write a script to launch multiple instances before your mutex
code is reached, right? :)
I've had customers who felt that giving a program the "mad mouse clicker" test was legitimate to test robustness.

Even in the case of a devious script I am confident that one, and only one, instance will get the mutex ownership, and thus become the one and only instance that is allowed to proceed.
David Lowndes
2012-06-24 23:30:13 UTC
Permalink
Post by ScottMcP [MVP]
I've had customers who felt that giving a program the "mad mouse clicker" test was legitimate to test robustness.
One of my first experiences of a customer acceptance test was of the
user who lays down on the keyboard. Mad random typing, holding any and
as many keys down as possible with hands and arms. It was a bit of a
shock when I encountered it but thankfully what I was working on
passed.
Post by ScottMcP [MVP]
Even in the case of a devious script I am confident that one, and only one, instance will get the mutex ownership, and thus become the one and only instance that is allowed to proceed.
Implemented correctly, the mutex solution should be solid.

Dave
none
2012-06-25 19:18:30 UTC
Permalink
Post by David Lowndes
Post by ScottMcP [MVP]
I've had customers who felt that giving a program the "mad mouse
clicker" test was legitimate to test robustness.
...
Post by David Lowndes
Implemented correctly, the mutex solution should be solid.
Ok, I'm sold on the mutex idea. One question, though:

if(hMutexOneInstance)
ReleaseMutex(hMutexOneInstance);

Why does the first instance of the application release the mutex after
creating it?
David Lowndes
2012-06-25 22:05:24 UTC
Permalink
Post by none
Why does the first instance of the application release the mutex after
creating it?
ReleaseMutex is not the equivalent of CloseHandle, if that's what
you're thinking.

In this usage (single instance detection), the process closure will
close the mutex handle.

Dave

Continue reading on narkive:
Loading...