title: Using windows command line from Pascal
body: <p>I'm trying to use some windows command line tools from within a short Pascal program.  To make it easier, I'm writing a function called DoShell which takes a command line string as an argument and returns a record type called ShellResult, with one field for the process's exitcode and one field for the process's output text.</p>
  
  <p>I'm having major problems with some standard library functions not working as expected.  The DOS Exec() function is not actually carrying out the command i pass to it.  The Reset() procedure gives me a runtime error RunError(2) unless i set the compiler mode {I-}. In that case i get no runtime error, but the Readln() functions that i use on that file afterwards don't actually read anything, and furthermore the Writeln() functions used after that point in the code execution do nothing as well.</p>
  
  <p>Here's the source code of my program so far.  I'm using Lazarus 0.9.28.2 beta, with Free Pascal Compiler 2.24</p>
  
  <pre><code>
  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.
  </code></pre>