IPB
ЛогинПароль:

> ВНИМАНИЕ!

Прежде чем задать вопрос, смотрите FAQ.
Рекомендуем загрузить DRKB.

Наладить общение поможет, если вы подпишитесь по почте на новые темы в этом форуме.

 
 Ответить  Открыть новую тему 
> Отслеживание двойного запуска
сообщение
Сообщение #1


mea culpa
*****

Группа: Пользователи
Сообщений: 1 372
Пол: Мужской
Реальное имя: Николай

Репутация: -  24  +


Нужно встроить в программу проверку, не запущена ли уже эта её копия. В гугле это есть, но.. осложняется тем, что теоретический дабл-запуск будет как бы фор-кликом, то есть мгновенно после первого запуска. И видимой формы тоже нет..


--------------------
"Знаешь, стыдно - когда не видно, что услышал всё, что слушал.."
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #2


Гуру
*****

Группа: Пользователи
Сообщений: 1 013
Пол: Мужской
Ада: Разработчик
Embarcadero Delphi: Сторонник
Free Pascal: Разработчик

Репутация: -  627  +


Цитата
осложняется тем, что теоретический дабл-запуск будет как бы фор-кликом, то есть мгновенно после первого запуска.
И что? CreateMutex - атомарная операция. Первый из тех, кто вызовет эту функцию получит хэндл мьютекса, второй (пускай даже на следующем такте процессора) - уже поймает ERROR_ALREADY_EXISTS.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #3


mea culpa
*****

Группа: Пользователи
Сообщений: 1 372
Пол: Мужской
Реальное имя: Николай

Репутация: -  24  +


var

f_m: THandle; // mutex
begin
f_m := CreateMutex(nil, true, srMutexName);
if ( (ERROR_ALREADY_EXISTS = GetLastError()) or (ERROR_ACCESS_DENIED = GetLastError()) ) then begin
if (0 <> f_m) then CloseHandle(f_m);
MessageBox('Another instance is already running');
end
else try
Application.Initialize;
...
Application.Run;
finally
CloseHandle(f_m);
end;
end.


Нашёл такой код (это в .dpr), нормальный? Мессадж что-то не вылетает.

Сообщение отредактировано: Unconnected -


--------------------
"Знаешь, стыдно - когда не видно, что услышал всё, что слушал.."
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #4


Гуру
*****

Группа: Пользователи
Сообщений: 1 013
Пол: Мужской
Ада: Разработчик
Embarcadero Delphi: Сторонник
Free Pascal: Разработчик

Репутация: -  627  +


Цитата
Мессадж что-то не вылетает.


program Project1;

{$APPTYPE CONSOLE}

uses
Windows, SysUtils;

const
srMutexName = 'VOLVO_APP_VERY_LONG_ID_STRING'; // Тут на самом деле была еще пара десятков цифр

var
f_m: THandle; // mutex
begin
f_m := CreateMutex(nil, true, srMutexName);
if ( (ERROR_ALREADY_EXISTS = GetLastError()) or (ERROR_ACCESS_DENIED = GetLastError()) ) then begin
if (0 <> f_m) then CloseHandle(f_m);
MessageBox(0, 'Another instance is already running', 'Error', MB_OK);
end
else try
MessageBox(0, 'test', 'test', MB_OK);
//Application.Initialize;
// ...
//Application.Run;
finally
CloseHandle(f_m);
end;
end.

Вылетает сообщение о том, что приложение уже запущено, при Quad-клике... А вот насчет необходимости ERROR_ACCESS_DENIED я бы поспорил... Если у тебя нет доступа к мьютексу - значит, у тебя и на его установку нет доступа, ты можешь и при запуске первой копии нарваться на сообщение, что "уже запущено"...
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #5


Гуру
*****

Группа: Пользователи
Сообщений: 1 013
Пол: Мужской
Ада: Разработчик
Embarcadero Delphi: Сторонник
Free Pascal: Разработчик

Репутация: -  627  +


Кстати, тут у тебя еще есть неприятные мелочи, которые могут сильно осложнить тебе жизнь:

1)
  f_m := CreateMutex(nil, true, srMutexName);
if ( (ERROR_ALREADY_EXISTS = GetLastError()) or (ERROR_ACCESS_DENIED = GetLastError()) ) then begin
Я бы поменял проверки местами: то есть, сначала убедись, что CreateMutex вернула не NULL, и только потом проверяй, а что за ошибка? Если ERROR_ALREADY_EXISTS (ну, и ERROR_ACCESS_DENIED тоже можешь сюда включить) - то все нормально, мьютекс просто уже существует... Кстати, зачем ты его при этом удаляешь - не понятно. Если он есть - то удалить его может только владелец, кто ж тебе даст другому приложению удалить объект ядра? Проблемы что-ли нужны? 64-битные ОСи таких ошибок не прощают smile.gif Это тебе не старая добрая WinXP 32 bit...

2) даже если и даст - мьютекс не удаляется через CloseHandle... Специально была придумана ReleaseMutex... То есть, во втором чтении код принимает вид:

uses
Windows, SysUtils;
const
srMutexName = 'VOLVO_APP_VERY_LONG_ID_STRING'; // Тут на самом деле была еще пара десятков цифр
var
f_m: THandle; // mutex
begin
f_m := CreateMutex(nil, true, srMutexName);

if (f_m <> 0) then
begin
if (GetLastError() = ERROR_ALREADY_EXISTS) or (GetLastError() = ERROR_ACCESS_DENIED) then
begin
MessageBox(0, 'Another instance is already running', 'Error', MB_OK);
end
else
try
MessageBox(0, 'test', 'test', MB_OK);
//Application.Initialize;
// ...
//Application.Run;
finally
ReleaseMutex(f_m);
end;
end
else
MessageBox(0, 'CreateMutex = NULL', 'Error', MB_OK); // А вот это уже странно...
end.

(не надо этих Сишных заморочек с константой слева/именем функции справа. Это в случае Дельфи бесполезно)

Сообщение отредактировано: IUnknown -
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #6


mea culpa
*****

Группа: Пользователи
Сообщений: 1 372
Пол: Мужской
Реальное имя: Николай

Репутация: -  24  +


Угу, спасибо, все сделал по рекомендациям, работает) Правда, не в .dpr, а прямо в коде, там такая специфика.. А что за заморочка с константой\именем? Я сначала думал, что у автора стиль такой написания, да и f_m не константа вовсе..
Блин, меня постоянно пугает, что на одной машине прога работает, а на другой с такой же осью - не будет, или будет как-то непонятно, и непонятно что с исключениями делать зачастую..(


--------------------
"Знаешь, стыдно - когда не видно, что услышал всё, что слушал.."
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #7


Гуру
*****

Группа: Пользователи
Сообщений: 1 013
Пол: Мужской
Ада: Разработчик
Embarcadero Delphi: Сторонник
Free Pascal: Разработчик

Репутация: -  627  +


Цитата
А что за заморочка с константой\именем? Я сначала думал, что у автора стиль такой написания
Этот "стиль" пришел из Си... Ибо если напишешь так:

if (f_m = 0)
{
//
}
(пропустишь второй знак равенства), то присвоишь f_m значение ноль, и этим дело закончится. Программа будет компилироваться (кто ж на предупреждения внимание обращает, да они и отключены у многих, стоит ли после этого удивляться, что "90% кода в интернете - ...", ну, ты помнишь), но работать не будет, разумеется. Поэтому пишут так:

if (0 == f_m)
{
//
}
. если здесь упустить один из знаков равенства - то ты уже нарушаешь синтаксис: присвоить значение числовой константе нельзя, компилятор сразу "встанет на дыбы". В языках с Паскалевским синтаксисом это лишено смысла: компилятор так или иначе поднимет тревогу, если ты вместо "=" где-нибудь напишешь ":=", или наоборот...

Цитата
Блин, меня постоянно пугает, что на одной машине прога работает, а на другой с такой же осью - не будет, или будет как-то непонятно
Еще раз: для того, чтобы программа работала одинаково на разных компьютерах (возможно даже с разными ОСями) - нужно очень немного: всего-навсего программа должна быть написана корректно. Особенно это касается IA64. Если какие-то шероховатости на i386 тебе прощались - то 64 битная архитектура за них жестоко наказывает: Неинициализированный мусор на ia64 может быть смертелен как пример...
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 

 Ответить  Открыть новую тему 
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 





- Текстовая версия 23.12.2024 20:25
500Gb HDD, 6Gb RAM, 2 Cores, 7 EUR в месяц — такие хостинги правда бывают
Связь с администрацией: bu_gen в домене octagram.name