Как определить работает ли уже данное приложение или это его первая копия
Сидит программист в столовой, обедает, суп ест. В очках такой, задумчивый, программу думает. Народу никого, все уже поели, ушли. Подходит к нему официантка и заигрывает:
- Если Вы хотите хорошо провести время, то меня зовут Маша!
Программист медленно возвращается на землю и смотрит на официантку отрешенным взглядом и на автопилоте спрашивает:
- А если не хочу, то как Вас зовут?!
Каждый экземпляр программы имеет ссылку на свою предыдущую копию - hPrevInst: hWnd. Ее можно проверить перед созданием приложения и при необходимости отреагировать соответствующим образом. Если запущена только одна копия, то эта ссылка равна нулю. Только для Delphi 1. Пример использования hPrevInst:
procedure TForm1.FormCreate(Sender: TObject);
begin// Проверяем есть ли указатель на предыдущую копию приложенияif hPrevInst <> 0 thenbegin// Если есть, то выдаем сообщение и выходим
MessageDlg('Программа уже запущена!', mtError, [mbOk], 0);
Application.Terminate;
end;
// Иначе - ничего не делаем (не мешаем созданию формы)end;
Другой способ - по списку загруженных приложений
procedure TForm1.FormCreate(Sender: TObject);
var
Wnd : hWnd;
buff : array[0.. 127] of Char;
begin//Получили указатель на первое окно
Wnd := GetWindow(Handle, gw_HWndFirst);
// Поискwhile Wnd <> 0 dobegin// Это окно предыдущей копии ?if (Wnd <> Application.Handle) and (GetWindow(Wnd, gw_Owner) = 0) thenbegin
GetWindowText (Wnd, buff, sizeof (buff ));
if StrPas (buff) = Application.Title thenbegin
MessageDlg('Приложение уже загружено', mtWarning, [mbOk], 0);
Halt;
end;
end;
Wnd := GetWindow (Wnd, gw_hWndNext);
end;
end;
Данный пример не всегда применим - часто заголовок приложения меняется при каждом старте, поэтому рассмотрим более надежный способ - через FileMapping
Дело в том, что можно в памяти создавать временные файлы. При перезагрузке они теряются, а так существуют. Кстати, этот метод можно использовать и для обмена информацией между вашими приложениями. Пример с использованием FileMapping:
program Project1;
uses
Windows, // Обязательно
Forms,
Unit1 in 'Unit1.pas' {Form1};
{$R *.RES}const
MemFileSize = 1024;
MemFileName = 'one_inst_demo_memfile';
var
MemHnd : HWND;
begin// Попытаемся создать файл в памяти
MemHnd := CreateFileMapping(HWND($FFFFFFFF),
nil, PAGE_READWRITE, 0, MemFileSize, MemFileName);
// Если файл не существовал запускаем приложениеif GetLastError<>ERROR_ALREADY_EXISTS thenbegin
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end;
CloseHandle(MemHnd);
end.
Часто при работе у пользователя может быть открыто 5-20 окон и сообщение о том, что программа уже запущено приводит к тому, что он вынужден полчаса искать ранее запущенную копию. Выход из положения - найдя копию программы активировать ее, для чего в последнем примере перед HALT необходимо добавить строку : SetForegroundWindow(Wnd);
Блокировка запуска второй копии при помощи Mutex На мой взгляд, это один из самых простых и надежных способов.
procedure TForm1.FormCreate(Sender: TObject);
var
hMutex : THandle;
begin
hMutex := CreateMutex(0, true , 'My application name');
if GetLastError = ERROR_ALREADY_EXISTS thenbegin
CloseHandle(hMutex);
Application.Terminate;
end;
end;
В данном примере при старте приложения создается мьютекс с некоторым уникальным именем (у каждого приложения оно должно бять свое !!). Если хоть одна копия приложения запущена, то в системе уже будет мьютекс с таким именем и возникнет ошибка ERROR_ALREADY_EXISTS. В противном случае мьютекс создается и существует, пока работает данная копия приложения Задать вопрос
Как определить работает ли уже данное приложение или это его первая копия: можно использовать хандл предыдущей копии (hPrevInst), список загруженных приложений, временные файлы (FileMapping), именованный семафор (mutex).
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS