На главную
Подписка
Новости


Рейтинг@Mail.ru











Главная / DELPHI / Часто задаваемые вопросы и ответы на них / Win Api / Как определить работает ли уже данное приложение или это первая его копия? Сделать домашней страницей Добавить в избранное Написать писмо

Как определить работает ли уже данное приложение или это первая его копия?


Для Delphi 1. Каждый экземпляр программы имеет ссылку на свою предыдущую копию - hPrevInst: hWnd. Ее можно проверить перед созданием приложения и при необходимости отреагировать соответствующим образом. Если запущена только одна копия, то эта ссылка равна нулю.
Пример:


procedure TForm1.FormCreate(Sender: TObject);
begin
 {Проверяем есть ли указатель на предыдущую копию приложения}
 IF hPrevInst <> 0 THEN BEGIN
   {Если есть, то выдаем сообщение и выходим}
   MessageDlg('Программа уже запущена!', mtError, [mbOk], 0);
   Halt;
 END;
 {Иначе - ничего не делаем (не мешаем созданию формы)}
end;


P.S. Для выхода необходимо использовать Halt, а не Close, как хотелось бы, так как форма еще не создана и закрывать нечего.
Есть и другой способ - по списку загруженных приложений




procedure TForm1.FormCreate(Sender: TObject);
VAR
Wnd : hWnd;
buff : ARRAY[0.. 127] OF Char;
Begin
Wnd := GetWindow(Handle, gw_HWndFirst);
WHILE Wnd <> 0 DO BEGIN
 IF (Wnd <> Application.Handle) AND (GetWindow(Wnd, gw_Owner) = 0)
 THEN BEGIN
  GetWindowText (Wnd, buff, sizeof (buff ));
  IF StrPas (buff) = Application.Title THEN
  BEGIN
   MessageDlg('Приложение уже загружено', mtWarning, [mbOk], 0);
   Halt;
  END;
 END;
 Wnd := GetWindow (Wnd, gw_hWndNext);
END;
End;


Еще один интересный способ для Win32. Дело в том, что можно в памяти создавать временные файлы. При перезагрузке они теряются, а так существуют. Кстати, этот метод можно использовать и для обмена информацией между вашими приложениями.

Пример:


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 then
 begin
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
 end;
 CloseHandle(MemHnd);
end.


Часто при работе у пользователя может быть открыто 5-20 окон и сообщение о том, что программа уже запущено приводит к тому, что он вынужден полчаса искать ранее запущенную копию. Выход из положения - найдя копию программы активировать ее, для чего в последнем примере перед HALT необходимо добавить строку :
SetForegroundWindow(Wnd);
Например так:


program Project0;
uses
 Windows,  // !!!
 Forms,
 Unit0 in 'Unit0.pas' {Form1};

var
 Handle1 : LongInt;
 Handle2 : LongInt;

{$R *.RES}

begin
 Application.Initialize;
 Handle1 := FindWindow('TForm1',nil);
 if handle1 = 0 then
   begin
     Application.CreateForm(TForm1, Form1);
     Application.Run;
   end
 else
   begin
     Handle2 := GetWindow(Handle1,GW_OWNER);
      //Чтоб заметили :)
     ShowWindow(Handle2,SW_HIDE); ShowWindow(Handle2,SW_RESTORE);
     SetForegroundWindow(Handle1); // Активизируем
   end;
end.




Комментарий от "Vladimir" (damageinc@e-mail.ru)
Лучше  всего  использовать  именованные  мутексы.  Главное,  придумать
уникальное  имя  для  этого мутекса. Вот пример вполне работоспособной
программы:

program My1;
uses
 Forms, Windows, Dialogs, SysUtils,

var
g_hAppMutex: THandle;
Wnd : hWnd;
buff: array [0..127] of Char;
s:string;
i:integer;

function OneInstance: boolean;

begin
g_hAppMutex:=CreateMutex(nil,false,PChar('AnUniqueString'+IntToStr(GetDesktopWindow)));
Result:=(WaitForSingleObject(g_hAppMutex,0)<>WAIT_TIMEOUT);
end;

begin
 Application.Initialize;
 Application.Title := 'SmartDecoder';
 Application.HelpFile := 'Decoder.hlp';
 //создаём инстанс, если его ещё нету на текущем рабочем столе
 g_hAppMutex:=0;
 if OneInstance then
    begin
     Application.CreateForm(TMainFrm, MainFrm);
     Application.Run;
    end;
 if LongBool(g_hAppMutex) then //если уже есть
    begin
     ReleaseMutex(g_hAppMutex);
     CloseHandle(g_hAppMutex);
     if  ParamStr(1)=''  then  ShowMessage('Программа уже запущена на
     этом  рабочем столе. Нажмите кнопку "OK" для передачи управления
     уже запущенной копии программы.');
     Wnd:=GetWindow(GetTopWindow(0),gw_HWndFirst);
     while Wnd<>0 do
      begin
      //Если не собственное и не дочернее окно
       if (Wnd<>Application.Handle)and(GetWindow(Wnd,gw_Owner)=0) then
          begin
           GetWindowText(Wnd,buff,sizeof(buff));
           if Copy(StrPas(buff),1,12)='SmartDecoder' then
              if Wnd=GetWindowLong(Wnd,GWL_USERDATA) then
                 begin
                  ShowWindow(Wnd,SW_ShowNormal);
                  SetForegroundWindow(Wnd);
                  i:=1;
                  while ParamStr(i)<>'' do
                   begin
                    s:=ParamStr(i);
                    PostMessage(Wnd,WM_OPEN_FILE,GlobalAddAtom(PChar(s)),0);
                    inc(i);
                   end;
                  Application.Terminate;
                  Exit;
                 end;
          end;
       Wnd:=GetWindow(Wnd,gw_hWndNext);
      end;
    end;
end.

Если  программа  уже  запущена, управление будет передано существующей
копии.

Copyright ©   "Мастера DELPHI"   E-mail:   delphi@mastak.com  http://www.delphimaster.ru
Источник получения информации: http://www.delphimaster.ru
Hosted by uCoz