2010-05-04 53 views
4

我正尝试使用一些简短的Pascal程序中的一些Windows命令行工具。为了更容易,我正在编写一个名为DoShell的函数,它将一个命令行字符串作为参数,并返回一个名为ShellResult的记录类型,其中一个字段用于进程的退出代码,一个字段用于进程的输出文本。使用来自Pascal的Windows命令行

我遇到了一些标准库函数无法按预期工作的主要问题。 DOS Exec()函数实际上并没有执行我传递给它的命令。 Reset()过程给我一个运行时错误RunError(2),除非我设置编译模式{I-}。在这种情况下,我没有运行时错误,但之后我在该文件上使用的Readln()函数实际上并没有读取任何内容,而且在代码执行之后使用的Writeln()函数也不会执行任何操作。

这是我的程序到目前为止的源代码。我正在使用Lazarus 0.9.28.2 beta,使用Free Pascal编译器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. 
+0

Windows下尝试CMD/s的PROGRAMNAME参数1参数2 ...... – 2010-05-04 01:03:54

回答

1

快速查看我看到您尝试基于空间拆分命令。如果:

  • 我试着执行一些没有参数的东西,比如fpc? (回答:exepath将为空)
  • 我尝试使用完整路径执行某些操作,并且其中有空格,如C:\Program Files\Edit Plus 3\editplus.exe

我试过Exec()它似乎工作时,你给它的完整路径到你想运行的可执行文件,但输出重定向不起作用。看看:Command line redirection is performed by the command line interpreter。但是,您可以执行.bat重定向文件(使用命令user + give redirection,创建临时.bat文件并运行该批处理文件)。

+1

这就是为什么sysutils.executeprocess(含常量作为参数数组)在2004年推出,并dos.exec以来一直 – 2010-05-15 11:31:55

1

不要使用dos.exec,它仅限于短的(255个字符)命令行。使用sysutils.executeprocess

但是Michal的评论可能会触及主要问题。当通过内核(不是shell)执行时,应该总是提供一个完整的路径。另外,使用内核函数不能使用shell命令,如重定向。

一般而言,我建议您尝试使用process单元中的TProcess类。它抽象出所有这些和更多,也被Lazarus用来调用外部工具。

+0

以往任何时候都不赞成在较新版本,单元进程具有运行和捕获输出的runco​​mmand函数。 – 2017-12-06 14:17:49