Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Запрет работы нескольких копий программы

1.9K
31 января 2005 года
bad_duck
59 / / 29.07.2003
Хочу так: :)
Программа работает в скрытом режиме (никаких окон, иконок в трее, только процесс в диспетчере задач). А когда запускаешь ее снова, то вместо запуска второй копии программы, скрытая показывает окно с которым и можно работать.
Т.е. нужно запретить запуск нескольких копий программы и обеспечить взаимодействие "запускаемой" и работающей.
301
31 января 2005 года
lord Kelvin
897 / / 08.11.2004
Цитата:
Originally posted by bad_duck
Хочу так: :)
Программа работает в скрытом режиме (никаких окон, иконок в трее, только процесс в диспетчере задач). А когда запускаешь ее снова, то вместо запуска второй копии программы, скрытая показывает окно с которым и можно работать.
Т.е. нужно запретить запуск нескольких копий программы и обеспечить взаимодействие "запускаемой" и работающей.


Ну, хочешь. И что? Ты просто решил об этом рассказать?=)

Код:
int WINAPI  WinMain(HINSTANCE hI, HINSTANCE hPI, LPSTR CmdLine, int Show)
{
   HANDLE Test_Present = CreateMutex(NULL,false,"My_Program_Already_Present");
   if(GetLastError() == ERROR_ALREADY_EXISTS)
   {
       MessageBox(0,"Программа уже запущена",NULL,MB_OK);
       return 0;
   };
   CloseHandle(Test_Present);
   return 0;
}
1.9K
01 февраля 2005 года
bad_duck
59 / / 29.07.2003
Цитата:
Originally posted by lord Kelvin

Ну, хочешь. И что? Ты просто решил об этом рассказать?=)



гы. Да вот решил поделиться :)
Спасибо. А я все думал, для чего эти мутексы?
А как работающий процесс узнает том, что другую копию пытались запустить?

301
01 февраля 2005 года
lord Kelvin
897 / / 08.11.2004
Цитата:
Originally posted by bad_duck

гы. Да вот решил поделиться :)
Спасибо. А я все думал, для чего эти мутексы?
А как работающий процесс узнает том, что другую копию пытались запустить?


Mutex объявляется глобально, два одинаковых создать нельзя. Вот так. Если приглядеться к коду, то ты увидишь что если последняя ошибка ОШИБКА_УЖЕ_ЕСТЬ, то выдается сообщение, что программв уже запущена.

1.9K
01 февраля 2005 года
bad_duck
59 / / 29.07.2003
Цитата:
Originally posted by lord Kelvin

Mutex объявляется глобально, два одинаковых создать нельзя. Вот так. Если приглядеться к коду, то ты увидишь что если последняя ошибка ОШИБКА_УЖЕ_ЕСТЬ, то выдается сообщение, что программв уже запущена.


То-ли я чего-то не понял, то-ли ты меня непонял.
Повторно запускаемая копия узнает, что приложение уже запущено. Это ясно. А наоборот как? Т.е. сделать, чтобы уже находящийся в памяти и работающий процесс узнал о попытке повторного запуска.

1.9K
01 февраля 2005 года
bad_duck
59 / / 29.07.2003
И еще такая просьба. Не мог бы ты описать значения параметров CreateMutex. Потому как я понял только значение третьего :) У меня есть MSDN, но туго с английским.
368
01 февраля 2005 года
rostyslav
629 / / 13.07.2004
Цитата:
Originally posted by bad_duck
Т.е. сделать, чтобы уже находящийся в памяти и работающий процесс узнал о попытке повторного запуска.

Можно использовать событие.
Программа при запуске могла бы попытаться открыть конкретное событие, если оно есть, значит это вторая копия. Совсем упрощенно

Код:
HANDLE hEvent;

BOOL bRun = TRUE;

DWORD WINAPI myFunc(LPVOID)
{
  while(bRun==TRUE)
  {
    WaitForSingleObject(hEvent, INFINITE);
    AfxMessageBox("Event fired!");
    ResetEvent(hEvent);
  }
  return 0;
}

//при запуске

hEvent = OpenEvent(EVENT_ALL_ACCESS, FALSE, _T("My_Event"));
if(hEvent==NULL)  //первая копия
{
  hEvent = CreateEvent(NULL, FALSE, FALSE, _T("My_Event"));
  DWORD threadID;
  CreateThread(NULL, 0, myFunc, NULL, 0, &threadID);
}
else // запуск второй копии
{
  SetEvent(hEvent); // сообщение
  CloseHandle(hEvent);
  return 0;
}
301
01 февраля 2005 года
lord Kelvin
897 / / 08.11.2004
Цитата:
Originally posted by bad_duck
И еще такая просьба. Не мог бы ты описать значения параметров CreateMutex. Потому как я понял только значение третьего :) У меня есть MSDN, но туго с английским.


 
Код:
HANDLE CreateMutex(
    LPSECURITY_ATTRIBUTES lpMutexAttributes,    // указатель на структуру с атрибутами безопасности
    BOOL bInitialOwner, // кажется, наличие зозяина у мутекса
    LPCTSTR lpName  // указатель на имя.  
   );

Если у твоей программы есть окно - находишь его (при повторном запуске) FindWindow и посылаешь (SendMessage) экзотическое сообщение с экзотическими параметрами. Если программа его ловит - выскакивает на передний план, скажем. Вот.
1.9K
02 февраля 2005 года
bad_duck
59 / / 29.07.2003
Цитата:
Originally posted by lord Kelvin
Если у твоей программы есть окно - находишь его (при повторном запуске) FindWindow и посылаешь (SendMessage) экзотическое сообщение с экзотическими параметрами. Если программа его ловит - выскакивает на передний план, скажем. Вот.



Блин. Спасибо. Сам бы не догнал :)

301
02 февраля 2005 года
lord Kelvin
897 / / 08.11.2004
Цитата:
Originally posted by bad_duck

Блин. Спасибо. Сам бы не догнал :)


Оффтоп: Ты это сказал с иронией?

1.7K
06 февраля 2005 года
Envel
206 / / 29.11.2004
Цитата:
Originally posted by lord Kelvin

Оффтоп: Ты это сказал с иронией?


Роль mutex гораздо больше в многозадачном/многопоточном программировании.
И вообще, насколько помню, в Win3.1 второй параметр WinMain передавал HINSTANCE предыдущей копии процесса. Может, оно как-то и работает еще (хотя, где-то опять же читал, что параметр устарел, но это относилось к win95).

1.9K
15 февраля 2005 года
bad_duck
59 / / 29.07.2003
Цитата:
Originally posted by lord Kelvin

Оффтоп: Ты это сказал с иронией?



Ничего не понял. Вообще-то я смеюсь над собой :)

1.9K
15 февраля 2005 года
bad_duck
59 / / 29.07.2003
Цитата:
Originally posted by rostyslav
Можно использовать событие.
Программа при запуске могла бы попытаться открыть конкретное событие, если оно есть, значит это вторая копия. Совсем упрощенно
Код:
HANDLE hEvent;

BOOL bRun = TRUE;

DWORD WINAPI myFunc(LPVOID)
{
  while(bRun==TRUE)
  {
    WaitForSingleObject(hEvent, INFINITE);
    AfxMessageBox("Event fired!");
    ResetEvent(hEvent);
  }
  return 0;
}

//при запуске

hEvent = OpenEvent(EVENT_ALL_ACCESS, FALSE, _T("My_Event"));
if(hEvent==NULL)  //первая копия
{
  hEvent = CreateEvent(NULL, FALSE, FALSE, _T("My_Event"));
  DWORD threadID;
  CreateThread(NULL, 0, myFunc, NULL, 0, &threadID);
}
else // запуск второй копии
{
  SetEvent(hEvent); // сообщение
  CloseHandle(hEvent);
  return 0;
}



Как я понял созданый поток, в данном примере, будет ждать события и выводить окошко. А можно-ли вместо вывода MessageBox вызвать функцию CreateWindow из основного потока? Как все это будет работать?

487
19 февраля 2005 года
ddnh_bc
301 / / 16.09.2003
Цитата:
Originally posted by bad_duck


Как я понял созданый поток, в данном примере, будет ждать события и выводить окошко. А можно-ли вместо вывода MessageBox вызвать функцию CreateWindow из основного потока? Как все это будет работать?



А почему нет?
Thread - это такой-же фрагмент кода в твоей программе как и MainThread. Сидят они в одном адресном пространстве и используют одни и те-же библиотеки и.т.п. Единственные грабли - на которые можно наступить при разработке Multithread приложений - некорректная обработка доступа нескольких потоков к одним и тем-же участкам памяти.

6.5K
20 февраля 2005 года
Kanary
33 / / 10.02.2005
Цитата:
Originally posted by bad_duck

То-ли я чего-то не понял, то-ли ты меня непонял.
Повторно запускаемая копия узнает, что приложение уже запущено. Это ясно. А наоборот как? Т.е. сделать, чтобы уже находящийся в памяти и работающий процесс узнал о попытке повторного запуска.



Попробуй через зашареные секции.
Типа:

#pragma data_seg("Shared")
volatile int CountApp=0;
#pragma data_seg()

#pragma comment(linker,"/Selection:Shared,RWS")

Переменная CountApp - доступна из любого екземпляра приложения. Увеличивай её при запуске приложения и уменьшай при закрытии, будешь знать количество приложений. Только грабли: нужно её инициализировать; и в строке #pragma comment... в кавычках не поставь пробела.

По-моему так...

584
17 марта 2007 года
brodotsky
33 / / 25.01.2004
Насчет mutex.
Чтобы не допустить
запуск других экземпляров программы,
нужно создать ИМЕННОВАНЫЙ mutex
(если НЕИМЕННОВАННЫЙ, то не сработает GetLastError).
Но любое заранее определенное имя
может уже использоваться.
Таким образом, я рискую,
что ни один экземпляр не запустится.

Вопрос такой - как гарантировать,
что первый экземплят точно запустится,
а второй - точно не запустится?

Вообще, хотелось бы иметь что-то вроде FindProcess ().
А всякие левые способы типа FindWindow ()
мне не нравятся.
В последнем случае нужно искать окно
определенного класса с определенным заголовком.
А вдруг у чужой программы класс и заголовок такие же,
как и у моей?

Хочу ГАРАНТИРОВАННОЙ работы программ!
А Microsoft на каждом шагу предлагает
ПОЛАГАТЬСЯ НА "АВОСЬ".
263
17 марта 2007 года
koltaviy
816 / / 16.12.2004
Цитата: brodotsky

..
Но любое заранее определенное имя
может уже использоваться.
..


С чего ты взял?? Просто не создавай имена типа "Hallo", "Test" или "Mutex":D.. Если уж ты настолько 'озабочен' этой "проблемой", используй генераторы уникальных идентификаторов. Их в Интернете полно. Я использую UUID, когда нужно. В VS 2005, насколько я помню, есть встроенный генератор.

Цитата: brodotsky

..
Таким образом, я рискую,
что ни один экземпляр не запустится.
..


Определенный риск при использовании Mutex конечно есть. К примеру, если твоя программа экстренно завершилась - не всегда можно предположить, что случилось с Mutex. Есть несколько способов обеспечения запуска единственной копии приложения(где-то валялась статья по этому поводу), к примеру, создание временного файла на время работы программы и т.д..
ИМХО: Использование Mutex наиболее уместно в данном случае!

Цитата: brodotsky

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


Очень просто - грамотно написать рабочую прорамму, чтобы у тебя хотя бы первая копия запустилась:D

Цитата: brodotsky

А вдруг у чужой программы класс и заголовок такие же,
как и у моей?


У тебя прям мания какая-то!!:D Для этого существуют области имен!

Цитата: brodotsky

Хочу ГАРАНТИРОВАННОЙ работы программ!
А Microsoft на каждом шагу предлагает
ПОЛАГАТЬСЯ НА "АВОСЬ".


Блин, еще один!! Тогда чо ты лезешь в программирование под Windows - программируй под другие ОС!! И где это интересно она в официальных источниках 'такое' предлагала?!

584
18 марта 2007 года
brodotsky
33 / / 25.01.2004
Не понял насчет генератора уникального имени.
Он что, все Mutexы в системе проверит?

Про временный файл - хорошая идея, я уже думал.
Тем более есть какая-то функция
для поиска уникального имени файла.
(Правда, можно опасаться,
что второй экземпляр стартует раньше,
чем первый экземпляр создаст файл.
Но это действительно уже на невроз тянет).

Насчет грамотной рабочей программы.
С этим-то проблем нет.
Проблема, чтобы моя защита против второго экземпляра
не сработала против первого.

Насчет области имен - опять же, не понял.
Я всегда думал,
что имена классов главных окон приложений
хранятся в какой-то общесистемной области.
Разве нет?

Не заявляла Microsoft ОФИЦИАЛЬНО,
что надо полагаться на "авось"?
Еще бы она заявляла.
Официально-то у нее все безоблачно...

Вообще-то я не люблю брюзжать про "плохую Microsoft".
Во-первых, я пользователь многих ее продуктов,
а во-вторых -
они не слабые специалисты по маркетингу.
Их среднего качества продукты
успешно борятся с более качественными.
Это надо уметь.
292
19 марта 2007 года
Matush
726 / / 14.01.2004
Цитата: brodotsky
Не понял насчет генератора уникального имени.
Он что, все Mutexы в системе проверит?


Ничего он проверять не будет. Но GUID тебе даст уникальный (почитай что это такое).

P.S. Mutex'а вполне достаточно для контроля запуска одной копии программы. Ставь мьютекс и не заморачивай голову. Все будет работать.

 
Код:
[SIZE=2][COLOR=#808080][COLOR=black]m_hMutex = CreateMutex(NULL, FALSE, g_pProgramGUID);[/COLOR][/COLOR][/SIZE]
[COLOR=#808080][SIZE=2][COLOR=black]if(m_hMutex == INVALID_HANDLE_VALUE)[/COLOR][/SIZE]
[SIZE=2][COLOR=black]   return -1;[/COLOR][/SIZE]
[SIZE=2][COLOR=black]int res = WaitForSingleObject(m_hMutex, 0);[/COLOR][/SIZE]
[SIZE=2][COLOR=black]if(res == WAIT_TIMEOUT)[/COLOR][/SIZE]
[SIZE=2][COLOR=black]   return -1;[/COLOR][/SIZE]
[/COLOR]
334
19 марта 2007 года
HexEdit
809 / / 27.07.2006
А я юзаю генератор паролей, генерирую из 20-30 символов, со всеми символами )). Это тоже вариант.
292
19 марта 2007 года
Matush
726 / / 14.01.2004
Цитата: HexEdit
А я юзаю генератор паролей, генерирую из 20-30 символов, со всеми символами )). Это тоже вариант.


Это конечно мало вероятно что они повторятся :)
Но GUID был специально придуман для уникальности. Так что его и надо юзать

584
19 марта 2007 года
brodotsky
33 / / 25.01.2004
Я написал по простому.
В начале функции WinMain поместил 2 строчки:

CreateMutex (NULL,FALSE,MUTEX_NAME);
if (GetLastError ()==ERROR_ALREADY_EXISTS) return 0;

Все работает как надо, а в качестве идентификатора
я взял более или менее заковыристую строку.

Что касается GUID, то слабоваты познания
(ни разу не приходилось использовать).
Я посмотрел документацию (ole.hlp):
"CoCreateGuid. Creates a GUID, a unique 128-bit integer...
Use the CoCreateGuid function when you need an absolutely unique number...
To a very high degree of certainty, this function returns a unique value..."
Т.е. функция CoCreateGuid
создает 128-битовое целое значение,
которое с большой вероятностью уникально.

Судя по всему,
просто создается случайная последовательность
из 128 битов.
Количество вариантов - 2 в степени 128.
Это примерно 10 в 38-ой.
Вероятность повтора - 10 в минус 38-ой (очень мала).

Так вот.
По-моему, с таким же точно успехом
можно использовать в Mutexе
строку из 128 случайных символов.
Впрочем, с GUID удобнее - не надо forов и randomов.
263
20 марта 2007 года
koltaviy
816 / / 16.12.2004
Вариантов, что идентификаторы повторятся вообще нет! GUID'э, по идее, должны генерится на каждой машине разные - исходя из разных параметров системы и железа(типа номер поца)!!
Точно параметров не знаю;), но то, что на уникальность можно рассчитывать - 101%. Видимо по этому вероятность совпадения GUID и не оговорена в help'е:D
4.6K
23 марта 2007 года
Tokolist
268 / / 22.03.2007
Извиняюсь за свои 5 копеек :)

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

А для передачи данных между экземплярами оконного приложения лучше всего подходит сообщение WM_COPYDATA.

Если будет нужно приведу пример на C++ или Delphi.
279
22 апреля 2007 года
bave
456 / / 07.03.2004
А чтобы имена уникальные получать в каждом процессе, можно использовать pid - он точно для каждого процесса разный будет.
------------------------------
 
Код:
memset(g_szEventName, 0, 128);
sprintf(g_szEventName,"event_%u", _getpid());
g_tpsMain.m_hEvent = bthread::newsignal(FALSE, FALSE, g_szEventName);

-------------------------------
Хотя если нужкн один уникальный для всех процессов, а не уникальный в каждом процессе, то не катит.
279
22 апреля 2007 года
bave
456 / / 07.03.2004
Есть тоже пара вопросов по Mutex'aм:
(хотел создать новую тему, ну думаю здесь будет тоже втему).
Вобщем я использую mutex-ы для синхронизации процессов, которые делают записи в один и тот же файл.
Допустим стандартная ситуация:
Один процесс(поток процесса) занял под себя Mutex, а другой соответствено ждёт используя WaitForSingleObject и если первый процесс отработал корректно он вызовёт ReleaseMutex, и тогда во втором процессе WaitForSingleObject вернёт WAIT_OBJECT_0 - но вот интересуют две ситуации:
1. что будет если первый процесс завершится из-за какой либо ошибки - по идее mutex object тоже тогда освободится, но что тогда вернёт функция - WaitForSingleObject?
2. Допустим Mutex ждут много процессов, тогда кто первый из них его получит - тот кто первый вызвал WaitForSingleObject?
-------------------
Данные вопросы связаны с моим фиговым знанием англ. языка - я вижу
в MSDN что там какая то засада описана с некорректным завершением потока, который занимает Mutex, но чёт не очень врубаюсь какая...
367
22 апреля 2007 года
Meatcoins
303 / / 18.01.2006
Есть ещё и семафоры с событиями!
Будто Mutex'ы - это ответ на все проблемы!
Копай в сторону CreateSemaphore - семафоры!
+ CreateEvent - события!
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог