我有一个命令行应用程序在delphi中编码,我需要从一个普通的桌面应用程序(也在delphi中编码)调用。简而言之,我想调用命令行应用程序,并在列表框中显示“live”输出的文本。
它已经老了,因为我玩了壳,但我清楚地记住,为了从命令行应用程序抓取文本 – 我必须使用管道符号“>”。喜欢这个:
C:/mycmdapp.exe> c:/result.txt
这将使任何打印到shell(使用writeLn)的文本并将其转储到名为“result.txt”的文本文件。
但是..(这里来的pickle),我想要一个现场结果,而不是一个积压文件。一个典型的例子是Delphi编译器本身 – 它管理向IDE报告发生了什么。如果我的记忆正确地服务我,我似乎记得,我必须创建一个“管道”通道(?),然后将管道名称分配给shell调用。
我试图google这个,但我真的不知道如何制定它。希望社会上有人能指出我的方向正确。
预先感谢您的帮助
更新:这个问题可能等同于How do I run a command-line program in Delphi?.一些answeres适合什么im寻找,虽然标题和问题本身不相同。
像往常一样,Zarco Gajic有一个解决方案:
Capture the output from a DOS (command/console) Window.这是他的文章的副本,供将来参考:
The example runs ‘chkdsk.exe c:\’ and displays the output to Memo1.
Put a TMemo (Memo1) and a TButton (Button1) on your form. Put this code in the OnCLick event procedure for Button1:
procedure TForm1.Button1Click(Sender: TObject) ; procedure RunDosInMemo(DosApp:String;AMemo:TMemo) ; const ReadBuffer = 2400; var Security : TSecurityAttributes; ReadPipe,WritePipe : THandle; start : TStartUpInfo; ProcessInfo : TProcessInformation; Buffer : Pchar; BytesRead : DWord; Apprunning : DWord; begin With Security do begin nlength := SizeOf(TSecurityAttributes) ; binherithandle := true; lpsecuritydescriptor := nil; end; if Createpipe (ReadPipe,WritePipe,@Security,0) then begin Buffer := AllocMem(ReadBuffer + 1) ; FillChar(Start,Sizeof(Start),#0) ; start.cb := SizeOf(start) ; start.hStdOutput := WritePipe; start.hStdInput := ReadPipe; start.dwFlags := STARTF_USESTDHANDLES + STARTF_USESHOWWINDOW; start.wShowWindow := SW_HIDE; if CreateProcess(nil,PChar(DosApp),true,NORMAL_PRIORITY_CLASS,nil,start,ProcessInfo) then begin repeat Apprunning := WaitForSingleObject (ProcessInfo.hProcess,100) ; Application.ProcessMessages; until (Apprunning <> WAIT_TIMEOUT) ; Repeat BytesRead := 0; ReadFile(ReadPipe,Buffer[0],ReadBuffer,BytesRead,nil) ; Buffer[BytesRead]:= #0; OemToAnsi(Buffer,Buffer) ; AMemo.Text := AMemo.text + String(Buffer) ; until (BytesRead < ReadBuffer) ; end; FreeMem(Buffer) ; CloseHandle(ProcessInfo.hProcess) ; CloseHandle(ProcessInfo.hThread) ; CloseHandle(ReadPipe) ; CloseHandle(WritePipe) ; end; end; begin {button 1 code} RunDosInMemo('chkdsk.exe c:\',Memo1) ; end;
更新:
上面的示例在一个步骤中读取输出。这里是从DelphiDabbler的另一个例子,显示在进程仍在运行时如何读取输出:
function GetDosOutput(CommandLine: string; Work: string = 'C:\'): string; var SA: TSecurityAttributes; SI: TStartupInfo; PI: TProcessInformation; StdOutPipeRead,StdOutPipeWrite: THandle; WasOK: Boolean; Buffer: array[0..255] of AnsiChar; BytesRead: Cardinal; WorkDir: string; Handle: Boolean; begin Result := ''; with SA do begin nLength := SizeOf(SA); bInheritHandle := True; lpSecurityDescriptor := nil; end; CreatePipe(StdOutPipeRead,StdOutPipeWrite,@SA,0); try with SI do begin FillChar(SI,SizeOf(SI),0); cb := SizeOf(SI); dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES; wShowWindow := SW_HIDE; hStdInput := GetStdHandle(STD_INPUT_HANDLE); // don't redirect stdin hStdOutput := StdOutPipeWrite; hStdError := StdOutPipeWrite; end; WorkDir := Work; Handle := CreateProcess(nil,PChar('cmd.exe /C ' + CommandLine),True,PChar(WorkDir),SI,PI); CloseHandle(StdOutPipeWrite); if Handle then try repeat WasOK := ReadFile(StdOutPipeRead,Buffer,255,nil); if BytesRead > 0 then begin Buffer[BytesRead] := #0; Result := Result + Buffer; end; until not WasOK or (BytesRead = 0); WaitForSingleObject(PI.hProcess,INFINITE); finally CloseHandle(PI.hThread); CloseHandle(PI.hProcess); end; finally CloseHandle(StdOutPipeRead); end; end;