如何得到控制台程序的输出

所有的程序都有标准输入,标准输出,标准错误这三个管道存在, 所以我们想得到控制台程序的输出,可以通过重定向这些管道来实现.

首先, 我们要建立一个管道作为控制台程序的标准输出管道, 因为这个管道要转给控制台程序使用, 所以它应该是可以被控制台程序继承的句柄.
ZeroMemory(@mSa, SizeOf(mSa));
mSa.nLength :
= SizeOf(mSa);
mSa.bInheritHandle :
= True; //设定为可以为子进程继承的句柄
mSa.lpSecurityDescriptor := nil;

if not CreatePipe(mOutRd, mOutWr, @mSa, 0) then raise Exception.Create('建立管道出错');


第二步, 复制读管道的句柄, 因为读管道的句柄在建立时是一个可继承句柄, 它可能会被子进程使用, 那样会造成信息的丢失与父进程的堵塞, 所以我们要复制成一个不可以继承句柄, 并且它实际上在子进程中是没有用的, 所以我们在复制成功后要关闭它.

if not DuplicateHandle(GetCurrentProcess, mOutRd, GetCurrentProcess,
@mOutRdDup, 
0, False, DUPLICATE_SAME_ACCESS) then
raise Exception.Create(
'复制读句柄出错');

CloseHandle(mOutRd);


第三步, 我们要建立控制台子进程了
ZeroMemory(@mStartupInfo, SizeOf(mStartupInfo));
mStartupInfo.cb :
= SizeOf(mStartupInfo);
mStartupInfo.dwFlags :
= mStartupInfo.dwFlags or STARTF_USESTDHANDLES; //将标准输出重定向
mStartupInfo.hStdOutput := mOutWr;
mStartupInfo.hStdError :
= mOutWr;
ZeroMemory(@mProcess, SizeOf(mProcess));

if not CreateProcess(nil, cmdLine,nil, nil, True, 0, nil, WorkDir, mStartupInfo,mProcess) then
raise Exception.Create(
'启动程序出错');

CloseHandle(mProcess.hProcess);
CloseHandle(mProcess.hThread);


第四步, 关闭写句柄, 要不然当子进程关闭了自己后, 会因为写句柄还被父进程所打开, 而使下面的ReadFile无法得知管道已结束, 从而堵塞.

if not CloseHandle(mOutWr) then
raise Exception.Create(
'标准输出句柄关闭出错');

while ReadFile(mOutRdDup, mBuff, 256, mRealRead, nil) do begin
if mRealRead = 0 then Break;
//作点自己爱作的事情吧
end;


完整的代码如下:
var
mRealRead: DWORD;
mOutRd, mOutWr, mOutRdDup: THandle;
mSa: TSecurityAttributes;
mProcess: TProcessInformation;
mStartupInfo: TStartupInfo;
mBuff: array[
0..255] of Char;
begin
ZeroMemory(@mSa, SizeOf(mSa));
mSa.nLength :
= SizeOf(mSa);
mSa.bInheritHandle :
= True;
mSa.lpSecurityDescriptor :
= nil;

if not CreatePipe(mOutRd, mOutWr, @mSa, 0) then raise Exception.Create('建立管道出错');

if not DuplicateHandle(GetCurrentProcess, mOutRd, GetCurrentProcess,
@mOutRdDup, 
0, False, DUPLICATE_SAME_ACCESS) then
raise Exception.Create(
'复制读句柄出错');

CloseHandle(mOutRd);
ZeroMemory(@mStartupInfo, SizeOf(mStartupInfo));
mStartupInfo.cb :
= SizeOf(mStartupInfo);
mStartupInfo.dwFlags :
= mStartupInfo.dwFlags or STARTF_USESTDHANDLES;
mStartupInfo.hStdOutput :
= mOutWr;
mStartupInfo.hStdError :
= mOutWr;
mStartupInfo.hStdInput :
= GetStdHandle(STD_INPUT_HANDLE);
ZeroMemory(@mProcess, SizeOf(mProcess));


if not CreateProcess(nil, cmdLine,nil, nil, True, 0, nil, WorkDir, mStartupInfo,mProcess) then raise Exception.Create('启动程序出错');

CloseHandle(mProcess.hProcess);
CloseHandle(mProcess.hThread);

if not CloseHandle(mOutWr) then
raise Exception.Create(
'标准输出句柄关闭出错');

while ReadFile(mOutRdDup, mBuff, 256, mRealRead, nil) do begin
if mRealRead = 0 then Break;
mmo1.Lines.Add(mBuff);
Application.ProcessMessages;
end; 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值