Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > определить, запущена ли программа?


Автор: andrew_121 18.5.2009, 10:29
Нужно определить запущена ли программа дважды. Если один экземпляр уже запущен, убить, и запуститься.

Автор: azesmcar 18.5.2009, 10:46
Цитата(andrew_121 @  18.5.2009,  10:29 Найти цитируемый пост)
Нужно определить запущена ли программа дважды. Если один экземпляр уже запущен, убить, и запуститься. 

Создавай мютекс, при старте программы проверяй его наличие.
Функция CreateMutex

Автор: Lazin 18.5.2009, 10:47
Цитата(azesmcar @  18.5.2009,  10:46 Найти цитируемый пост)
Создавай мютекс, при старте программы проверяй его наличие.

именованый мюьтекс

Автор: azesmcar 18.5.2009, 10:48
примерно так
Код

if (CreateMutex(NULL, false, "MYMUTEXUNIQUENAME") == 0 || GetLastError() == ERROR_ALREADY_EXISTS)
{
    //Program is already running!
}


Добавлено @ 10:51
Цитата(Lazin @  18.5.2009,  10:47 Найти цитируемый пост)
именованый мюьтекс 

ну да, я это в примере показал smile 

Автор: Mechanic 18.5.2009, 10:55
Проблема достаточно древняя. Видел отличный, подробнейший разбор методов, с анализом недостатков каждого. Даавно. Понравился.  smile 
Может быть, и не здесь, но на похожем форуме.. ;-)
Поиск рулит.  smile 

Во, кажется нашел.
http://rsdn.ru/article/baseserv/avins.xml.
И http://forum.sources.ru/index.php?showtopic=192835.

Автор: andrew_121 18.5.2009, 11:09
Ну допустим мьютекс существует, как мне убить тот экземпляр который был запущен ранее.
А при завершении программы мьютекс уничтожается?

Автор: azesmcar 18.5.2009, 11:10
andrew_121

Цитата

Use the CloseHandle function to close the handle. The system closes the handle automatically when the process terminates. The mutex object is destroyed when its last handle has been closed. 
 

Автор: artsb 18.5.2009, 11:21
Цитата(andrew_121 @  18.5.2009,  10:29 Найти цитируемый пост)
Если один экземпляр уже запущен, убить, и запуститься.

Если надо убивать уже запущенную прогу, а не ту которая только запустилась, придётся юзать сообщения, чтобы уже запущенная себя убила  smile 

Автор: andrew_121 18.5.2009, 11:51
Цитата(artsb @  18.5.2009,  11:21 Найти цитируемый пост)
придётся юзать сообщения

Это как?

Автор: azesmcar 18.5.2009, 11:52
Цитата(andrew_121 @  18.5.2009,  11:51 Найти цитируемый пост)
Это как? 

Код

SendMessage(handle, WM_QUIT ... );

Автор: andrew_121 18.5.2009, 11:59
azesmcar, Ща попробую.

Автор: Mechanic 18.5.2009, 12:05
Цитата(artsb @  18.5.2009,  11:21 Найти цитируемый пост)
Если надо убивать уже запущенную прогу, а не ту которая только запустилась, придётся юзать сообщения, чтобы уже запущенная себя убила  smile 


Скорее всего. Вот только сообщения в кого? Нужно при запуске где-то сохранять или Window.Handle для сообщения, или же ProcessHandle for TerminateProcess. Может быть "атомные" технологии помогут?

Хотя, если есть окно - то совсем просто найдется всё, что имеет нужные окна.
Окна-то есть?  smile 

Автор: GremlinProg 18.5.2009, 12:27
WM_QUIT конечно поможет, если перед закрытием не потребуется участие пользователя при сохранении каких-либо данных

а так - можно создать то же именованое автоматически-сбрасываемое событие и тестировать его в главном цикле сообщений на предмет автоматического сохранения всех данных и завершения приложения, типа такого:
Код

while( ::GetMessage(...) ){

  Translate...
  Dispatch...

  if( ::WaitForSingleObject(hAbortEvent,0) == WAIT_OBJECT_0 ){
    save_quietly_all();
    ::PostQuitMessage(S_OK);
  }

}

или отдельным потоком аналогично слушать hAbortEvent, так будет немного экономнее, только PostQuitMessage придется заменить на нечто вроде такого:
Цитата(azesmcar @  18.5.2009,  13:52 Найти цитируемый пост)
SendMessage(handle, WM_QUIT ... );


Добавлено через 4 минуты и 22 секунды
тогда и окно искать не потребуется:
Код

if (CreateMutex(NULL, false, "MYMUTEXUNIQUENAME") == 0 || GetLastError() == ERROR_ALREADY_EXISTS){
  ::SetEvent(hAbortEvent);
}

ps: код azesmcar

Автор: artsb 18.5.2009, 13:34
andrew_121, пример в атаче (BCB 6). Возможно, немного коряво smile

Такой вариант можешь юзать, если необходимо корректно закрыть прогу, т.е. сохранить какие-то данные и т.п. Иначе просто шли WM_QUIT и не обрабатывай своё сообщение.  smile 

Автор: Alca 18.5.2009, 14:40
Код

//---------------------------------------------------------------------------
bool bWeAreAlone(LPWSTR wzName) {
    HANDLE hMutex = CreateMutex(NULL,TRUE, wzName);
    if (GetLastError() == ERROR_ALREADY_EXISTS) {
        CloseHandle(hMutex);
        return false;
    } else {
        return true;
    }
}
//---------------------------------------------------------------------------
WINAPI _tWinMain(HINSTANCE, HINSTANCE, LPTSTR, int) {
    //-------------------------------------
    //запущена ли прога?
    if (bWeAreAlone(L"Start_Unique_Name") == false) {
        return 0;
    }
    ....
}
//---------------------------------------------------------------------------

Автор: artsb 18.5.2009, 15:15
Alca, надо не себя закрыть, а прогу, которая до этого работала  smile 

Автор: Alca 18.5.2009, 15:26
Значит плохо прочитал топик.  smile 

Автор: korbian 19.5.2009, 09:07
GremlinProg, можно одним эвентом обойтись.

псевдокод
Код

if( !OpenEvent(...) )
{
    CreateEvent(...); // эвент несигнализирующий :)
}
else
{
    SetEvent(...);
    ResetEvent(...);
}

а после диспатча или в выделенном потоке ваш код с ожиданием события!

Автор: GremlinProg 19.5.2009, 13:50
korbian, можно, а почему без автомата? это же риск просто не закрыть окно
Код

hAbortEvent = ::CreateEvent(NULL, FALSE, FALSE, "MYEVENT");
if( ::GetLastError() == ERROR_ALREADY_EXISTS ){
  ::SetEvent(hAbortEvent);
}

можно подстраховаться и использовать два события, из которых второй, фидбэк - неавтомат:
Код

hFeedback   = ::CreateEvent(NULL, TRUE, FALSE, "MYFBEVENT");
hAbortEvent = ::CreateEvent(NULL, FALSE, FALSE, "MYEVENT");
if( GetLastError() == ERROR_ALREADY_EXISTS ){
  ::SignalObjectAndWait(hAbortEvent,hFeedback,INFINITE);
}

а в закрывающемся процессе вызвать PulseEvent для hFeedback

Добавлено через 13 минут и 25 секунд
Цитата(GremlinProg @  19.5.2009,  15:50 Найти цитируемый пост)
::SignalObjectAndWait(hAbortEvent,hFeedback,INFINITE);

Код

::SignalObjectAndWait(hAbortEvent,hFeedback,INFINITE,FALSE);

Автор: GremlinProg 19.5.2009, 14:06
а еще лучше использовать для сигнализации семафор, а не событие, тогда три и более подряд открытых окон разберутся между собой правильно

Автор: korbian 19.5.2009, 14:06
GremlinProg, соглашусь, что ошибался. smile
Проскользнула идея запользовать тотже евент для фидбэка, но похоже без двух объектов синхронизации действительно не обойтись. 

Автор: GoldFinch 19.5.2009, 19:03
создать shared секцию, и хранить в ней флаги, хендлы и т.п.
или FileMapping, но секция лучше, т.к. файл один 

Автор: korbian 20.5.2009, 08:32
GoldFinch, все равно без синхронизации обращения к общей секции или filemapping не обойтись, а значит мьютексы, эвенты или семафоры.

Автор: GoldFinch 20.5.2009, 18:21
korbian, в большинстве случаев, достаточно volatile флагов

Автор: GremlinProg 20.5.2009, 18:28
Цитата(GoldFinch @  20.5.2009,  20:21 Найти цитируемый пост)
в большинстве случаев, достаточно volatile флагов

не надо мешать огурцы с утюгами
для двух разных процессов volatile ни чего не решает, как и взаимоблокировки
тут в любом случае нужны объекты ядра, korbian верно говорит

Автор: GoldFinch 20.5.2009, 20:03
GremlinProg, все же тема не о тех случаях когда нужна синхронизация

Автор: GremlinProg 20.5.2009, 20:57
Цитата(GoldFinch @  20.5.2009,  22:03 Найти цитируемый пост)
тема не о тех случаях когда нужна синхронизация

для примера: создай общую секцию с одной переменной типа int
запусти 100-200 процессов, которые будут инкрементировать эту переменную и выводить окно со своим номером, если счетчик дощел до пика (для 100 - 100, для 200 - 200)

в идеале, на одну серию запусков, всегда должно выводиться окно,
но при наложении запусков, этого просто не будет, счетчик не будет доходить до пика
(наложение можно имитировать вставкой Sleep между чтением и записью в секцию)

так что без синхронизации, секции особого смысла не имеют, с меппингом - аналогично

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)