调用一个控制台程序并取得其输出(PIPE)
来源:互联网 发布:淘宝pc端的海报尺寸 编辑:程序博客网 时间:2024/04/29 20:26
在程序设计中,有时候需要调用一些控制台程序并取得其在控制台上的输出,如VS的IDE就调用了cl.exe、link.exe等控制台的程序,并可将这些程序的输出在IDE中显示出来。
曾经很迷惑这个功能的实现,直到有一天看到下面的参考代码才恍然大悟,原来一切都这么简单,只不过用了CreatePipe、CreateProcess、ReadFile寥寥几个函数而已。特此记下以供参考。
#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
typedef struct {
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, /* Module name. */
cmdline, /* Command line. */
NULL, /* Process handle not inheritable. */
NULL, /* Thread handle not inheritable. */
TRUE, /* yes, inherit handles. */
DETACHED_PROCESS, /* No console for you. */
NULL, /* Use parent's environment block. */
NULL, /* Use parent's starting directory. */
&si, /* Pointer to STARTUPINFO structure. */
&pi); /* Pointer to PROCESS_INFORMATION structure. */
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;
}
纏ar 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 */
}
- 调用一个控制台程序并取得其输出(PIPE)
- 调用一个控制台程序并取得其输出(PIPE)
- 调用一个控制台程序并取得其输出(PIPE)
- 调用一个控制台程序并取得其输出
- .Net ( C# ) 调用控制台程序并取得输出结果
- 调用控制台程序,并实施获取控制台输出文字
- 调用控制台应用程序并获得程序的输出信息
- C# 调用控制台程序,并获取输出写入文件
- c调用程序并得到其输出的方法
- C# - 调用控制台程序并取回控制台程序的输出结果
- 定义一个不规整的二维数组,并将其从控制台输出
- c# 调用控制台程序并传参 获取控制台输出(解释器的前台处理)
- c# 调用控制台程序并传参 获取控制台输出(解释器的前台处理)
- c# 调用控制台程序并传参 获取控制台输出(解释器的前台处理)
- C#中调用消息对话框,并取得其返回值
- 调用消息对话框,并取得其返回值
- C#中调用消息对话框,并取得其返回值
- C#启动控制台程序并实时输出
- 欢迎访问我的baidu空间
- baidu分词算法研究一
- 在 Ubuntu 7.10 上安装 Compiz Fusion
- baidu分词算法研究二
- baidu分词算法研究三
- 调用一个控制台程序并取得其输出(PIPE)
- ADODB.STREAM组件方法和属性
- 了解SQL Server锁争用:NOLOCK 和 ROWLOCK 的秘密
- Excel File to Oracle data.
- 在asp.net发邮件
- 提高查询速度方法总结
- 小技巧--textbox的滚动条保持在最后
- 组合 MinGW 与 wxWidgets环境
- struts2.0在action里获得servlet对象方法