C / C ++如何判断一个程序是否已经在运行?

Windows环境中,我不想同时运行两个程序实例。

有关

使用互斥锁来防止同一程序的多个实例运行安全吗?

我认为在未来之前,你需要考虑一下你的情况。 对于“运行同一个程序”有不止一次的解释。 比如你

  1. 每台机器一次
  2. 每次登录会话一次
  3. 每个用户一次

所有这些都有不同的,尽管类似的解决方案。

最容易描述的是每台机器。 在这种情况下,你想创建一个名为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条目。