2010-05-04 54 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