Using Windows command line from Pascal

I am trying to use some Windows command line tools from the short Pascal program. To keep things simple, I write a DoShell function that takes a command line as an argument and returns a record type called ShellResult, with one field for the process termination code and one field for the output of the process.

I am having serious problems with some standard library functions that do not work properly. The DOS Exec () function does not actually execute the command that I pass to it. The Reset () procedure gives me a RunError (2) runtime error if I did not set the compiler mode {I-}. In this case, I do not get errors at runtime, but the Readln () functions that I use in this file do not actually read anything, and in addition, the Writeln () functions used after this point in the code execution are also nothing do not do.

Here is the source code of my program. I am using Lazarus 0.9.28.2 beta, with Free Pascal Compiler 2.24

program project1; {$mode objfpc}{$H+} uses Classes, SysUtils, StrUtils, Dos { you can add units after this }; {$IFDEF WINDOWS}{$R project1.rc}{$ENDIF} type ShellResult = record output : AnsiString; exitcode : Integer; end; function DoShell(command: AnsiString): ShellResult; var exitcode: Integer; output: AnsiString; exepath: AnsiString; exeargs: AnsiString; splitat: Integer; F: Text; readbuffer: AnsiString; begin //Initialize variables exitcode := 0; output := ''; exepath := ''; exeargs := ''; splitat := 0; readbuffer := ''; Result.exitcode := 0; Result.output := ''; //Split command for processing splitat := NPos(' ', command, 1); exepath := Copy(command, 1, Pred(splitat)); exeargs := Copy(command, Succ(splitat), Length(command)); //Run command and put output in temporary file Exec(FExpand(exepath), exeargs + ' >__output'); exitcode := DosExitCode(); //Get output from file Assign(F, '__output'); Reset(F); Repeat Readln(F, readbuffer); output := output + readbuffer; readbuffer := ''; Until Eof(F); //Set Result Result.exitcode := exitcode; Result.output := output; end; var I : AnsiString; R : ShellResult; begin Writeln('Enter a command line to run.'); Readln(I); R := DoShell(I); Writeln('Command Exit Code:'); Writeln(R.exitcode); Writeln('Command Output:'); Writeln(R.output); end. 
+4
source share
3 answers

In a quick scan, I see that you are trying to split a command based on space. What to do, if:

  • Am I trying to do something without parameters like fpc ? (answer: exepath will be empty)
  • Am I trying to execute something with a full path and with space in it, like C:\Program Files\Edit Plus 3\editplus.exe ?

I tried Exec() and it seems to work when you give the full path to the executable you want to run, but output redirection does not work. Take a look: Command line redirection is performed by the command line interpreter . However, you can execute the .bat file that redirects (create a temporary .bat file with the user command, give + redirection and run this batch).

+1
source

Do not use dos.exec, it is limited to a short (255 char) command line. Use sysutils.executeprocess .

However, Michal's comments probably address the underlying issue. When executed through kernel functions (not shells), the full path must always be provided. In addition, using kernel functions, you cannot use shell commands such as redirection.

In general, I suggest you try using the TProcess class in the process module. It abstracts all of this and more, and is also used by Lazarus to call external tools.

+1
source

You can use this:

 uses sysutils; begin ExecuteProcess('cmd','/c dir C:\foo'); ExecuteProcess('C:\foo\bar.exe','param1 param2'); end. 

If you want to get the output of the command, you can see this post. http://wiki.freepascal.org/Executing_External_Programs#TProcess

+1
source

Source: https://habr.com/ru/post/1308708/


All Articles