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

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

首先, 我们要建立一个管道作为控制台程序的标准输出管道, 因为这个管道要转给控制台程序使用, 所以它应该是可以被控制台程序继承的句柄.
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; 
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值