2008-11-06 2 views
1

저는 여러 프로그램을 실행하는 Delphi로 작성된 Windows 서비스를 보유하고 있습니다.Delphi - 서비스에서 생성 된 프로세스를 정상적으로 종료합니다. (tprocess/createProcess 사용)

On 서비스를 중지 할 때도이 프로그램을 닫고 싶습니다. 서비스가 원래 작성되었을 때이 작업은 정상적으로 수행되었지만 tProcess 구성 요소를 지금 업데이트 한 것 같습니다. - 하위 프로그램이 닫히지 않았습니다.

in tProcess - 여기에 새 프로세스를 시작하는 코드가 있습니다.

if CreateProcess(nil , PChar(FProcess.Command) , nil , nil , False , 
    NORMAL_PRIORITY_CLASS , nil , Directory , 
    StartupInfo , ProcessInfo) then 
    begin 
     if FProcess.Wait then 
     begin 
      WaitForSingleObject(ProcessInfo.hProcess , Infinite); 
      GetExitCodeProcess(ProcessInfo.hProcess , ExitCode); 
      if Assigned(FProcess.FOnFinished) then 
      FProcess.FOnFinished(FProcess , ExitCode); 
     end; 
     CloseHandle(ProcessInfo.hProcess); 
     CloseHandle(ProcessInfo.hThread); 
    end; 

여기에서 호출되는 실행 파일은 Windows GUI 프로그램 (맨 위에 닫기 버튼이 있음)입니다.

서비스를 중지하면 createProcess 프로 시저를 통해 시작한 프로그램도 중지 (죽이지 않음)하고 싶습니다.

어떻게 하시겠습니까?

+0

시작은 문제가되지 않습니다 :

uses Windows; interface function MyTerminateAppEnum(hHwnd:HWND; dwData:LPARAM):Boolean; stdcall; implementation function MyTerminateAppEnum(hHwnd:HWND; dwData:LPARAM):Boolean; var vID:DWORD; begin GetWindowThreadProcessID(hHwnd, @vID); if vID = dwData then begin PostMessage(hHwnd, WM_CLOSE, 0, 0); //tell window to close gracefully Result := False; //can stop enumerating end else begin Result := TRUE; //keep enumerating until you find your id end; end; 

그런 다음 당신이 실행 된 응용 프로그램을 종료 할 때 코드에서이를 활용하는 것이 좋습니다 : 여기에 몇 가지 예제 코드는? 그렇다면 TProcess가 프로그램을 닫으려면 어떻게해야합니까? –

답변

1

실행중인 ProcessId와 일치하는 열린 창을 열거하고 해당 창을 닫을 것을 말합니다. 오른쪽

Procedure TerminateMe(YourSavedProcessInfo:TProcessInformation); 
var 
    vExitCode:UINT; 
begin 
    GetExitCodeProcess(YourSavedProcessInfo.hProcess, vExitCode); 
    if (vExitCode = STILL_ACTIVE) then //launched app still running.. 
    begin 
    //tell it to close 
    EnumWindows(@MyTerminateAppEnum, YourSavedProcessInfo.dwProcessId); 

    if WaitForSingleObject(YourSavedProcessInfo.hProcess, TIMEOUT_VAL) <> WAIT_OBJECT_0 then 
    begin 
     if not TerminateProcess(YourSavedProcessInfo.hProcess, 0) then //didn't close, try to terminate 
     begin 
     //uh-oh Didn't close, didn't terminate.. 
     end; 
    end; 
    end; 
    CloseHandle(YourSavedProcessInfo.hProcess); 
    CloseHandle(YourSavedProcessInfo.hThread); 
end; 
4

구성 요소를 JVCL으로 사용하면 win32의 모든 프로세스 관련 기능이 정상적으로 마무리됩니다. 이 답변은 Dont-Touch-Winapi에서 제공하는 것입니다. :-)

+0

그는 이미 TProcess라는 클래스를 사용하고 있다고 생각합니다. –

1

프로세스를 중지하는 유일한 방법은 TerminateProcess입니다. 그러나 그것은 당신이 얻을 수있는만큼 우아하지 않습니다. 프로세스를 정상적으로 종료하려면 프로세스에 중단을 알리고 프로세스가 종료되기를 바란다. 그러나 일반적으로 그렇게 할 방법이 없습니다.

GUI 프로그램의 경우 실행을 멈추고 싶다고 알리는 일반적인 방법은 기본 창을 닫는 것입니다. 하지만 "메인 윈도우"에 대한 공식적인 아이디어는 없습니다. 프로그램은 0 개 이상의 창을 가질 수 있으며, 프로그램을 작동시키지 않기 위해 어느 창을 닫아야하는지 외부에서 알 수있는 방법이 없습니다.

EnumWindows을 사용하여 모든 창을 순환하고 프로세스에 속한 창을 선택할 수 있습니다. (그들은 GetWindowThreadProcessId이 CreateProcess가 준 프로세스 ID와 동일한 프로세스 ID를 제공합니다.)

창을 닫으면 충분하지 않을 수 있습니다. 프로그램에 대화 상자가 표시 될 수 있습니다 (확인을 요청하거나 변경 사항 저장을 요청하는 등). 대화 상자를 닫는 방법을 미리 알아야합니다.

비 GUI 프로그램에도 유사한 문제가있을 수 있습니다. Ctrl + C 키 입력을 시뮬레이트하는 것으로 충분할 수 있습니다. 그것은 키 스트로크를 잡아서 다르게 처리 할 수 ​​있습니다. 프로그램을 종료하기 위해 "Q"를 입력 할 것을 기대하는 메뉴 시스템이있을 수 있습니다.

간단히 말해서 프로그램이 어떻게 닫힐 것으로 예상되는지 미리 알지 못한다면 프로그램을 정상적으로 종료 할 수 없습니다.

관련 문제