Запрет запуска нескольких копий программы
Запрет запуска нескольких копий программы бывает полезен если может возникнуть конфликт из-за занятых системных ресурсов, монопольно открытых файлов или если задачи приложения подразумевают наличие только одного его экземпляра. Проверка наличия работающей копии программы реализуется несколькими способами в зависимости от поставленной задачи.Первый способ основан на том, что в приложении можно определить расшаренную секцию, данные из которой будут доступны для всех его запущенных экземпляров. Достаточно прописать в ней некоторую переменную и присвоить ей уникальное значение. При старте выполняется проверка, и если значение переменной равно начальному, то считается что это старт первой копии, иначе приложение является второй копией и должно завершить свою работу. Поэтому первая копия приложения сразу после запуска и проверки должна заменить значение переменной на другое.
Code (Assembler) : Убрать нумерацию
- ; Расшаренная секция, общая для всех копий данного приложения
- section '.shared' data readable writeable shareable
- started dd 1 ; Флаг первого запуска
- ; Сегмент кода
- section '.code' code readable executable
- cmp [started],1 ; Уже запущен экземпляр программы?
- jne already_started ; Да, на выход
- xor eax,eax
- ; Префикс LOCK и команда XCHG используются для предотвращения
- ; возможных конфликтов на многопроцессорных машинах
- lock xchg eax,[started] ; Сбросить флаг
- ; Нормальный запуск программы
- ...
- already_started:
- ; Выход из программы
- ...
Второй способ использует поиск окна по заголовку или имени класса окна через функцию FindWindow. Этот способ может применяться для глобального запрета запуска второй копии приложения.
Code (Assembler) : Убрать нумерацию
- ; Сегмент данных
- section '.data' data readable writeable
- title db 'Only One Demo #2',0 ; Заголовок окна
- ; Сегмент кода
- section '.code' code readable executable
- ...
- invoke FindWindow,NULL,title ; Попробовать найти окно по заголовку
- or eax,eax ; Уже запущен экземпляр программы?
- jnz already_started ; Да, на выход
- ; Нормальный запуск программы
- ...
- already_started:
- ; Выход из программы
- ...
Третий, самый надежный и предпочтительный способ глобальной проверки и запрета основан на использовании мьютексов. Одновременно в системе не может быть двух мьютексов с одинаковыми именами, поэтому если один процесс создаст мьютекс с уникальным именем, то попытка создания одноименного мьютекса пока активен первый процесс, приведет к возникновению ошибки ERROR_ALREADY_EXISTS. Это и будет считаться признаком того, что одна копия вашей программы уже находится в памяти.
Code (Assembler) : Убрать нумерацию
- ; Определить константу кода ошибки
- ERROR_ALREADY_EXISTS = 000000B7h
- ; Сегмент данных
- section '.data' data readable writeable
- mutex db 'Only One Demo #3',0 ; Уникальное имя мьютекса
- ; Сегмент кода
- section '.code' code readable executable
- ...
- invoke CreateMutex,NULL,0,mutex ; Создать мьютекс
- invoke GetLastError ; Проверить код ошибки
- cmp eax,ERROR_ALREADY_EXISTS ; Такой мьютекс уже есть?
- je already_started ; Да, на выход
- ; Нормальный запуск программы
- ...
- already_started:
- ; Выход из программы
- ...
If you need to detect whether another instance already exists, create a named mutex using the CreateMutex function. If the GetLastError function returns ERROR_ALREADY_EXISTS, another instance of your application exists (it created the mutex).
Просто имейте этот факт в виду. Вместо мьютексов точно по такой же схеме можно использовать события (events) с уникальными именами. Работа с ними осуществляется с помощью функций OpenEvent и CreateEvent.
Четвертый способ основан на создании в памяти виртуального файла при помощи функции CreateFileMapping. Аналогично мьютексам и событиям в системе одновременно может быть создан только один виртуальный файл с определенным именем. Попытки создания второго такого же файла приведут к ошибке ERROR_ALREADY_EXISTS.
Code (Assembler) : Убрать нумерацию
- ; Определить константу кода ошибки
- ERROR_ALREADY_EXISTS = 000000B7h
- ; Сегмент данных
- section '.data' data readable writeable
- fname db 'Only One Demo 4',0 ; Уникальное имя виртуального файла
- ; Сегмент кода
- section '.code' code readable executable
- ...
- invoke CreateFileMapping,0FFFFFFFFh,NULL,\
- PAGE_READWRITE,NULL,1024,fname ; Создать виртуальный файл
- invoke GetLastError ; Проверить код ошибки
- cmp eax,ERROR_ALREADY_EXISTS ; Такой виртуальный файл уже есть?
- je already_started ; Да, на выход
- ; Нормальный запуск программы
- ...
- already_started:
- ; Выход из программы
- ...
Не забывайте в разных ваших программах использовать разные имена мьютексов, событий, виртуальных файлов, классов окон, заголовков окон и т.д. А то после неудачного копипаста куска кода придется немало поломать голову почему приложение работает не так как надо. Примеры программ с исходными текстами для всех описанных способов прилагаются.
Просмотров: 16134 | Комментариев: 7
Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье
ManHunter
(23.09.2018 в 23:04):
Элементарно. Начинаешь создавать мьютексы с числовым счетчиком, типа "Mutex_01", "Mutex_02" и т.д., увеличивая счетчик до нужного значения, пока не встретится свободный. Если все мьютексы окажутся заняты, значит предельное количество копий приложения уже запущено. Аналогично с CreateFileMapping.
Aleksandr
(23.09.2018 в 02:32):
А как реализовать запуск ограниченного числа копий программы больше одного ?
Adam.Martin
(07.09.2010 в 14:34):
Автору спасибо. Для меня лично - очень полезный ресурс
ManHunter
(06.09.2010 в 16:13):
Чо-то долго шел :)
Adam.Martin
(06.09.2010 в 16:11):
Вот для этого и нужен интернет.
Нужно было на FASMe проверить копию программы в памяти. Чтото слышал про мьютекс, нужен был пример, вышел на эту страницу в 2 минуты.
Нужно было на FASMe проверить копию программы в памяти. Чтото слышал про мьютекс, нужен был пример, вышел на эту страницу в 2 минуты.
BarMentaLisk
(11.02.2009 в 19:58):
Весьма подробно все описано, спасибо!
Лично я пока довольствовался проверкой существования одноименного окна, но может когда-нибудь для безоконного приложения заюзаю и мутексы =).
Лично я пока довольствовался проверкой существования одноименного окна, но может когда-нибудь для безоконного приложения заюзаю и мутексы =).
Добавить комментарий
Заполните форму для добавления комментария
http://www.manhunter.ru/assemb...ogrammi.html