在 Windows 环境中,我不希望我的程序的两个实例同时运行。
有关的
如果是你的程序,那么在 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 ...
}
无需变得疯狂复杂,如果您只需要一个简单的检查...
我认为您需要在继续之前考虑一下您的情况。不止一次“运行同一个程序”有很多不同的解释。比如你
所有这些都有不同但相似的解决方案。
最容易描述的是每台机器。在这种情况下,您要创建一个命名的 Mutex。每次启动时,每个程序都必须获得此互斥锁,如果它们成功,它们会在进程生命周期内运行并持有互斥锁。否则,其他一些程序正在运行,它们会立即退出。
不幸的是,这种方法也有其缺点。如果我想弄乱你的程序,我可以创建一个同名的互斥锁。这将阻止您的程序运行任何实例,因为它们无法分辨谁持有互斥锁,只是有东西持有互斥锁。
您可以在应用程序的第一个实例启动时创建互斥锁。为了防止第二个实例,您需要做的就是检查是否正在使用互斥锁。
实际上,这里有一个关于为此目的使用互斥锁的问题,请查看 JaredPar 的答案。
注意:如果您希望“一个实例”仅应用于用户会话(而不是所有用户),则可以使用本地互斥锁
最好的方法是使用互斥锁。请参阅使用互斥对象。
另一种简单的解决方案是创建一个适当唯一的全局命名事件(可能是 GUID 字符串),然后在启动时检查它是否存在。如果它存在,那么您的应用程序的一个实例已经启动。如果没有,您已经自动创建了事件并可以继续运行,例如:
// 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;
}
}
这是我使用boost.interrprocess编写的一个类,我用它在 GUI 和 CLI 版本之间同步。
您可能会发现它很有用:
#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;
};
用法很简单:
CProcessMutex pm;
size_t current_process_count = pm.GetCount();
if(current_process_count > 1)
{
...
}
因此您可以轻松限制并行进程的数量。
当您使用 Qt 时,您可以下载QtSingleApplication组件。
正如其他人所建议的那样,使用互斥锁。
MS 的CreateMutex () 文档有很多有用的信息,并专门解决了使用互斥锁来防止多个程序实例运行的情况。尤其是:
CreateMutex()
,bInitialOwner = FALSE
然后调用等待函数(例如WaitForSingleObject()
)以确保只有一个实例获取互斥锁。在你的程序启动时,你可以枚举你机器上运行的进程
然后如果你看到你已经在运行,退出
您可以检查窗口类是否已注册。看看这个MSDN 条目。