Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: WinAPI и системное программирование > Отследить завершение приложе или события WM_CLOSE


Автор: _snikers_ 29.5.2006, 21:52
Здрасте! нужно отследить завершение приложения - если его закрыли, нужно выполнить некоторые действия... 
Пользуюсь функцией в таймере:
Код

function FindProcess(ExeName:string):string;
var
  PIDArray   : array [0..1023] of DWORD;
  cb         : DWORD;
  I          : Integer;
  ProcCount  : Integer;
  hMod       : HMODULE;
  hProcess   : THandle;
  ModuleName : array [0..1024] of Char;
begin
  Result := '';
  EnumProcesses(@PIDArray, SizeOf(PIDArray), cb);
  ProcCount := cb div SizeOf(DWORD);
  for I := 0 to ProcCount - 1 do
  begin
    hProcess := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ,False,PIDArray[I]);
    if (hProcess <> 0) then
       begin
          EnumProcessModules(hProcess, @hMod, SizeOf(hMod), cb);
          GetModuleFilenameEx(hProcess, hMod, ModuleName, SizeOf(ModuleName));
          if UpperCase(ExtractFileName(ModuleName))=UpperCase(ExeName) then Result:=ModuleName;
       end;
    CloseHandle(hProcess);
  end
end;

НО НЕ ПОДХОДИТ ПОТОМУ ЧТО

во время работы таймера постоянно моргает курсор мыши.. 
По-этому может возможно как-то сделать проверку по другому, или может быть перехватывать событие завершения приложения WM_DESTROY или WM_CLOSE... Пробовал установить хук на это событие но ничего не получается...
Код

function HookProc(Code: integer; WParam: word; LParam: Longint): Longint; stdcall; 
var 
 msg: PEVENTMSG; 
begin 
 if Code >= 0 then begin 
   result := 0; 
   msg := Pointer(LParam); 
   with Form1 do
     case msg.message of 
       WM_DESTROY: {или WM_CLOSE}
          BEGIN
          ...................
          END;
     end; 
 end else 
   result := CallNextHookEx(HookHandle, code, WParam, LParam); 
end;


 ГОСПОДА ПОМОГИТЕ.........
 

Автор: vv3 30.5.2006, 12:07
А просто отрабатывать необходимые по закрытии действия в событии onClose или onCloseQuery главной формы приложения недостаточно? Зачем такие сложности? 

Автор: Nickel 30.5.2006, 12:09
Если мы сами запускаем приложение, то легче всего сделать так:
Код

procedure ExecAndWait;
var
  StartInfo  : TStartupInfo;
  ProcInfo   : TProcessInformation;
  CreateOK   : Boolean;
begin
  FillChar(StartInfo,SizeOf(TStartupInfo),#0);
  FillChar(ProcInfo,SizeOf(TProcessInformation),#0);
  StartInfo.cb := SizeOf(TStartupInfo);
  CreateOK := CreateProcess('наше приложение',nil, nil, nil,False,
              CREATE_NEW_PROCESS_GROUP+NORMAL_PRIORITY_CLASS,
              nil, nil, StartInfo, ProcInfo);
  if CreateOK then begin
    WaitForSingleObject(ProcInfo.hProcess, INFINITE);
    MessageBox(0,'Процесс завершился','',0);
    end;
end;

...

var a:cardinal;
begin
CreateThread(nil,0,@ExecAndWait,nil,0,a);
end;

Если не сами, то:
Код


uses TlHelp32;

function GetProcessId(pName: PChar): dword;
var
 Snap: dword;
 Process: TPROCESSENTRY32;
begin
  Result := 0;
  Snap := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  if Snap <> INVALID_HANDLE_VALUE then
     begin
      Process.dwSize := SizeOf(TPROCESSENTRY32);
      if Process32First(Snap, Process) then
         repeat
          if lstrcmpi(Process.szExeFile, pName) = 0 then
             begin
              Result := Process.th32ProcessID;
              CloseHandle(Snap);
              Exit;
             end;
         until not Process32Next(Snap, Process);
      Result := 0;
      CloseHandle(Snap);
     end;
end;

procedure OpenAndWait;
var h:THandle;
begin
  h := OpenProcess(PROCESS_ALL_ACCESS, False, GetProcessId('наше прилодение'));
  if h<>0 then
    begin
    WaitForSingleObject(h, INFINITE);
    MessageBox(0,'Процесс завершился','',0);
    end
  else MessageBox(0,'Возможно процесс не запущен','',0);
end;

...

var a:cardinal;
begin
CreateThread(nil,0,@OpenAndWait,nil,0,a);
end;

Чтобы наше приложение (если оно оконное) не "зависло", убираем запуск и ожидание в отдельный поток. Да ещё я не понял, что не так с таймером? 

Автор: _snikers_ 30.5.2006, 23:22
Что значит: убираем запуск и ожидание в отдельный поток

и приложение не мое, а чужое отслеживаю....  

Автор: Nickel 31.5.2006, 09:42
Это значит, что если у тебя приложение оконное, и ты сделаешь так:
Код

procedure TForm1.Button1Click(Sender: TObject);
begin
OpenAndWait;
end;

То твоя форма благополучно зависнет, пока не завершится приложение, потому что
Код

WaitForSingleObject(h, INFINITE);

останавливает поток в котором идёт обработка сообщений формы. А если мы сделаем так:
Код

procedure TForm1.Button1Click(Sender: TObject);
begin
CreateThread(nil,0,@OpenAndWait,nil,0,a);
end;

Т.е. создадим новый поток, в котором и будет происходить ожидание завершения работы некоторгоо приложения. 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)