Программистские проекты бывают трех основных типов:
1. Неудачный проект первого рода - когда не удалось заключить контракт.
2. Неудачный проект второго рода - когда удалось заключить контракт.
3. Удачный проект, или проект с предоплатой.
Предоставленное разработчиками Delphi 2 Пачекой (Pacheco) и Тайхайрой (Teixeira)
и значительно переработанное.
unit multinst;
{
Применение:
Необходимый код в исходном проекте
if InitInstance then
begin
Application.Initialize;
Application.CreateForm(TFrmSelProject, FrmSelProject);
Application.Run;
end;
Это все понятно (я надеюсь)
}interfaceuses Forms, Windows, Dialogs, SysUtils;
const
MI_NO_ERROR = 0;
MI_FAIL_SUBCLASS = 1;
MI_FAIL_CREATE_MUTEX = 2;
{ Проверка правильности запуска приложения с помощью описанных ниже функций. }{ Количество флагов ошибок MI_* может быть более одного. }function GetMIError: Integer;
function InitInstance: Boolean;
implementationconst
UniqueAppStr: PChar; {Различное для каждого приложения}var
MessageId: Integer;
WProc: TFNWndProc = nil;
MutHandle: THandle = 0;
MIError: Integer = 0;
function GetMIError: Integer;
begin
Result := MIError;
end;
function NewWndProc(Handle: HWND; Msg: Integer; wParam,
lParam: Longint): Longint; stdcall;
begin{ Если это - сообщение о регистрации... }if Msg = MessageID thenbegin{ если основная форма минимизирована, восстанавливаем ее }{ передаем фокус приложению }if IsIconic(Application.Handle) thenbegin
Application.MainForm.WindowState := wsNormal;
ShowWindow(Application.Mainform.Handle, sw_restore);
end;
SetForegroundWindow(Application.MainForm.Handle);
end{ В противном случае посылаем сообщение предыдущему окну }else
Result := CallWindowProc(WProc, Handle, Msg, wParam, lParam);
end;
procedure SubClassApplication;
begin{ Обязательная процедура. Необходима, чтобы обработчик }{ Application.OnMessage был доступен для использования. }
WProc := TFNWndProc(SetWindowLong(Application.Handle, GWL_WNDPROC,
Longint(@NewWndProc)));
{ Если происходит ошибка, устанавливаем подходящий флаг }if WProc = nilthen
MIError := MIError or MI_FAIL_SUBCLASS;
end;
procedure DoFirstInstance;
begin
SubClassApplication;
MutHandle := CreateMutex(nil, False, UniqueAppStr);
if MutHandle = 0 then
MIError := MIError or MI_FAIL_CREATE_MUTEX;
end;
procedure BroadcastFocusMessage;
{ Процедура вызывается, если уже имеется запущенная копия Вашей программы. }var
BSMRecipients: DWORD;
begin{ Не показываем основную форму }
Application.ShowMainForm := False;
{ Посылаем другому приложению сообщение и информируем о необходимости }{ перевести фокус на себя }
BSMRecipients := BSM_APPLICATIONS;
BroadCastSystemMessage(BSF_IGNORECURRENTTASK or BSF_POSTMESSAGE,
@BSMRecipients, MessageID, 0, 0);
end;
function InitInstance: Boolean;
begin
MutHandle := OpenMutex(MUTEX_ALL_ACCESS, False, UniqueAppStr);
if MutHandle = 0 thenbegin{ Объект Mutex еще не создан, означая, что еще не создано }{ другое приложение. }
ShowWindow(Application.Handle, SW_ShowNormal);
Application.ShowMainForm := True;
DoFirstInstance;
result := True;
endelsebegin
BroadcastFocusMessage;
result := False;
end;
end;
initializationbegin
UniqueAppStr := Application.Exexname;
MessageID := RegisterWindowMessage(UniqueAppStr);
ShowWindow(Application.Handle, SW_Hide);
Application.ShowMainForm := FALSE;
end;
finalizationbeginif WProc <> nilthen{ Приводим приложение в исходное состояние }
SetWindowLong(Application.Handle, GWL_WNDPROC, LongInt(WProc));
end;
end.
Программный код, который вы предоставили, - это программу на Delphi, которая предназначена для предотвращения запуска нескольких экземпляров приложения одновременно. Она использует механизмы Windows API Mutex и WindowMessage для достижения этого.
Вот подробное описание того, что код делает:
Функция InitInstance инициализирует экземпляр приложения. Если уже запущен другой экземпляр того же приложения, она возвращает False. В противном случае, она создает мьютекс с именем, соответствующим имени исполняемого файла приложения.
Процедура DoFirstInstance вызывается, если это первый запущенный экземпляр приложения. Она подклассирует процедуру окна приложения для захвата сообщений и настраивает фильтр сообщений для обнаружения запуска другого экземпляра того же приложения.
Если обнаружен другой экземпляр того же приложения, процедура BroadcastFocusMessage отправляет сообщение этому экземпляру, запросив его сфокусироваться (то есть, принести главное окно в передний план).
Функция NewWndProc обрабатывает сообщения, отправленные процедурой окна приложения. Если она получает сообщение, указывающее на запуск другого экземпляра того же приложения, она восстанавливает главное окно и устанавливает фокус.
Чтобы предотвратить запуск нескольких экземпляров, вы можете использовать следующий подход:
Проверьте, существует ли мьютекс, созданный в DoFirstInstance, перед его созданием.
Если мьютекс существует, это означает, что уже запущен другой экземпляр того же приложения, поэтому возвращает False из InitInstance.
Если мьютекс не существует, создайте его и продолжите процесс инициализации.
Вот пример, как можно модифицировать код для достижения этого:
functionInitInstance:Boolean;beginifOpenMutex(MUTEX_ALL_ACCESS,False,UniqueAppStr)<>0thenExit(False);// Остальная часть кода инициализации...end;
Таким образом, если уже запущен другой экземпляр того же приложения, InitInstance вернет False, предотвратив запуск текущего экземпляра.
Обратите внимание, что этот подход предполагает, что мьютекс, созданный в DoFirstInstance, не будет удален до тех пор, пока приложение не будет закрыто. Вы можете достичь этого, переместив вызов CloseHandle(MutHandle) в раздел Finalization единицы, после того как переменная WProc будет установлена в nil.
Как не допустить запуска второй копии программы: код на Delphi для предотвращения одновременного запуска приложения.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.