问题
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?
回答1:
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
- Once per machine
- Once per logon session
- Once per user
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.
回答2:
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)
回答3:
If it's your program, then the shortest possible version under windows:
int main(int argc, char** argv)
{
CreateMutexA(0, FALSE, "Local\\$myprogram$"); // try to create a named mutex
if(GetLastError() == ERROR_ALREADY_EXISTS) // did the mutex already exist?
return -1; // quit; mutex is released automatically
// ... program code ...
}
No need to get crazy complex, if all you needed was a simple check...
回答4:
The best way is to use a mutex. See Using Mutex Objects.
回答5:
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;
}
}
回答6:
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.
回答7:
When you use Qt you can download the QtSingleApplication component.
回答8:
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:
- Call
CreateMutex()
withbInitialOwner = FALSE
, then call a wait function (e.g.WaitForSingleObject()
) to ensure that just one instance acquires the mutex. - Consider using a locked file instead if you're worried about denial of service attacks.
回答9:
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
回答10:
You could check if window class is already registered. Take a look at this MSDN entry.
来源:https://stackoverflow.com/questions/800730/c-c-how-to-tell-if-a-program-is-already-running