Czy jest możliwe zamknięcie aplikacji jeśli znamy jej PID ewentualnie uchwyt?
Zaznaczam, że nie chodzi mi tutaj o zabicie procesu ale o zamknięcie, tak aby aplikacja mogła chociażby zapisać swoje ustawienia.
Na podstawie uchwytu można bez problemów zamknąć. Poniżej mój przykład dla emulatora WinUAE:
var
WinUAE_HWND : HWND;
begin
WinUAE_HWND := FindWindow('PCsuxRox', nil);
SendMessage(WinUAE_HWND, WM_SYSCOMMAND, SC_CLOSE, 0);
end;
// PID to nie uchwyt okna! - Ł
uses
TlHelp32, PSApi, ShellApi, ShlObj;
function ZamknijProcesPID(PID: Cardinal): Boolean;
var
PHandle, FHandle: THandle;
Process: TProcessEntry32;
Next: Boolean;
begin
Result := False;
FHandle := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
Process.dwSize := Sizeof(Process);
Next := Process32First(FHandle, Process);
while Next do
begin
PHandle := OpenProcess(PROCESS_TERMINATE, False, PID);
if TerminateProcess(PHandle, 0) then Result := True;
Next := Process32Next(FHandle, Process);
end;
CloseHandle(FHandle);
end;
gosc napisał(a)
ewentualnie uchwyt?
LF: napisał że uchwyt też może być, wiem że to nie to samo co pid, ale Opi już podał mu chyba ok sposób.
Nie chodziło mi o zamykanie na podstawie nazwy okna. Powiedzmy, że mamy uruchomione kilka kopii tego same go procesu. Ja chce zamknąć konkretny proces znając jego PID. Nie mogę wykonać terminate, gdyż to nie pozwoli na prawidłowe zakończenie działania procesu i zapisanie wyniku.
Gosc napisał(a)
Nie chodziło mi o zamykanie na podstawie nazwy okna. Powiedzmy, że mamy uruchomione kilka kopii tego same go procesu. Ja chce zamknąć konkretny proces znając jego PID. Nie mogę wykonać terminate, gdyż to nie pozwoli na prawidłowe zakończenie działania procesu i zapisanie wyniku.
Jeśli to jest Twoja aplikacja to zaimplementuj odbieranie komunikatu o wymuszeniu zamknięcia.
Jeśli to obca aplikacja to chyba też można wysłać odpowiedni komunikat do programu.
var
MyHandle: THandle;
begin
MyHandle:=FindWindow(nil, 'Delphi Help');
SendMessage(MyHandle, WM_CLOSE, 0, 0);
end;
Ta opcja raczej odpada.
Napisałem usługę sysemową która cyklicznie uruchamia pewne procesy przez OpenProcess. Wtedy uzyskuje bez problemu PID oraz uchwyt procesu. Potrzebny jest mi natomiast uchwyt okna aby wysłać komunikat zamknięcia. W momencie zatrzymania usługi muszę wysłać do uruchomionej aplikacji komunikat zamknięcia. Napisałem taką procedurę:
function TForm1.GetHandleFromPID(PID: Cardinal): THandle;
function EnumWindowsProc(wHandle: HWND): Boolean; StdCall;
var
ePID : DWORD;
begin
Result := True;
GetWindowThreadProcessId(WHandle, @ePID);
if ePID = PID then GetHandleFromPID := wHandle;
end;
begin
EnumWindows(@EnumWindowsProc,0);
end;
Procedura sprawdza wszystkie dostępne uchwyty. Na ich podstawie mogę pobrać pid, jednak przy próbie porównania ePID = PID wywala AccesViolation.