Poprawne zamykanie ChomikBoxa - nie terminate, kill.

0

Witam.

Nie mam problemów z brutalnym zabiciem procesu programu ChomikBox. Ale takie zakończenie jego procesu, powoduje że ChomikBox nie zapisze do pliku INI ostatnio dodanych plików do listy uploadu (jeżeli mamy akurat spauzowane wgrywanie plików).

Próbowałem typowych metod (WM_QUIT, WM_CLOSE, po PID, po HWND) ale ChomikBox na nie nie reaguje.
Za pomocą tego programu http://delphi.about.com/od/windowsshellapi/l/aa080304a.htm można zobaczyć, że ChomikBox uruchamia się w kilku procesach, które są opisane jako QWidget. Próbowałem zakańczać je wszystkie po kolei, ale bez rezultatu.

O QWidget jest trochę na forum, ale to chyba jednak nie to samo co QWidget ChomikBox'a ?

Proszę o pomoc w rozwiązaniu tego problemu, bo widocznie moja głowa już na to za mała :-).

0

spróbuj WM_QUERYENDSESSION i WM_ENDSESSION - na kończenie sesji powinien zareagować

0

Popełniłem błąd przy przekazywaniu uchwytu okna do PostMessage. WM_Quit jednak zadziałało.

Poniżej mój kod, który jest trochę rozbudowany jak na tak prostą operację, ale chodziło mi o zabezpieczenie się przed omyłkowym zamknięciem jakiejś innej aplikacji, która miałaby Class Name i Title takie same jak ChomikBox.

uses
  ...Variants, StdCtrls, ToolWin, ComCtrls, PsAPI...

// Pobranie scieżki pliku po PID
// http://stackoverflow.com/questions/4178443/get-the-full-path-from-a-pid-using-delphi
function ProcessGetPathFromPID(const PID: cardinal): string;
var
  hProcess: THandle;
  path: array[0..MAX_PATH - 1] of char;
begin
  hProcess := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, false, PID);
  if hProcess <> 0 then
    try
      if GetModuleFileNameEx(hProcess, 0, path, MAX_PATH) = 0 then
        RaiseLastOSError;
      result := path;
    finally
      CloseHandle(hProcess)
    end
  else
    RaiseLastOSError;
end;

// Funkcja szuka procesu ChomikBoxa i zamyka go
// http://delphi.about.com/od/windowsshellapi/l/aa080304a.htm
function ProcessEnum(hHwnd: HWND; lParam : integer): boolean; stdcall;
var
  pPid, pPid2 : DWORD;
  title, className : string;
begin
  if(hHwnd=NULL) then
    begin
    result := false;
    end
  else
    begin
    GetWindowThreadProcessId(hHwnd,pPid);
    SetLength(className, 255);
    SetLength(className, GetClassName(hHwnd, PChar(className), Length(className)));
    SetLength(title, 255);
    SetLength(title, GetWindowText(hHwnd, PChar(title), Length(title)));

    // Warunek zamykający program ChomikBox. Zamykanie po title='chomikbox' czasami
    // powoduje pojawienie się komunikatu o nieoczekiwanym zamknięciu aplikacji ChomikBox
    If (className = 'QWidget') AND (title = 'Dodawanie plików') Then
      begin

      // Dla pewności sprawdzamy po scieżce pliku, czy to rzeczywiście jest ChomikBox.
      If (ProcessGetPathFromPID(pPid) = 'C:\Program Files (x86)\ChomikBox\chomikbox.exe') 
		OR (ProcessGetPathFromPID(pPid) = 'C:\Program Files\ChomikBox\chomikbox.exe') Then
        begin
        //showmessage('Class Name = ' + className + '; Title = ' + title + '; HWND = ' + IntToStr(hHwnd) + '; Pid = ' + IntToStr(pPid));
        If NOT PostMessage(hHwnd, WM_Quit, 0, 0) Then 
		MessageBox(0, PChar('Wystąpił problem przy zamykaniu ChomikBoxa. Zamknij program ręcznie i naciśnij OK.'), 
		PChar(naglowek), MB_ICONWARNING + MB_OK);
        end;
      end;

    result := true;
    end;
end;

procedure ProcessGet;
var
  lp : integer;
begin
  lp := 0;
  if EnumWindows(@ProcessEnum, lp) = false then ShowMessage('Błąd: Nie można uzyskać uchwytu okna.');
end; 

Jeżeli macie jakieś uwagi lub lepszy pomysł na kod, to pisać śmiało.

1 użytkowników online, w tym zalogowanych: 0, gości: 1