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

时间:2009-04-29 03:10:53

标签: c++ c windows systems-programming

在Windows环境中,我不希望我的程序的两个实例同时运行。

  

相关

     

Is using a Mutex to prevent multiple instances of the same program from running safe?

10 个答案:

答案 0 :(得分:10)

我认为你需要在前进之前考虑一下你的情景。不止一次对“运行相同程序”有许多不同的解释。比如你

  1. 每台机器一次
  2. 每次登录会话
  3. 每位用户一次
  4. 所有这些都有不同的,虽然相似的解决方案。

    最容易描述的是每台机器。在这种情况下,您想要创建一个名为Mutex。一个启动每个程序必须获得这个互斥锁,如果它们成功,它们会在进程生命周期内运行并持有互斥锁。否则其他一些程序正在运行,它们会立即退出。

    不幸的是,这种方法也有其缺点。如果我想弄乱你的程序,我可以创建一个具有相同名称的互斥锁。这将阻止您的程序运行任何实例,因为他们无法分辨谁拥有互斥锁,只是某些东西持有互斥锁。

答案 1 :(得分:9)

您可以在应用程序的第一个实例启动时创建互斥锁。要防止第二个实例,您需要做的就是检查是否正在使用互斥锁。

实际上有一个问题是关于为此目的使用互斥量here查看JaredPar的答案。

注意:如果您希望“一个实例”仅应用于用户的会话(而不是所有用户),则可以使用本地互斥锁

答案 2 :(得分:7)

如果是您的程序,那么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 ...
}

如果您只需要一个简单的检查,就不需要疯狂复杂......

答案 3 :(得分:3)

最好的方法是使用互斥锁。见Using Mutex Objects

答案 4 :(得分:3)

另一种简单的解决方案是创建一个适当唯一的全局命名事件(可能是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;
    }
}

答案 5 :(得分:2)

这是我使用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)
{
 ...
}

因此您可以轻松地并行限制多少个进程。

答案 6 :(得分:2)

使用Qt时,您可以下载QtSingleApplication组件。

答案 7 :(得分:1)

正如其他人所建议的那样使用互斥锁。

来自MS的CreateMutex() documentation有很多有用的信息,并且特别针对使用互斥锁来防止多个程序实例运行的情况。特别是:

  • 使用CreateMutex()致电bInitialOwner = FALSE,然后调用等待函数(例如WaitForSingleObject())以确保只有一个实例获取互斥锁。
  • 如果您担心拒绝服务攻击,请考虑使用锁定文件。

答案 8 :(得分:0)

在程序启动时,您可以enumerate the processes running on your machine

然后,如果您发现自己已经在运行,请退出

答案 9 :(得分:-1)

您可以检查窗口类是否已注册。请查看this MSDN条目。