2011-08-18 3 views
3

Delphi에서 오랫동안 실행중인 백그라운드 프로세스를 시작하고 싶습니다. 프로세스를 독립적으로 실행하고 싶지만 먼저 프로세스가 시작되었는지 확인하고 싶습니다.장기 실행 백그라운드 프로세스 시작 및 상태 확인

시작시 문제가 발생하면 standardErr에 기록 된 출력을 캡처하여 기록하려고합니다. 백그라운드 프로세스가 정상적으로 시작되면 내 프로그램이 종료되어 생성 된 프로세스가 실행되도록 유지해야합니다.

들의 유사 코드는 다음과 같이 될 것이다 : 나는 몇 가지 (WinExec, CreateProcess를,에서 ShellExecute, JclMiscel)을 검토 한

process:=RunProgramInBackground('someCommand.exe'); 
sleep(1000); // Wait a bit to see if the program started OK 
if process.Finished and process.ExitCode=FAIL then 
    Raise Exception.Create(process.ErrorStream); 
process.Dispose; // Close any connection we may still have to the running process 
Program.Exit; // Background process keeps running 

하지만 난 노력하고있어에 대한 예제를 찾을 수 없습니다 할 것. 이 작업을 수행하는 가장 좋은 방법은 무엇입니까? 델파이 2010

백그라운드 프로세스를 사용하고

나는 소스가없는 제 3 자 프로그램입니다.

+0

'RunProgramInBackground가'(당신이 'somecommand'에 코드를 가지고 있다고 가정) 스레드에서 구현 될 수있다 : 여기

내가 무슨 짓을? –

+0

이 질문은 분명히 필요합니다. "someCommand.exe"가 소스를 가지고 있는지 아닌지? 그렇지 않으면 프로세스를 시작한 다음 종료 코드를 캡처하고 오류가없는 경우 완료 될 때까지 기다리는 것입니다. 당연히 스레드에서이 작업을 수행 할 수 있지만 원하는 작업을 많이 수행하면보다 구체적인 작업을 수행 할 수 있습니다. – Glenn1234

+0

@ No'am 그것은 제 3 자 실행 파일입니다. 나는 소스 코드가 없다. – awmross

답변

0

보는 것이 좋습니다. 이 함수는 백그라운드 프로세스의 종료 코드 만 검사하며 StdErr 출력은 읽지 않습니다. 확실히

/// <summary> Runs a new process in the background. Waits for a short period, then checks that the process started succesfully. 
/// If the process has already finished, checks the exit status. Otherwise, leaves it to run. </summary> 
/// <param> ProgramName The executable name, including any parameters.</param> 
/// <param> TimeOut Milliseconds to wait before checking the process has executed correctly</param> 
/// <param> Directory The full path of the working directory</param> 
/// <exception> Exception If the process was not started correctly or if the process was started but returned 
/// an error before the timeout.</exception> 
procedure ExecBackgroundProcess(ProgramName : String; TimeOut: Integer; Directory:string); 
var 
    StartInfo : TStartupInfo; 
    ProcInfo : TProcessInformation; 
    CreateOK : Boolean; 
    status: Cardinal; 
    theExitCode: Cardinal; 
begin 
    FillChar(StartInfo,SizeOf(TStartupInfo),#0); 
    FillChar(ProcInfo,SizeOf(TProcessInformation),#0); 
    StartInfo.cb := SizeOf(TStartupInfo); 
    UniqueString(ProgramName); // Required if a const string is passed in. Otherwise the program crashes. 
    CreateOK := CreateProcess(nil, PChar(ProgramName), nil, nil,False, 
       CREATE_NEW_PROCESS_GROUP+NORMAL_PRIORITY_CLASS+CREATE_NO_WINDOW, 
       nil, PChar(Directory), StartInfo, ProcInfo); 

    if CreateOK then 
    begin 
     status:=WaitForSingleObject(ProcInfo.hProcess, TimeOut); 
     if status<> WAIT_TIMEOUT then 
     begin 
      // Program has exited. Get exit code. 
      GetExitCodeProcess(ProcInfo.hProcess, theExitCode); 
      if theExitCode<>0 then raise Exception.Create('Program '''+ProgramName+''' failed with exit code '+IntToStr(theExitCode)); 
     end 
    end 
    else 
     Raise Exception.Create('Unable to run '+ProgramName+' in directory '+Directory); 

    CloseHandle(ProcInfo.hProcess); 
    CloseHandle(ProcInfo.hThread); 
end; 
3

체크 아웃 article. 나는 다음과 같이 인용한다. "코드를 업데이트하고 개선 한 버전으로, 호출 응용 프로그램이 다른 프로그램이 닫히기 전까지 기다려야하는지 아니면 계속 새로 시작한 프로그램을 자체 장치에 남겨 둘지를 코드에서 선택할 수 있습니다."

procedure ExecNewProcess(ProgramName : String; Wait: Boolean); 
var 
StartInfo : TStartupInfo; 
ProcInfo : TProcessInformation; 
CreateOK : Boolean; 

begin 
{ fill with known state } 
FillChar(StartInfo,SizeOf(TStartupInfo),#0); 
FillChar(ProcInfo,SizeOf(TProcessInformation),#0); 
StartInfo.cb := SizeOf(TStartupInfo); 
CreateOK := CreateProcess(nil, PChar(ProgramName), nil, nil,False, 
        CREATE_NEW_PROCESS_GROUP+NORMAL_PRIORITY_CLASS, 
        nil, nil, StartInfo, ProcInfo); 
{ check to see if successful } 
if CreateOK then 
    begin 
    //may or may not be needed. Usually wait for child processes 
    if Wait then 
    WaitForSingleObject(ProcInfo.hProcess, INFINITE); 
    end 
else 
    begin 
    ShowMessage('Unable to run '+ProgramName); 
    end; 

CloseHandle(ProcInfo.hProcess); 
CloseHandle(ProcInfo.hThread); 
end; 

편집 : 귀하의 의견을 읽은 후, 나는 당신이 내가 프로세스가 OK 시작 있는지 확인하는 코드를 연결 예제 No'Am을 사용하고 추가 결국이 이전 question

+0

프로세스가 정상적으로 시작되었지만 오류와 함께 종료 될 수 있습니다. 아마도 WaitForSingleObject를 호출해야하지만 유한 시간 초과 (예 : 원래 질문과 같이 1000)가 필요합니다. 난 여전히 어떤 오류 스트림을 읽을 수있는 방법이 필요합니다 ... – awmross

+0

@awmross 여기에 주어진 것은 좋은 것입니다. 당신이해야 할 일은 "WaitForSingleObject"호출을 제거하고 그곳에서 에러 스트림이 무엇인지보기 위해 파이프를 읽는 것입니다. – Glenn1234

+0

@ Glenn1234 어떻게 그럴 수 있니? – awmross

관련 문제