In a Windows environment, I don't want two instances of my program running at the same time.
Related
Is using a Mutex to prevent multiple instances of the same program from running safe?
In a Windows environment, I don't want two instances of my program running at the same time.
Related
Is using a Mutex to prevent multiple instances of the same program from running safe?
You could check if window class is already registered. Take a look at this MSDN entry.
You could create a mutex when the first instance of your application starts. To prevent a second instance all you'd need to do is check if the mutex is being used.
Actually there was a question raised about using mutexes for this purpose here check out JaredPar's answer.
Note: You can use a local mutex if you want the "one instance" to apply only within a user's session (instead of for all users)
I think you need to consider your scenario a bit before going forward. There are many different interpretations of "running the same program" more than once. For instance do you
All of these have different, albeit similar, solutions.
The easiest one to describe is the per machine. In this case you want to create a named Mutex. One startup every program must obtain this mutex, if they are successful they run and hold onto the Mutex for the duration of the process lifetime. Otherwise some other program is running and they exit immediately.
Unforunately this approach also has its drawbacks. If I want to mess up your program, I can create a mutex with the same name. This will prevent your program from running any instance because they are unable to tell who holds the Mutex, just that something is holding the mutex.
Use a mutex, as others have suggested.
That CreateMutex() documentation from MS has a lot of useful information, and specifically addresses the case of using mutexes for preventing more than one instance of a program from running. In particular:
CreateMutex()
with bInitialOwner = FALSE
, then call a wait function (e.g. WaitForSingleObject()
) to ensure that just one instance acquires the mutex.At the startup of your program, you can enumerate the processes running on your machine
Then if you see that you're already running, quit
this is a class I scripted using boost.interrprocess, I use it to sync between the GUI and CLI versions.
You might find it useful:
#pragma once
#include <boost/interprocess/windows_shared_memory.hpp>
#include <boost/interprocess/mapped_region.hpp>
#ifndef max
#define max(a,b) (((a) > (b)) ? (a) : (b))
#endif
using boost::interprocess::windows_shared_memory;
using boost::interprocess::mapped_region;
using boost::interprocess::open_or_create;
using boost::interprocess::read_write;
using boost::interprocess::interprocess_exception;
class CProcessMutex
{
public:
CProcessMutex()
: m_region()
, m_status(false)
{
initSharedMemory();
Increment();
}
~CProcessMutex()
{
Decrease();
}
public:
int GetCount()
{
return m_status ? *(static_cast<unsigned char*>(m_region.get_address())) : 0;
}
private:
void initSharedMemory()
{
try
{
//Create a native windows shared memory object.
windows_shared_memory shm (open_or_create, "shared_memory", read_write, 1);
//Map the whole shared memory in this process
m_region.swap(mapped_region(shm, read_write));
m_status = true;
}
catch(interprocess_exception &ex)
{
ex.what();
m_status = false;
}
}
void Increment()
{
if(m_status) (*(static_cast<unsigned char*>(m_region.get_address())))++;
}
void Decrease()
{
if(m_status) (*(static_cast<unsigned char*>(m_region.get_address())))--;
}
private:
mapped_region m_region;
bool m_status;
};
the usage is simple:
CProcessMutex pm;
size_t current_process_count = pm.GetCount();
if(current_process_count > 1)
{
...
}
so you can easily limit how many processes in parallel.
An alternative simple solution is to create a suitably unique global named event (possibly a GUID string) then check for its existence on startup. If it exists then an instance of your app has already been started. If not, you've automatically created the event and can continue to run, e.g.:
// for brevity, a complete set of error handling has been omitted
m_hEvent = CreateEvent(NULL, TRUE, FALSE, szMyUniqueNamedEvent);
switch (GetLastError)
{
// app is already running
case ERROR_ALREADY_EXISTS:
{
CloseHandle(m_hEvent);
// now exit
break;
}
// this is the first instance of the app
case ERROR_SUCCESS:
{
// global event created and new instance of app is running,
// continue on, don't forget to clean up m_hEvent on exit
break;
}
}