匿名管道实现获取控制台程序输出

原创 2007年10月12日 12:19:00

 

在程序设计中,有时候需要调用一些控制台程序并取得其在控制台上的输出,如VSIDE就调用了cl.exelink.exe等控制台的程序,并可将这些程序的输出在IDE中显示出来。
曾经很迷惑这个功能的实现,直到有一天看到下面的参考代码才恍然大悟,原来一切都这么简单,只不过用了CreatePipeCreateProcessReadFile寥寥几个函数而已。特此记下以供参考。
#include"Stdafx.h"
#include<windows.h>
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
 /* protos */ 
DWORD WINAPI ReadFromPipe(LPVOID args);
 /* globals */ 
#define CHUNK 25
#define STATICBUFFERSIZE    1000
typedefstruct {
HANDLE pipe;
char buffer[STATICBUFFERSIZE];
} pipeinfo;
 
 
pipeinfo Out = {INVALID_HANDLE_VALUE, '/0'};
pipeinfo Err = {INVALID_HANDLE_VALUE, '/0'};
 
int main( int argc, char *argv[])
{
if (argc < 2)
{
printf("pipetest ??");
return 0;
}
STARTUPINFO si;
 
PROCESS_INFORMATION pi;
SECURITY_ATTRIBUTES sa;
DWORD threadID;
char msg[300];
BOOL ok;
HANDLE hProcess, h, pipeThreads[2];
char cmdline[100];
 
hProcess = GetCurrentProcess();
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
si.dwFlags   = STARTF_USESTDHANDLES;
 
si.hStdInput = INVALID_HANDLE_VALUE;
 
ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES));
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
 
/* Create a non-inheritible pipe.  */
CreatePipe(&Out.pipe, &h, &sa, 0);
 
/* Dupe the write side, make it inheritible, and close the original. */
 DuplicateHandle(hProcess, h, hProcess, &si.hStdOutput, 0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
 
/*  Same as above, but for the error side.  */
 CreatePipe(&Err.pipe, &h, &sa, 0);
DuplicateHandle(hProcess, h, hProcess, &si.hStdError, 0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
 
strcpy(cmdline, "");
for (int i = 1; i < argc; i++)
{
strcat(cmdline, argv[i]);
strcat(cmdline, " ");
}
 
ok = CreateProcess(NULL, cmdline, NULL, NULL, TRUE, DETACHED_PROCESS, NULL, NULL, &si, &pi);
 if  (!ok)
{
DWORD err = GetLastError();
int chars = _snprintf(msg, sizeof(msg) - 1, "Tried to launch: /"%s/", but got error [%u]: ", cmdline, err);
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS |  FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, &msg[chars], (300-chars), 0);
WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, lstrlen(msg), &err,NULL);
return 2;
}
/*  Close our references to the write handles that have now been inherited.*/
CloseHandle(si.hStdOutput);
CloseHandle(si.hStdError);
 
WaitForInputIdle(pi.hProcess, 5000);
CloseHandle(pi.hThread);
 
/* Start the pipe reader threads.*/
pipeThreads[0] = CreateThread(NULL, 0, ReadFromPipe, &Out, 0, &threadID);
pipeThreads[1] = CreateThread(NULL, 0, ReadFromPipe, &Err, 0, &threadID);
 
/*  Block waiting for the process to end.*/
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
 
/*  Wait for our pipe to get done reading, should it be a little slow.*/
WaitForMultipleObjects(2, pipeThreads, TRUE, INFINITE);
CloseHandle(pipeThreads[0]);
CloseHandle(pipeThreads[1]);
 
return 0;
}
 
DWORD WINAPI ReadFromPipe(LPVOID args)
{
pipeinfo *pi = (pipeinfo *) args;
char *lastBuf = pi->buffer;
DWORD dwRead;
BOOL ok;
char buf[2000];
 
again:
ok = ReadFile(pi->pipe, buf, 2000, &dwRead, 0L);
if  (!ok || dwRead == 0)
{
CloseHandle(pi->pipe);
return 0;
}
else
{
buf[dwRead] = 0;
printf("%s", buf);
}
goto again:
return 0; /* makes the compiler happy */
}

从利用匿名管道实现可交互式远程超级终端cmd.exe说起

为了实现
  • bobopeng
  • bobopeng
  • 2014年10月23日 13:29
  • 1589

使用CreateProcess函数实现隐秘的程序调用之二:使用匿名管道

前一篇文章已经实现了基本功能,但有一个问题,就是需要读写硬盘上的文件。如果实在不想读写文件,可以将进程启动信息中的输出重定向到一个匿名管道,再从管道中读取进程的输出即可。void CCPTFDlg::...
  • blackboyofsnp
  • blackboyofsnp
  • 2010年10月10日 12:26
  • 2604

利用匿名管道实现CMD回显

SECURITY_ATTRIBUTES sa; HANDLE hRead,hWrite;    sa.nLength = sizeof(SECURITY_ATTRIBUTES);   sa.lpSec...
  • caowei880123
  • caowei880123
  • 2011年01月11日 11:10
  • 3943

如何使用匿名管道输出重定向

VC++在多进程通讯中有一种很好的方法就是使用管道技术。对于很多的初学者来说,不知道IDE的具体原理是什么,作者也是一样,为此迷惑了很多年,也最近才弄清楚IDE是如何集成了其他的命令行软件的,比如VC...
  • kinker
  • kinker
  • 2006年02月28日 16:10
  • 1272

利用管道获取控制台程序的标准输出

1.该程序调用控制台程序hello.exe,通过管道获取到hello.exe的标准输出数据,并打印到当前程序的标准输出。 #include #include #include using n...
  • coolibin
  • coolibin
  • 2015年01月22日 21:35
  • 2183

管道和多线程

管道是内核维护的一个缓存, 它提供两个 fd, 从一个fd写入数据, 从另一个fd读出数据.  所以它是半双工的.  我在这里讨论一下如何在单进程多线程环境下使用管道. 假设一个系统里有多个生产者...
  • chengangdzzd
  • chengangdzzd
  • 2016年03月22日 20:00
  • 2621

易语言匿名管道类

  • 2015年08月25日 19:05
  • 8KB
  • 下载

匿名管道,重定向PING中的数据

#include #include void go(HWND hwnd) { char * ping = "IPCONFIG /all"; // 命令 char pbuf[102...
  • windows_nt
  • windows_nt
  • 2013年03月02日 15:32
  • 1312

Delphi 执行控制台(console)程序获取返回结果

[delphi] view plain copy  print? function GetRunConsoleResult(FileName:String;Visibili...
  • chinajobs
  • chinajobs
  • 2016年12月21日 10:53
  • 776

[Windows]_[中级]_[界面程序打开控制台输出-转发输出到控制台]

场景: 1. 开发Windows界面程序时,需要打印输出,断点在调试多线程程序有局限性,就是会干扰线程的优先顺序,看不到正确的结果,往往就是断点就没事, 没断点程序就不能正常运行了。 2. 使用动态库...
  • infoworld
  • infoworld
  • 2015年05月10日 00:54
  • 2362
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:匿名管道实现获取控制台程序输出
举报原因:
原因补充:

(最多只允许输入30个字)