Lazarus

Programming => General => Topic started by: Pascal on October 12, 2018, 01:23:02 pm

Title: [Solved] TProcess.ExitStatus not working on Windows?
Post by: Pascal on October 12, 2018, 01:23:02 pm
I can't get the exit status of an external script actual. I tried many ways of calling the external script.
- TProcess with cmd /c myscript.cmd parameter
- TProcess with path\myscript parameter
- RunCommandInDir

The script runs and sets errorlevel to 9 but the exitstatus is always 0.

Any ideas?
Title: Re: TProcess.ExitStatus not working on Windows?
Post by: Thaddy on October 12, 2018, 02:21:18 pm
What is the exitcode? (we have exitstatus and exitcode).
Title: Re: TProcess.ExitStatus not working on Windows?
Post by: Pascal on October 12, 2018, 02:39:56 pm
What is the exitcode? (we have exitstatus and exitcode).

ExitCode returns 0 while process is running and returns ExitStatus when finished:
Code: Pascal  [Select][+][-]
  1. Function TProcessnamemacro.GetExitCode : Integer;
  2.  
  3. begin
  4.   if Not Running then
  5.     Result:=GetExitStatus
  6.   else
  7.     Result:=0
  8. end;
Title: Re: TProcess.ExitStatus not working on Windows?
Post by: Jurassic Pork on October 12, 2018, 03:36:07 pm
hello,
you can try runcommandindir from process unit :
Code: Pascal  [Select][+][-]
  1. function RunCommandIndir(
  2.   const curdir: string;
  3.   const exename: string;
  4.   const commands: array of string;
  5.   out outputstring: string;
  6.   out exitstatus: Integer;
  7.   Options: TProcessOptions = []
  8. ):Integer;
  9.  

Quote
RunCommandInDir will execute binary exename with command-line options commands, setting curdir as the current working directory for the command. The Options are taken into consideration (poRunSuspended,poWaitOnExit are removed from the set). The output of the command is captured, and returned in the string OutputString. The function waits for the command to finish, and returns True if the command was started succesfully, False otherwise. In the case where the return value is an integer, it is zero for success, and -1 on error.

If a ExitStatus parameter is specified the exit status of the command is returned in this parameter.

Friendly, J.P
Title: Re: TProcess.ExitStatus not working on Windows?
Post by: Pascal on October 12, 2018, 05:09:58 pm
hello,
you can try runcommandindir from process unit :
Code: Pascal  [Select][+][-]
  1. function RunCommandIndir(
  2.   const curdir: string;
  3.   const exename: string;
  4.   const commands: array of string;
  5.   out outputstring: string;
  6.   out exitstatus: Integer;
  7.   Options: TProcessOptions = []
  8. ):Integer;
  9.  

Quote
RunCommandInDir will execute binary exename with command-line options commands, setting curdir as the current working directory for the command. The Options are taken into consideration (poRunSuspended,poWaitOnExit are removed from the set). The output of the command is captured, and returned in the string OutputString. The function waits for the command to finish, and returns True if the command was started succesfully, False otherwise. In the case where the return value is an integer, it is zero for success, and -1 on error.

If a ExitStatus parameter is specified the exit status of the command is returned in this parameter.

Friendly, J.P

Well, i did, see original post. In fact it just encapsulates TProcess. So internally it uses TProcess.ExitStatus.
Title: Re: TProcess.ExitStatus not working on Windows?
Post by: marcov on October 12, 2018, 06:00:31 pm
File 1: test1.cmd

Code: [Select]
  exit /b 7

file 2 exectest.pas

Code: [Select]
{$mode delphi}
uses process ;
var ex : integer;
    outp:string;
begin
  writeln(Runcommandindir('.','cmd.exe',['/c','test1.cmd'],outp,ex));  // returns 0 on success execution, -1 otherwise
   writeln(ex);  // prints exitstatus.
end.

prints

Code: [Select]
0
7

If I change the code in test.cmd to "8" and rerun, I get 0 8

So what is exactly the problem?
Title: Re: TProcess.ExitStatus not working on Windows?
Post by: Jurassic Pork on October 12, 2018, 06:09:20 pm
you can also try TprocessEx from ProcessUtils unit of fpcUpDeluxe project (https://github.com/newpascal/fpcupdeluxe). :
Code: Pascal  [Select][+][-]
  1. procedure TForm1.Bt_GoExClick(Sender: TObject);
  2. var
  3.   Proc: TProcessEx;
  4. begin
  5.    try
  6.    Proc := TProcessEx.Create(nil);
  7.    Proc.Executable := 'cmd.exe';
  8.    Proc.Parameters.Add('/C');
  9.    Proc.Parameters.Add('ping.exe juju');
  10. //Proc.Parameters.Add('ping.exe 127.0.0.1');
  11.    Proc.OnErrorM:=@(ProcessError);
  12.    Proc.OnOutputM:=@(ProcessOutput);
  13.    Proc.Execute();
  14.    MemConsole.Append(inttoStr(Proc.ExitStatus));
  15.    MemConsole.Append(inttoStr(Proc.ExitCode));
  16.    finally
  17.      Proc.Free;
  18.      Proc := nil;
  19.    end;
With ping.exe 127.0.0.1 i have exitCode and exitStatus to 0 and with ping.exe juju i have exitCode and exitStatus to 1.
Title: Re: TProcess.ExitStatus not working on Windows?
Post by: jamie on October 13, 2018, 02:12:01 am
I don't think using the CMD to execute a ping.exe is going to return an exit code from the ping.exe app

 you started CMD and that is where the exit code is coming from, from my point of view that is.

 Directly call the ping.exe in the process and then try using "GetExitCOdeProess(ProcessHandle, StorageVariable)" before
 freeing the Tprocess…
Title: Re: TProcess.ExitStatus not working on Windows?
Post by: Pascal on October 13, 2018, 06:19:19 am
I found the problem:
There are three nested scripts. The inner script calls "exit /b 9" on error but this does not get handed over to the initially called script.
Also %ERRORLEVEL% is 9, ExitStatus is still 0.
To solve this i added "exit /b %ERRORLEVEL%" to the end of the initially called script.

Then it also makes no difference if i call the script directly or with "cmd /c".

I would have thought that ExitStatus would have been set to the value of %ERRORLEVEL% automatically  :'(

Anyway, many thanks for all the hints here!
Title: Re: TProcess.ExitStatus not working on Windows?
Post by: marcov on October 13, 2018, 02:09:04 pm
I would have thought that ExitStatus would have been set to the value of %ERRORLEVEL% automatically  :'(

This is one of the command.com/cmd.exe differences. In cmd.exe errorlevel is just an environment variable which life stops if its shell ends.
TinyPortal © 2005-2018