Delphi - 생성된 서비스 프로세스를 정상적으로 종료합니다.(tprocess / createProcess 사용)

StackOverflow https://stackoverflow.com/questions/268208

문제

저는 여러 프로그램을 실행하는 Delphi로 작성된 Windows 서비스를 가지고 있습니다.

서비스를 중지하면 해당 프로그램도 종료하고 싶습니다.서비스가 처음 작성되었을 때는 잘 작동했지만 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 프로시저를 통해 시작한 프로그램도 중지(종료 아님)하고 싶습니다.

어떻게 하시겠습니까?

도움이 되었습니까?

해결책

출시 된 ProcessID와 일치하는 열린 창을 열거하고 창문을 닫으라고 지시합니다. 다음은 다음과 같은 샘플 코드입니다.

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;

그런 다음 시작된 응용 프로그램을 종료하려면 코드에서이를 활용하려고합니다.

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;

다른 팁

나는 사용할 것이다 tjvcreateprocess 구성 요소 JVCL 이는 Win32의 모든 프로세스 관련 기능에 대해 우아한 방식으로 랩합니다. 이 답변은 Dont-Touch-Winapi-unly really required 부서에서 나옵니다 :-)

프로세스를 중지하는 유일한 일반적인 방법은 다음을 사용하는 것입니다. 프로세스 종료.그러나 그것은 당신이 얻을 수 있는 우아함과는 거리가 멀다.프로세스를 정상적으로 종료하려면 프로세스를 중지하고 싶다고 말한 다음 프로세스가 따르기를 바라야 합니다.하지만 일반적으로 그렇게 할 수 있는 방법은 없습니다.

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

당신은 사용할 수 있습니다 열거형Windows 모든 창을 순환하고 프로세스에 속하는 창을 선택합니다.(그들은 다음과 같은 사람들이 될 것입니다 GetWindowThread프로세스 ID CreateProcess가 제공한 것과 동일한 프로세스 ID를 제공합니다.)

창을 닫는 것만으로는 충분하지 않을 수 있습니다.프로그램은 대화 상자를 표시할 수 있습니다(확인 메시지 또는 변경 사항 저장 요청 등).해당 대화 상자를 닫는 방법을 미리 알아야 합니다.

GUI가 아닌 프로그램에도 비슷한 문제가 있을 수 있습니다.Ctrl+C 키 입력을 시뮬레이션하는 것으로 충분할 수 있습니다.하지만 해당 키 입력을 다르게 포착하고 처리할 수도 있습니다.프로그램을 종료하려면 "Q"를 입력해야 하는 메뉴 시스템이 있을 수 있습니다.

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

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top