C / C ++ Как узнать, запущена ли уже программа? - PullRequest
2 голосов
/ 29 апреля 2009

В среде Windows я не хочу, чтобы два экземпляра моей программы запускались одновременно.

Относящиеся

Использует ли Mutex для предотвращения безопасного выполнения нескольких экземпляров одной и той же программы?

Ответы [ 10 ]

10 голосов
/ 29 апреля 2009

Я думаю, вам нужно немного рассмотреть свой сценарий, прежде чем идти вперед. Существует много разных интерпретаций «запуска одной и той же программы» более одного раза. Например, вы

  1. Один раз на машину
  2. Один раз за сеанс входа в систему
  3. Один раз на пользователя

Все они имеют разные, хотя и похожие, решения.

Проще всего описать на каждую машину. В этом случае вы хотите создать именованный Mutex. При каждом запуске каждая программа должна получить этот мьютекс, если они успешны, они запускаются и удерживают Mutex в течение всего времени жизни процесса. В противном случае запускается какая-то другая программа, и они немедленно закрываются.

К сожалению, у этого подхода есть свои недостатки. Если я хочу испортить вашу программу, я могу создать мьютекс с тем же именем. Это предотвратит запуск вашей программы любым экземпляром, потому что они не могут определить, кто владеет Mutex, просто что-то содержит мьютекс.

9 голосов
/ 29 апреля 2009

Вы можете создать мьютекс при запуске первого экземпляра вашего приложения. Для предотвращения второго экземпляра все, что вам нужно сделать, это проверить, используется ли мьютекс.

На самом деле был задан вопрос об использовании мьютексов для этой цели здесь проверьте ответ JaredPar.

Примечание. Вы можете использовать локальный мьютекс, если хотите, чтобы «один экземпляр» применялся только в течение сеанса пользователя (а не для всех пользователей)

7 голосов
/ 06 января 2013

Если это ваша программа, то самая короткая версия под 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 голосов
/ 29 апреля 2009

Альтернативное простое решение - создать подходящее уникальное глобальное именованное событие (возможно, строку 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;
    }
}
3 голосов
/ 29 апреля 2009

Лучший способ - использовать мьютекс. См. Использование объектов Mutex .

2 голосов
/ 29 апреля 2009

Когда вы используете Qt, вы можете загрузить компонент QtSingleApplication .

2 голосов
/ 29 апреля 2009

это класс, который я написал с использованием 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)
{
 ...
}

, чтобы вы могли легко ограничить количество параллельных процессов.

1 голос
/ 29 апреля 2009

Используйте мьютекс, как предлагали другие.

В документации CreateMutex () от MS содержится много полезной информации, в частности, речь идет о случае использования мьютексов для предотвращения запуска более одного экземпляра программы. В частности:

  • Вызовите CreateMutex() с помощью bInitialOwner = FALSE, затем вызовите функцию ожидания (например, WaitForSingleObject()), чтобы убедиться, что только один экземпляр получает мьютекс.
  • Попробуйте использовать заблокированный файл, если вас беспокоит атака типа "отказ в обслуживании".
0 голосов
/ 29 апреля 2009

При запуске вашей программы вы можете перечислить процессы, запущенные на вашем компьютере

Тогда, если вы видите, что уже работаете, выйдите из системы

0 голосов
/ 29 апреля 2009

Вы можете проверить, если класс окна уже зарегистрирован. Взгляните на эту запись MSDN.

...