我正在尝试在一个简短的Pascal程序中使用一些Windows命令行工具。为了更容易,我正在编写一个名为DoShell的函数,它将命令行字符串作为参数并返回一个名为ShellResult的记录类型,其中一个字段用于进程的exitcode,一个字段用于进程的输出文本。
我遇到了一些标准库函数无法按预期工作的主要问题。 DOS Exec()函数实际上并没有执行我传递给它的命令。除非我设置编译器模式{I-},否则Reset()过程会给出运行时错误RunError(2)。在这种情况下,我没有得到运行时错误,但我之后在该文件上使用的Readln()函数实际上并没有读取任何内容,而且在代码执行中该点之后使用的Writeln()函数也不做任何事情。 / p>
到目前为止,这是我的程序的源代码。我正在使用Lazarus 0.9.28.2 beta,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.
答案 0 :(得分: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 :(得分:1)
不要使用dos.exec,它仅限于短(255个字符)命令行。使用sysutils.executeprocess
。
一般情况下,我建议您尝试使用TProcess
单元中的process
类。它抽象了所有这些以及更多内容,Lazarus也使用它来调用外部工具。
答案 2 :(得分:1)
您可以使用:
uses sysutils;
begin
ExecuteProcess('cmd','/c dir C:\foo');
ExecuteProcess('C:\foo\bar.exe','param1 param2');
end.
如果您想获得命令输出,可能需要查看此帖子。 http://wiki.freepascal.org/Executing_External_Programs#TProcess