在Windows环境中,我不想同时运行两个程序实例。
有关
使用互斥锁来防止同一程序的多个实例运行安全吗?
我认为在未来之前,你需要考虑一下你的情况。 对于“运行同一个程序”有不止一次的解释。 比如你
所有这些都有不同的,尽管类似的解决方案。
最容易描述的是每台机器。 在这种情况下,你想创建一个名为Mutex。 一个启动每个程序必须获得这个互斥,如果他们成功,他们运行并在整个过程中保持互斥。 否则,其他程序正在运行,并立即退出。
不幸的是,这种方法也有其缺点。 如果我想搞乱你的程序,我可以创建一个同名的互斥体。 这将阻止你的程序运行任何实例,因为他们无法分辨谁持有互斥体,只是某些东西持有互斥体。
当您的应用程序的第一个实例启动时,您可以创建一个互斥锁。 为了防止第二个实例所有你需要做的是检查是否正在使用互斥。
其实有一个关于使用互斥体为此目的提出的问题在这里检查JaredPar的答案。
注意:如果您希望“one instance”仅适用于用户的会话(而不是所有用户),则可以使用本地互斥锁
如果是你的程序,那么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 ... }
如果你需要的只是一个简单的检查,不需要变得复杂
最好的方法是使用互斥锁。 请参阅使用互斥对象 。
另一个简单的解决方案是创建一个适当唯一的全局命名事件(可能是一个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()文档有很多有用的信息,特别是解决使用互斥体防止运行一个程序的多个实例的情况。 尤其是:
bInitialOwner = FALSE
调用CreateMutex()
,然后调用一个等待函数(例如WaitForSingleObject()
)来确保只有一个实例获得互斥体。 在程序启动时,可以枚举机器上运行的进程
那么如果你看到你已经在跑步,退出
你可以检查窗口类是否已经注册。 看看这个 MSDN条目。