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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/800730/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 12:22:12  来源:igfitidea点击:

C/C++ How to tell if a program is already running?

c++cwindowssystems-programming

提问by Jorma Rebane

In a Windows environment, I don't want two instances of my program running at the same time.

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

Related

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

有关的

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

回答by JaredPar

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
  1. 每台机器一次
  2. 每个登录会话一次
  3. 每个用户一次

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.

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

回答by RobS

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 herecheck out JaredPar's answer.

实际上,这里提出了一个关于为此目的使用互斥锁的问题请查看 JaredPar 的回答。

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)

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

回答by Jorma Rebane

If it's your program, then the shortest possible version under 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 ...
}

No need to get crazy complex, if all you needed was a simple check...

没有必要变得疯狂复杂,如果你需要的只是一个简单的检查......

回答by Murray

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

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

回答by binarybob

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

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

回答by corné

When you use Qt you can download the QtSingleApplicationcomponent.

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

回答by t.g.

this is a class I scripted using boost.interrprocess, I use it to sync between the GUI and CLI versions.

这是我使用boost.interrprocess编写的一个类,我用它在 GUI 和 CLI 版本之间进行同步。

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.

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

回答by j_random_hacker

Use a mutex, as others have suggested.

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

That CreateMutex() documentationfrom 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:

也就是说CreateMutex()文档从MS具有很多有用的信息,并具体涉及使用互斥用于防止程序的多个实例运行的情况下。特别是:

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

回答by Eric

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

然后,如果您看到您已经在运行,请退出

回答by Pablo Santa Cruz

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

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