• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 328
  • Last Modified:

GetExitCodeProcess

How can i create a timer for my application to call GetExitCodeProcess() . If the function returns 0
and the lpExitCode is STILL_ACTIVE , the program has not yet been terminated . If the function returns true , then the lpExitCode has the returned error value ( errorlevel ) ,

Can anyone help me.. i need a source please..!! THANKS
0
ichen
Asked:
ichen
  • 2
1 Solution
 
ZifNabCommented:
Hi ichen,

Is this what you want?

function WinExecAndWait32(FileName:String; Visibility :
integer):integer;
var
  zAppName:array[0..512] of char;
  zCurDir:array[0..255] of char;
  WorkDir:String;
  StartupInfo:TStartupInfo;
  ProcessInfo:TProcessInformation;
begin
  StrPCopy(zAppName,FileName);
  GetDir(0,WorkDir);
  StrPCopy(zCurDir,WorkDir);

  FillChar(StartupInfo,Sizeof(StartupInfo),#0);
  StartupInfo.cb := Sizeof(StartupInfo);
  StartupInfo.dwFlags := STARTF_USESHOWWINDOW;
  StartupInfo.wShowWindow := Visibility;
  if not CreateProcess(nil,
    zAppName, { pointer to command line string }
    nil, { pointer to process security attributes }
    nil, { pointer to thread security attributes }
    false, { handle inheritance flag }
    CREATE_NEW_CONSOLE or { creation flags }
    NORMAL_PRIORITY_CLASS,
    nil, { pointer to new environment block }
    nil, { pointer to current directory name }
    StartupInfo, ointer to STARTUPINFO }
    ProcessInfo) then Result := -1 { pointer to PROCESS_INF }
  else begin
    WaitforSingleObject(ProcessInfo.hProcess,INFINITE);
    GetExitCodeProcess(ProcessInfo.hProcess,Result);
  end;
end;

Zif.

Regr
0
 
erajojCommented:
Hi,
ZifNab's answer is the way to do it. Just execute his code in a thread so that your main app doesn't lock.
If you still want to do it the timer way; here's an example I just whipped together:

type
  TProcessWatch = class( TTimer )
  private
    FhProcess : THandle;
    FiExitCode: Integer;
    FbRunning : Boolean;
    FOnExit   : TNotifyEvent;
    procedure FWatch(Sender: TObject);
    property  OnTimer;
  public
    constructor Create( AOwner: TComponent; Process: THandle; Suspended: Boolean );
    procedure   Start;
    procedure   Stop;
    property    Handle  : THandle read FhProcess write FhProcess;
    property    ExitCode: Integer read FiExitCode;
    property    Running : Boolean read FbRunning;
    property    OnProcessExit: TNotifyEvent read FOnExit write FOnExit;
  end;

.

procedure TProcessWatch.FWatch(Sender: TObject);
var
  iExitCode: Integer;
begin
  if ( GetExitCodeProcess( FhProcess, iExitCode ) )
  then begin
    FiExitCode := iExitCode;
    FbRunning  := ( iExitCode = STILL_ACTIVE );
    if ( not FbRunning ) and Assigned( FOnExit )
    then FOnExit( Self );
  end else begin
    FiExitCode := -1;
    FbRunning  := False;
  end;
end;

constructor TProcessWatch.Create( AOwner: TComponent; Process: THandle; Suspended: Boolean );
begin
  inherited Create( AOwner );
  inherited OnTimer := FWatch;
  FhProcess         := Process;
  OnTimer( Self ); // get initial status
  Enabled := not Suspended;
end;

procedure   TProcessWatch.Start;
begin
  Enabled := True;
end;

procedure   TProcessWatch.Stop;
begin
  Enabled := False;
end;

To use it:

procedure TForm1.OnExitProc(Sender: TObject);
begin
  Windows.Beep( 1000, 1000 );
  ( Sender as TProcessWatch ).Free;
end;

.

procedure TForm1.NotepadButtonClick(Sender: TObject);
var
  Command    : string;
  StartupInfo: TStartupInfo;
  ProcessInfo: TProcessInformation;
begin
  Command := 'notepad';
  FillChar(StartupInfo, Sizeof(StartupInfo),#0);
  StartupInfo.cb := SizeOf( StartupInfo );
  StartupInfo.dwFlags := STARTF_USESHOWWINDOW;
  StartupInfo.wShowWindow := SW_SHOWNORMAL;
  if CreateProcess(nil,
    PChar(Command),           { pointer to command line string }
    nil,                      { pointer to process security attributes }
    nil,                      { pointer to thread security attributes }
    false,                    { handle inheritance flag }
    CREATE_NEW_CONSOLE or     { creation flags }
    NORMAL_PRIORITY_CLASS,
    nil,                      { pointer to new environment block }
    nil,                      { pointer to current directory name }
    StartupInfo,              { pointer to STARTUPINFO }
    ProcessInfo)              { pointer to PROCESS_INF }
  then begin
    with TProcessWatch.Create( Self, ProcessInfo.hProcess, True ) do begin // create suspended
      OnProcessExit := OnExitProc;
      Interval := 100; // faster check than def
      Start;
    end;
  end;
end;

Not pretty, but working!

/// John
0
 
ZifNabCommented:
you whipped good John :-), Zif.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now