Delphi: Запрет на запуск второй копии программы

Нашел в интернете много способов реализации на запрет запуска второго экземпляра приложения. Выбрал самый на мой взгляд минималистский. Я думаю, может многим понадобится — вообще применяется это достаточно часто.

Итак, нужно открыть исходный код главного файла проекта (меню Project — View Source). В секцию uses добавляем библиотеки Windows и Dialogs:

uses
...
Windows,
Dialogs,
...

В секцию Var (переменные, если нет такой — создаем):

var
H: THandle;

Теперь, непосредственно перед строкой:

Application.Initialize;

Добавим нашу проверку, не запущен ли уже другой экземпляр программы:

H := CreateMutex(nil, True, 'уникальная фраза');
if GetLastError = ERROR_ALREADY_EXISTS then
begin
showmessage('Программа уже работает!');
Exit;
end;

‘уникальная фраза’ — это что-то например «и64ерм9со46к79826о» — в общем то, что наверняка будет использовать только Ваша программа. Можно также использовать,например, название программы.

21 мысль о “Delphi: Запрет на запуск второй копии программы”

    1. Да, забыл объявить переменную, Вы в этом правы. Но я использовал тип THandle, насчет Cardinal — не проверял. Статью поправил, спасибо!

  1. Привет! (Сразу к делу) Я читал Ваши статьи и узнал, что Вы программируете свои приложения в среде разработки Delphi. Вы не подскажете (исходный код) как открывать все формы на одном окне? (Например: открывание Form2 в Form1)… Заранее благодарен! И спасибо большое за программу TurboSite!

    1. Привет. Не совсем понял что имеется ввиду. Если Ваш нужно в одном окне показывать разное содержимое, то можно использовать PageControl со скрытыми вкладками, которые Вы сами програмно будете переключать.

  2. Добавляю
    H := CreateMutex(nil, True, PChar(Application.Title));
    if GetLastError = ERROR_ALREADY_EXISTS then
    begin
    showmessage(‘Программа уже работает!’);
    SetForegroundWindow(FindWindow(nil, PChar(Application.Title))); // помещаем окно с уже запущенной программой на передний план
    Exit;
    end;
    перед строкой
    Application.Initialize;
    и кнопка Run перестает быть активной, как быть?

    1. O_o
      удивило
      если даже в коде ошибка — кнопка из-за этого не может стать не активной. Проверьте внимательно, в этом ли причина.

    2. Через run итак только одна копия запускается) заходи папку с проектом и открой exe файл два раза

  3. Та же фигня, что у baur, лечится заменой Application.Title на что-нибудь, не обращающееся к Application (я просто подставил строку).

    1. Тоже вариант. Application.Title я выбрал в качестве идентификатора программы. Надежнее всего будет вместо него использовать строку со случайным набором символов, который с наименьшей вероятностью будет использовать другое приложение.

    2. Если надо как-то привязатья к названию программы (файла), то надо использовать PChar(ExtractFileName(ParamStr(0)))
      Т.к. при запуске файла у него по умолчанию в качестве нулевого параметра передается имя файла

  4. плохой способ
    Application.Title не может быть использован пока не проинициализируется,
    лучше использовать FindWindow

  5. я сделал вот так

    var H: THandle;

    H := FindWindow(‘TMainForm’, ‘MainForm’);
    if H 0 then
    begin
    showmessage(‘Программа уже работает!’);
    Exit;
    end;

    Application.Initialize;

    где «MainForm» ваше главное окно, но в этом методе есть заковыка наименование вашего окна должно быть уникальным для всех используемых приложений в Windows

  6. Отлично. Понадобилось. У меня уже не раз эта проблема возникала и я ее никак не мог решить. Всегда старался ее обойти, но это не очень приятно.

  7. Если это в событие CreateForm поместить, то messagebox появляется. но почему-то не выходит на Exit, а продолжает работу.

    1. Все правильно, происходит Exit из процедуры OnCreateForm, а не из программы.
      Чтобы надежно завершить — надо вместо exit набрать halt (жесткое завершение) или Close. Но с процедурой halt надо аккуратно, потому что она убивает приложение, но могут быть потеряны куски памяти.
      Ну или как-то по другому, мягко завершить программу

  8. И кстати, не знаю, важно это или нет, но код надо доработать, а именно, перед Exit надо бы добавить CloseHandle(H), а в самом конце (после Application.Run) надо добавить строчку ReleaseMutex(H).

    Почему это важно: если Вы не просто закрываете вторую программу, а ждете завершения первой, то вторая программа не запустится даже после закрытия первой.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *