I need to ensure only 1 instance of my C++ application is running.
Using the Win API how do I;
retrieve the information about my current application?
GetCurrentProcess()
will give me a HANDLE on my application, how do I retrieve information about it
retrieve a list of all running processes for the user?
EnumProcesses()
gives a list, but appears to require a pre-allocated buffer, so how do I find out how many processes are currently running?
I need to compare the exe name of my server to the running processes, and raise an error if I find more than one
Note: I cannot use any boost libraries, and I am not interested in using a mutex
, seen on similar posts.
You can use the CreateMutex
function to create a system-wide named mutex to denote whether your process is running. It will return ERROR_ALREADY_EXISTS
if the process is already running:
(void)::CreateMutex( NULL,
TRUE,
TEXT( "My_Special_Invokation_Test_Mutex" ) );
switch ( ::GetLastError() ) {
case ERROR_SUCCESS:
// Process was not running already
break;
case ERROR_ALREADY_EXISTS:
// Process is running already
break;
default:
// Error occured, not sure whether process is running already.
break;
}
Now, if you insist on not using a mutex, you can use the CreateFile
function instead. Make sure to pass zero for the dwShareMode
field to get exclusive access semantics, CREATE_NEW
for the dwCreationDisposition
field (so that you create the file only if it doesn't exist already) and FILE_FLAG_DELETE_ON_CLOSE
for the dwFlagsAndAttributes
argument so that the file gets deleted once your process is terminated. Something like this:
LPCTSTR lockFileName = ...;
(void)::CreateFile( lockFileName,
GENERIC_READ,
0,
NULL,
CREATE_NEW,
FILE_FLAG_DELETE_ON_CLOSE,
NULL );
switch ( ::GetLastError() ) {
case ERROR_SUCCESS:
// Process was not running already
break;
case ERROR_FILE_EXISTS:
// Process is running already
break;
default:
// Error occured, not sure whether process is running already.
break;
}
See this article about Temporary file generation and usage best practices about how to deal with temporary files safely.
To make a long story short, it's certainly possible to use lock files for your task, but I think it's harder to do it right.
Updated version of Nawaz's answer:-
Handle mutex = CreateMutex (0, 0, "SomeUniqueName");
switch (GetLastError ())
{
case ERROR_ALREADY_EXISTS:
// app already running
break;
case ERROR_SUCCESS:
// first instance
break;
default:
// who knows what happened!
break;
}
This does have a security issue, a malicious application could create a mutex called "SomeUniqueName" before your app starts, which would then prevent your app from being run. To counter this, you can name the mutex based on a hash of some constant system parameter (the MAC address for example). The MSDN documentation has this to say about single instance applications:
If you are using a named mutex to limit your application to a single instance, a malicious user can create this mutex before you do and prevent your application from starting. To prevent this situation, create a randomly named mutex and store the name so that it can only be obtained by an authorized user. Alternatively, you can use a file for this purpose. To limit your application to one instance per user, create a locked file in the user's profile directory.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With