如何在应用中读入Dos程序的输出信息(200分)

  • 主题发起人 主题发起人 kagemaru
  • 开始时间 开始时间
K

kagemaru

Unregistered / Unconfirmed
GUEST, unregistred user!
大家知道,在delphi 中可以方便的调用DOS应用程序。
但是这样的效果是出现一个黑底白字的Dos程序运行的
小窗口,然后运行完了就自动关闭。。。

我希望能在delphi程序中调用dos应用程序以后,不显示
那个黑白的小窗口,并且可以得到该dos程序运行的输出
结果(比如是“takes nnn seconds”之类的运行提示),
而且可以知道该程序是否已经运行完毕……总而言之,是
让这个被调用的dos程序能在delphi应用程序的掌握之中。

PS:我用的是delphi 5.0,该dos程序用Ansi C编写

谢谢大家。
 
在windows下你能得到另外一个程序的输出吗?恐怕也不容易。在dos下除非你做一个TSR程序
比较麻烦,也不能保证顺利运行----个人意见,再听听别人的。
 
直接的方法好象没有,要不你试试这样:你再调用的时候在程序名后面加上“>msg.txt”,
这是一个DOS下的重定向参数,那个DOS程序的所有输出都不再显示在屏幕上,而是输出到
Msg.txt里,然后你再打开msg.txt,读出里面的内容就不行了。 :)
 
用WinExec来调用DOS程序倒是可行,也可以判断是否程序结束运行,但要得到提示不知行不
行。
 
我要知道输出结果是为了一步一步的以图形界面整合显示程序运行状态,把msg
重定向到文件里我考虑过了,那样的界面提示是不友好的。。。

希望大家再接再厉。。。
 
winexec('command.com /c >abc.txt',sw_hide);
memo1.lines.loadfromfile(abc.txt);
 
dos程序运行结束过后,dos窗口的标题是: '已完成 - ' + dosfilename
可以以这个为运行结束的标志(我就是这样干的)
 
这个问题以前讨论过,没有解决办法。
楼上的方法只适用于在运行过程中无输入的情况。
如果使用一个文件作为输入流,也只能解决固定的输入,不能动态产生输入。
 
to kagemaru:你要友好点的话,就把文件的内容友好点的显示出来不就行了。
to creation-zy:要动态输入的话,你就动态生成输入文件。
 
creation-zy,我这里的dos程序运行过程中是无输入的,真的没有其他办法吗?

beta,那样太。。。那个了吧
 
用过NETBUS的远程DOS命令吗?用命令重定向就可以了。去外国论坛看看就知道了,
《程序员大本营》上也有代码,(新建一个文本文件a.txt,如:
dir
d:
cd abc
e:
rd ahg
然后新建一个无内容的b.txt,运行程序就会把a.txt的执行结果输出到b.txt.
注意:winexec('command.com /c ‘d: > winexec('command.com /c dir >实际上还是
无法去到D盘的。)
不过无论是NETBUS还是《程序员大本营》的代码都有BUG,就是无法关机和重新启动。
 
请问用winexec或者createprocess调用dos程序后,如何知道这个程序已经运行完毕?
 
function WinExecAndWait32(FileName:String; Visibility :integer):integer;
//调用其它程序并等待
var
zAppName:array[0..512] of char;
zCurDir:array[0..255] of char;
WorkDir:String;
StartupInfo:TStartupInfo;
ProcessInfo:TProcessInformation;
begin
StrPCopy(zAppName,FileName);
GetDir(0,WorkDir);
StrPCopy(zCurDir,WorkDir);
FillChar(StartupInfo,Sizeof(StartupInfo),#0);
StartupInfo.cb := Sizeof(StartupInfo);

StartupInfo.dwFlags := STARTF_USESHOWWINDOW;
StartupInfo.wShowWindow := Visibility;
if not CreateProcess(nil,
zAppName, { pointer to command line string }
nil, { pointer to process securityattributes }
nil, { pointer to thread securityattributes }
false, { handle inheritance flag }
CREATE_NEW_CONSOLE or { creation flags }
NORMAL_PRIORITY_CLASS,
nil, { pointer to new environment block }
nil, { pointer to current directory name }
StartupInfo, { pointer to STARTUPINFO }
ProcessInfo) then Result := -1 { pointer to PROCESS_INF }

else begin
WaitforSingleObject(ProcessInfo.hProcess,INFINITE);
// GetExitCodeProcess(ProcessInfo.hProcess,Result);
end;
end;

这个函数将调用别的程序直到其执行完毕,当然包括DOS下的程序。
 
谢谢教父的代码!又出现一个奇怪的问题:

以下是我的dos命令行
D:/Documents/log2dat.exe -o gh.ldd D:/writeable/TS.log >c:/msg.txt

这个命令行在dos窗口下执行时一切正常,但是用createprocess来执行就无法生成
c:/msg.txt文件,但是log2dat命令执行到了(有了结果文件),何解?
 
WinexecAndWait32('arj.exe >c:/temp/arj.txt',SW_SHOW);
我试了上面这一句,可以得到arj.txt文件啊。
 
<b>Capturing all of the Output from a Console application</b>
unit consoleoutput;

interface

uses
Controls, Windows, SysUtils, Forms;

function GetDosOutput(const CommandLine:string): string;

implementation

function GetDosOutput(const CommandLine:string): string;
var
SA: TSecurityAttributes;
SI: TStartupInfo;
PI: TProcessInformation;
StdOutPipeRead, StdOutPipeWrite: THandle;
WasOK: Boolean;
Buffer: array[0..255] of Char;
BytesRead: Cardinal;
WorkDir, Line: String;
begin
Application.ProcessMessages;
with SA do
begin
nLength := SizeOf(SA);
bInheritHandle := True;
lpSecurityDescriptor := nil;
end;
// create pipe for standard output redirection
CreatePipe(StdOutPipeRead, // read handle
StdOutPipeWrite, // write handle
@SA, // security attributes
0 // number of bytes reserved for pipe - 0
default
);
try
// Make child process use StdOutPipeWrite as standard out,
// and make sure it does not show on screen.
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 std
input
hStdOutput := StdOutPipeWrite;
hStdError := StdOutPipeWrite;
end;

// launch the command line compiler
WorkDir := ExtractFilePath(CommandLine);
WasOK := CreateProcess(nil, PChar(CommandLine), nil, nil, True, 0, nil,
PChar(WorkDir), SI, PI);

// Now that the handle has been inherited, close write to be safe.
// We don't want to read or write to it accidentally.
CloseHandle(StdOutPipeWrite);
// if process could be created then handle its output
if not WasOK then
raise Exception.Create('Could not execute command line!')
else
try
// get all output until dos app finishes
Line := '';
repeat
// read block of characters (might contain carriage returns and
line feeds)
WasOK := ReadFile(StdOutPipeRead, Buffer, 255, BytesRead, nil);

// has anything been read?
if BytesRead > 0 then
begin
// finish buffer to PChar
Buffer[BytesRead] := #0;
// combine the buffer with the rest of the last run
Line := Line + Buffer;
end;
until not WasOK or (BytesRead = 0);
// wait for console app to finish (should be already at this point)
WaitForSingleObject(PI.hProcess, INFINITE);
finally
// Close all remaining handles
CloseHandle(PI.hThread);
CloseHandle(PI.hProcess);
end;
finally
result:=Line;
CloseHandle(StdOutPipeRead);
end;
end;
end.
 
to :qqphoenix
你的方法会出错。
并且你的方法中也是当DOS 程序运行结束后才在MEMO中显示的。
 
如果是文本行输出,管道和重定向都可以用
 
多人接受答案了。
 
后退
顶部