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

原创 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 */
}

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

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

VC 匿名管道获取控制台程序的输出

PS:用子线程,并对输出的字符串进行拆解,效果更逼真.直接代码附解释: void CShellPingDlg::OnBnClickedBtnPing() // 窗体上按钮的BN_CLICKED事件{ ...
  • xxingup
  • xxingup
  • 2010年04月20日 14:26
  • 3121

管道技术获取控制台输出

 不知你是否用过这样的程序,他们本身并没有解压缩的功能,而是调用DOS程序PKZIP完成ZIP包的解压缩。但是在程序运行时又没有DOS控制台的窗口出现而且一切本应该在DOS下显示的信息都出现在了那个安...
  • shiwei0124
  • shiwei0124
  • 2009年09月11日 13:44
  • 1120

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

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

利用匿名管道实现CMD回显

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

windows API之控制台界面

在windows里面,用户界面包括控制台(Console)形式的和窗口(Window)形式的。这里面我们将介绍如何通过Windows API开控制Console。...
  • u013128965
  • u013128965
  • 2014年10月19日 20:41
  • 4410

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

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

通过管道获取cmd输出

#define _CRT_SECURE_NO_WARNINGS #include #include #include int GerResurt(char* cmd, char* result...
  • u012628581
  • u012628581
  • 2015年04月23日 10:17
  • 1406

C语言利用管道获取CMD命令结果

在实践中,我们有时候需要用C语言来调用cmd的命令,并得到执行的结果,这里给出一个简单的例子。#include // 描述:execmd函数执行命令,并将结果存储到result字符串数组中 // 参...
  • qq_20307987
  • qq_20307987
  • 2017年08月10日 09:38
  • 296

C++进程通信之匿名管道

匿名管道只能用来实现同一台机器上父子进程间通信,而不能实现跨网络的通信。 利用匿名管道实现父子进程通信时,需要注意:因为匿名管道没有名称,所以只能在父进程中调用Createprocess函数创建子线程...
  • hk627989388
  • hk627989388
  • 2016年12月19日 11:17
  • 1162
收藏助手
不良信息举报
您举报文章:匿名管道实现获取控制台程序输出
举报原因:
原因补充:

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