Sources
Delphi Russian Knowledge Base
DRKB - это самая большая и удобная в использовании база знаний по Дельфи в рунете, составленная Виталием Невзоровым

Как сделать, чтобы запускалась только одна копия приложения?

01.01.2007
var AtomText: array[0..31] of Char; 
 
 
procedure LookForPreviousInstance; 
var 
  PreviousInstanceWindow : hWnd; 
  AppName : array[0..30] of char; 
  FoundAtom : TAtom; 
begin 
  // помещаем имя приложения в AtomText 
  StrFmt(AtomText, 'OnlyOne%s', [Copy(Application.Title,1,20)]); 
  // Проверяем, не создано ли уже атома с таким именем приложения
  FoundAtom := GlobalFindAtom(AtomText); 
  if FoundAtom <> 0 then      // эта копия приложения уже запущена
  begin 
    StrFmt(AppName,'%s', [Application.Title]); 
    // изменяем текущий заголовок, чтобы FindWindow не видела его
    Application.ShowMainForm := false; 
    Application.Title := 'destroy me'; 
    // ищем предыдущую копию приложения
    PreviousInstanceWindow := FindWindow(nil,AppName); 
    // Передаём фокус на предыдущую копию приложения
    // завершаем текущую копию
    Application.Terminate; 
 
    if PreviousInstanceWindow <> 0 then 
      if IsIconic(PreviousInstanceWindow) then 
           ShowWindow(PreviousInstanceWindow,SW_RESTORE) 
      else SetForegroundWindow(PreviousInstanceWindow); 
  end; 
  // создаём глобальный атом, чтобы предотвратить запуск другой копии приложения
  FoundAtom := GlobalAddAtom(AtomText); 
end; 
 
 
 
 
constructor TForm.Create(AOwner: TComponent); 
begin 
  inherited; 
 
  LookForPreviousInstance; 
  ... 
end; 
 
 
destructor TForm.Destroy; 
var 
  FoundAtom : TAtom; 
  ValueReturned : word; 
begin 
  // не забудьте удалить глобальный атом
  FoundAtom := GlobalFindAtom(AtomText); 
  if FoundAtom <> 0 then ValueReturned := GlobalDeleteAtom(FoundAtom); 
 
  inherited Destroy; 
end;

Взято из https://forum.sources.ru


В блоке begin..end модуля .dpr:

begin
  if HPrevInst <> 0 then
    begin
      ActivatePreviousInstance;
      Halt;
    end;
end;

Реализация:

unit PrevInst;
 
interface
 
uses
 
  WinProcs,
  WinTypes,
  SysUtils;
 
type
  PHWnd = ^HWnd;
 
function EnumApps(Wnd: HWnd; TargetWindow: PHWnd): bool; export;
 
procedure ActivatePreviousInstance;
 
implementation
 
function EnumApps(Wnd: HWnd; TargetWindow: PHWnd): bool;
var
 
  ClassName: array[0..30] of char;
begin
 
  Result := true;
  if GetWindowWord(Wnd, GWW_HINSTANCE) = HPrevInst then
    begin
      GetClassName(Wnd, ClassName, 30);
      if STRIComp(ClassName, 'TApplication') = 0 then
        begin
          TargetWindow^ := Wnd;
          Result := false;
        end;
    end;
end;
 
procedure ActivatePreviousInstance;
var
 
  PrevInstWnd: HWnd;
begin
 
  PrevInstWnd := 0;
  EnumWindows(@EnumApps, LongInt(@PrevInstWnd));
  if PrevInstWnd <> 0 then
    if IsIconic(PrevInstWnd) then
      ShowWindow(PrevInstWnd, SW_Restore)
    else
      BringWindowToTop(PrevInstWnd);
end;
 
end.

Взято из Советов по Delphi от Валентина Озерова

Сборник Kuliba