Board index » cppbuilder » Prevent Multiple Instance

Prevent Multiple Instance


2006-08-30 04:44:53 PM
cppbuilder82
I only want one instance of my application to run and have tried using
CreateMutex
but it doesn't appear to return NULL when one already exists, e.g.
hMutex = ::CreateMutex(NULL, NULL, "TestMutex");
hMutex = ::CreateMutex(NULL, NULL, "TestMutex"); // This should return
NULL but instead returns a new handle
How do I make this work? Or, what is a better way to prevent multiple
instances of my application?
Thanks,
Roger
 
 

Re:Prevent Multiple Instance

I found that
if (GetLastError() == ERROR_ALREADY_EXISTS)
works.
"Roger" < XXXX@XXXXX.COM >wrote in message
Quote
I only want one instance of my application to run and have tried using
CreateMutex
but it doesn't appear to return NULL when one already exists, e.g.

hMutex = ::CreateMutex(NULL, NULL, "TestMutex");

hMutex = ::CreateMutex(NULL, NULL, "TestMutex"); // This should return
NULL but instead returns a new handle

How do I make this work? Or, what is a better way to prevent multiple
instances of my application?

Thanks,
Roger


 

Re:Prevent Multiple Instance

"Roger" < XXXX@XXXXX.COM >wrote in message
Quote
I found that

if (GetLastError() == ERROR_ALREADY_EXISTS)

works.
I also use this method in my Projects since a few weeks;
WinMain(){
{
try
{
// Create the Mutex with the GUID...
HANDLE hMutex = CreateMutex(NULL, FALSE, "{PUTGUIDHERE}");
if (GetLastError() == ERROR_ALREADY_EXISTS)
{
ShowMessage("Program is already running.");
return 0;
}
// Start the program normally...
Application->Initialize();
Quote
Or, what is a better way to prevent multiple instances of my application?
Interesting material on this subject to read:
www.codeproject.com/cpp/limitnumins.asp
JasperP
 

{smallsort}

Re:Prevent Multiple Instance

"JasperP" < XXXX@XXXXX.COM >writes:
Quote
I also use this method in my Projects since a few weeks;

WinMain(){
{
try
{
// Create the Mutex with the GUID...
HANDLE hMutex = CreateMutex(NULL, FALSE, "{PUTGUIDHERE}");
if (GetLastError() == ERROR_ALREADY_EXISTS)
Hmm. I don't say that this doesn't work, but it doesn't exactly
correspond to the docs (shrunklink.com/?iyb , aka
msdn.microsoft.com/library/default.asp
, which might wrap), and it certainly doesn't correspond at all to the
idiom of first checking the return value, and only retrieving more
information about the possible error once we know that there is an
error. E.g.:
if (HANDLE mutex = CreateMutex(NULL,FALSE,"{PUTGUIDHERE}"))
{
// continue with application
CloseHandle(mutex);
}
else
{
// investigate problem, e.g. using GetLastError(),
// and act according to the problem
}
If there is a possibility that the code replacing the first comment
throws (and probably otherwise as well), a RAII object will lead to
simpler and more reliable code.
 

Re:Prevent Multiple Instance

"Roger" < XXXX@XXXXX.COM >wrote in message
Quote
I only want one instance of my application to run and have
tried using CreateMutex but it doesn't appear to return NULL
when one already exists
It is not supposed to. It is supposed to return a non-NULL handle. That is
the whole point of allowing multiple processes to share a named mutex with
each other. You have to use GetLastError() to find out whether the mutex
already existed or not.
Quote
hMutex = ::CreateMutex(NULL, NULL, "TestMutex"); // This should return
NULL but instead returns a new handle
No, it should not return NULL.
Gambit
 

Re:Prevent Multiple Instance

"JasperP" < XXXX@XXXXX.COM >wrote in message
Quote
HANDLE hMutex = CreateMutex(NULL, FALSE, "{PUTGUIDHERE}");
if (GetLastError() == ERROR_ALREADY_EXISTS)
{
ShowMessage("Program is already running.");
return 0;
}
You need to close the handle:
HANDLE hMutex = CreateMutex(NULL, FALSE, "{PUTGUIDHERE}");
if (!hMutex)
{
ShowMessage("Error detecting if the Program is already running.");
return 0;
}
if (GetLastError() == ERROR_ALREADY_EXISTS)
{
CloseHandle(hMutex); // <-- here
ShowMessage("Program is already running.");
return 0;
}
// run application normally ...
CloseHandle(hMutex); // <-- here
return 0;
Gambit
 

Re:Prevent Multiple Instance

"Thomas Maeder [TeamB]" < XXXX@XXXXX.COM >wrote in message
Well, I guess that should be the case, but it was in an error-catching-env
already.
Either way you do not want the program to start if it throws an error/can
not create the Mutex, but your code is more 'clean programming'.
try
{
...
}
catch (Exception &exception)
{
Application->ShowException(&exception);
}
catch (...)
{
try
{
throw Exception("");
}
catch (Exception &exception)
{
Application->ShowException(&exception);
}
 

Re:Prevent Multiple Instance

True..
But looking at Thomas Maeder his code, I realized that there is another
problem with my code and also the example you used.
if 'GetLastError() == ERROR_ALREADY_EXISTS' is caused by another
program/process (eg. the CreateFile API), then you also have a problem.
Jasper
 

Re:Prevent Multiple Instance

"JasperP" < XXXX@XXXXX.COM >wrote in message
Quote
if 'GetLastError() == ERROR_ALREADY_EXISTS' is caused by
another program/process (eg. the CreateFile API), then you also have
a problem.
Why would that be a problem? CreateFile() cannot cause CreateMutex() to
return ERROR_ALREADY_EXISTS. Only CreateMutex() can do that. On the other
hand, if you meant CreateProcess() instead, then the code is doing exactly
what you are asking for - detecting a previous instance of itself. If
another application starts a new process that creates the mutex first, then
the current process would detect it and close itself. Where is the problem?
Gambit
 

Re:Prevent Multiple Instance

I guess I misunderstood this:
Return Values
If the function succeeds, the return value is a handle to the mutex object.
If the named mutex object existed before the function call, the GetLastError
function returns ERROR_ALREADY_EXISTS. Otherwise, GetLastError returns zero.
If the function fails, the return value is NULL. To get extended error
information, call GetLastError.
I, incorrectly, assumed that the function would fail if it tried to create a
mutex when one already existed. I also, incorrectly assumed that if
an error is generated the function failed.
"Remy Lebeau (TeamB)" < XXXX@XXXXX.COM >wrote in message
Quote

"Roger" < XXXX@XXXXX.COM >wrote in message
news:44f54fff$ XXXX@XXXXX.COM ...

>I only want one instance of my application to run and have
>tried using CreateMutex but it doesn't appear to return NULL
>when one already exists

It is not supposed to. It is supposed to return a non-NULL handle. That
is
the whole point of allowing multiple processes to share a named mutex with
each other. You have to use GetLastError() to find out whether the mutex
already existed or not.

>hMutex = ::CreateMutex(NULL, NULL, "TestMutex"); // This should return
>NULL but instead returns a new handle

No, it should not return NULL.


Gambit


 

Re:Prevent Multiple Instance

"Roger" < XXXX@XXXXX.COM >writes:
Quote
If the function succeeds, the return value is a handle to the mutex
object. If the named mutex object existed before the function call,
the GetLastError function returns ERROR_ALREADY_EXISTS. Otherwise,
GetLastError returns zero. If the function fails, the return value
is NULL. To get extended error information, call GetLastError.
Correct. And admittedly easy to misunderstand at first, because many
functions set an error only if they return NULL.
 

Re:Prevent Multiple Instance

"Remy Lebeau \(TeamB\)" < XXXX@XXXXX.COM >wrote:
Quote

[...] You need to close the handle:
Actually, he does not because the system closes the handle
automatically when the process terminates and the mutex object
is destroyed when its last handle has been closed.
~ JD
 

Re:Prevent Multiple Instance

Quote
Correct. And admittedly easy to misunderstand at first,
because many functions set an error only if they return NULL.
Well, if all else fails he might try some rare and {*word*118} things such as
reading the documentation. :-)
. Ed
Quote
Thomas Maeder wrote in message
news: XXXX@XXXXX.COM ...
 

Re:Prevent Multiple Instance

Hmmm,
This is an extract from the documentation, that I read several times:
"Return Values
If the function succeeds, the return value is a handle to the mutex object.
If the named mutex object existed before the function call, the GetLastError
function returns ERROR_ALREADY_EXISTS. Otherwise, GetLastError returns zero.
If the function fails, the return value is NULL. To get extended error
information, call GetLastError."
Maybe you could be so kind as to explain to me exactly what it means?
Because I still think it
is either wrong or at the very least confusing.
Note, my interpretation:
GetLastError associated with CreateMutex returns either ERROR_ALREADY_EXISTS
OR ZERO.
If CreateMutex fails the return value is NULL.
To me that says, CreateMutex ONLY FAILS if the named mutex objected existed
before the function call when it should
return NULL and have GetLastError return ERROR_ALREADY_EXISTS.
Admittedly I am a novice at programming but I typically don't check
GetLastError unless a function has failed.
So, when CreateMutex discovers the named mutex already exists does it fail
or not?
"Ed Mulroy" < XXXX@XXXXX.COM >wrote in message
Quote
>Correct. And admittedly easy to misunderstand at first,
>because many functions set an error only if they return NULL.

Well, if all else fails he might try some rare and {*word*118} things such as
reading the documentation. :-)

. Ed

>Thomas Maeder wrote in message
>news: XXXX@XXXXX.COM ...


 

Re:Prevent Multiple Instance

"Roger" < XXXX@XXXXX.COM >wrote in message
Quote
Maybe you could be so kind as to explain to me exactly what it means?
Look at it this way instead:
Return Values
If the function succeeds:
- the return value is a handle to the mutex object.
- If the named mutex object existed before the function call, the
GetLastError function returns ERROR_ALREADY_EXISTS. Otherwise, GetLastError
returns zero.
If the function fails:
- the return value is NULL. To get extended error information, call
GetLastError.
Quote
Because I still think it is either wrong
It is not. What it says is accurate.
Quote
or at the very least confusing.
There is nothing confusing about it. It says exactly what it actually does.
You are just not reading it correctly
Quote
Note, my interpretation:

GetLastError associated with CreateMutex returns either
ERROR_ALREADY_EXISTS
OR ZERO.
If the function succeeds, yes.
Quote
If CreateMutex fails the return value is NULL.
The return value of CreateMutex(), if it fails, yes. In that case,
GetLastError() returns the actual error code.
Quote
To me that says, CreateMutex ONLY FAILS if the named
mutex objected existed before the function call when it should
return NULL and have GetLastError return
ERROR_ALREADY_EXISTS.
That is not what it says, and that is not the correct interpretation of what
it says. If the mutex already exists, then CreateMutex() WILL NOT fail. It
will return a non-NULL handle to the existing mutex, so that the application
can access it (otherwise, what is the point of naming a shared mutex in the
first place?). CreateMutex() will fail only if the creation of a fresh new
mutex object fails (out of memory, incorrect security permissions, etc).
The existence of a named mutex is not a failure, it is a success. That is
how named kernel objects work.
Quote
Admittedly I am a novice at programming but I typically don't
check GetLastError unless a function has failed.
Most of the time, that is the correct thing to do. Most API functions do
not reset the calling thread's last error code unless a real error actually
occurs. There are a few exceptions to that rule, though, and CreateMutex()
is one of them. However, there is no requirement that you have to check
GetLastError() when CreateMutex() succeeds. If you don't care whether or
not the mutex previously existed, then just ignore GetLastError() when
CreateMutex() succeeds. Some functions (such as CreateMutex()) do use
GetLastError() to provide additional details about a successful operation,
however. Such information is useful, such as in this situation where you do
care whether the mutex previously existed or not (such as when implementing
a singleton application, which is the original purpose of this discussion).
Quote
So, when CreateMutex discovers the named mutex already exists
does it fail or not?
No, it does not fail. It returns a non-NULL handle to the existing mutex,
rather than returning a non-NULL handle to a newly created mutex. The
documentation says as much.
Gabit