ar0j
ar0j

Reputation:

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

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?

Upvotes: 7

Views: 25898

Answers (10)

Jorma Rebane
Jorma Rebane

Reputation: 626

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

Upvotes: 17

corné
corné

Reputation: 798

When you use Qt you can download the QtSingleApplication component.

Upvotes: 2

t.g.
t.g.

Reputation: 1749

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.

Upvotes: 2

binarybob
binarybob

Reputation: 3569

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;
    }
}

Upvotes: 3

Eric
Eric

Reputation: 19873

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

Upvotes: 0

j_random_hacker
j_random_hacker

Reputation: 51316

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.

Upvotes: 1

JaredPar
JaredPar

Reputation: 755307

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.

Upvotes: 12

RobS
RobS

Reputation: 9422

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)

Upvotes: 9

Murray
Murray

Reputation: 690

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

Upvotes: 3

Pablo Santa Cruz
Pablo Santa Cruz

Reputation: 181430

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

Upvotes: -1

Related Questions