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

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

 

在程序设计中,有时候需要调用一些控制台程序并取得其在控制台上的输出,如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 */

}

 

你可能感兴趣的:(匿名管道实现获取控制台程序输出)