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

发布于 2024-07-17 22:47:03 字数 251 浏览 6 评论 0原文

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

相关

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

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

悟红尘 2024-07-24 22:47:03

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

如果您需要的只是一个简单的检查,则无需变得疯狂的复杂...

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...

幸福%小乖 2024-07-24 22:47:03

我认为在继续之前你需要考虑一下你的场景。 对于“多次运行同一个程序”有许多不同的解释。 例如,

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

所有这些都有不同但相似的解决方案。

最容易描述的是每台机器。 在本例中,您想要创建一个命名的互斥体。 每个程序在启动时都必须获取该互斥锁,如果成功,它们就会在进程生命周期内运行并保留该互斥锁。 否则,其他程序正在运行,它们会立即退出。

不幸的是,这种方法也有其缺点。 如果我想搞乱你的程序,我可以创建一个同名的互斥体。 这将阻止您的程序运行任何实例,因为它们无法判断谁持有互斥锁,只是知道有什么东西持有互斥锁。

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

  1. Once per machine
  2. Once per logon session
  3. 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.

旧瑾黎汐 2024-07-24 22:47:03

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

实际上,有人提出了关于为此目的使用互斥体的问题 在这里查看 JaredPar 的答案。

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

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)

沐歌 2024-07-24 22:47:03

最好的方法是使用互斥锁。 请参阅使用互斥对象

The best way is to use a mutex. See Using Mutex Objects.

灯角 2024-07-24 22:47:03

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

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;
    }
}
财迷小姐 2024-07-24 22:47:03

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

因此您可以轻松限制并行进程的数量。

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.

自由如风 2024-07-24 22:47:03

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

When you use Qt you can download the QtSingleApplication component.

青萝楚歌 2024-07-24 22:47:03

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

MS 的 CreateMutex() 文档 有一个许多有用的信息,并专门解决了使用互斥体来防止程序的多个实例运行的情况。 特别是:

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

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() with bInitialOwner = 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.
素手挽清风 2024-07-24 22:47:03

在程序启动时,您可以枚举计算机上运行的进程

然后如果你发现你已经在运行了,退出

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

各自安好 2024-07-24 22:47:03

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

You could check if window class is already registered. Take a look at this MSDN entry.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文