title: 重定向控制台程序的输入输出
author: Love02xp
date: 2019-12-12 05:55:42
category: [编程代码]
tags: [代码,VC6]
利用管道和createprocess
#include <windows.h>
#include <tchar.h>
#include <iostream>
using namespace std;
BOOL WriteToPipe();
// 读出stdout
BOOL ReadFromPipe();
//定义句柄: 构成stdin管道的两端句柄
HANDLE hStdInRead; //子进程用的stdin的读入端
HANDLE hStdInWrite; //主程序用的stdin的读入端
//定义句柄: 构成stdout管道的两端句柄
HANDLE hStdOutRead; ///主程序用的stdout的读入端
HANDLE hStdOutWrite; ///子进程用的stdout的写入端
//定义一个用于产生子进程的STARTUPINFO结构体 (定义见CreateProcess,函数说明)
STARTUPINFO siStartInfo;
//定义一个用于产生子进程的PROCESS_INFORMATION结构体 (定义见CreateProcess,函数说明)
PROCESS_INFORMATION piProcInfo;
void main()
{
//产生一个用于stdin的管道,得到两个HANDLE: hStdInRead用于子进程读出数据,hStdInWrite用于主程序写入数据
//其中saAttr是一个STARTUPINFO结构体,定义见CreatePipe函数说明
SECURITY_ATTRIBUTES saAttr = {0};
saAttr.nLength = sizeof(saAttr);
saAttr.bInheritHandle = TRUE;
if (!CreatePipe(&hStdInRead, &hStdInWrite, &saAttr, 0))
return;
//产生一个用于stdout的管道,得到两个HANDLE: hStdInRead用于主程序读出数据,hStdInWrite用于子程序写入数据
if (!CreatePipe(&hStdOutRead, &hStdOutWrite, &saAttr, 0))
return;
//对STARTUPINFO结构体赋值,对stdin,stdout的Handle设置为刚才得到的管道HANDLE
ZeroMemory(&siStartInfo, sizeof(STARTUPINFO));
siStartInfo.cb = sizeof(STARTUPINFO);
siStartInfo.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; //允许设置showwindow和设置新进程的输入输出句柄参数
siStartInfo.hStdOutput = hStdOutWrite; //意思是:子进程的stdout输出到hStdOutWrite
siStartInfo.hStdError = hStdOutWrite; //意思是:子进程的stderr输出到hStdErrWrite
siStartInfo.hStdInput = hStdInRead;
//CreateProcess()中使用了CREATE_NEW_CONSOLE后, 可以去掉下面这两句注释
//siStartInfo.wShowWindow = SW_SHOW;
//siStartInfo.lpTitle = "新进程标题";
TCHAR CommandLine[] = _T("/c ping 127.0.0.1"); //
// 产生子进程,具体参数说明见CreateProcess函数
BOOL bSuccess = CreateProcess("C:\\Windows\\System32\\cmd.exe",
CommandLine, // 子进程的命令行
NULL, // process security attributes
NULL, // primary thread security attributes
TRUE, // handles are inherited
CREATE_NO_WINDOW, // creation flags 如果想新进程显示窗口, 可以设置CREATE_NEW_CONSOLE
NULL, // use parent's environment
NULL, // use parent's current directory
&siStartInfo, // STARTUPINFO pointer
&piProcInfo); // receives PROCESS_INFORMATION
//如果失败,退出
if (!bSuccess) return;
//然后,就可以读写管道了
//写入stdin,具体代码在一个WriteToPipe函数中
WriteToPipe();
DWORD process_exit_code = 0;
//不断子检测进程有否结束
while (GetExitCodeProcess(piProcInfo.hProcess, &process_exit_code))
{
//读stdout,stderr
ReadFromPipe();
//如果子进程结束,退出循环
if (process_exit_code != STILL_ACTIVE) break;
}
::CloseHandle(hStdOutWrite);
::CloseHandle(hStdInRead);
::CloseHandle(piProcInfo.hProcess);
::CloseHandle(piProcInfo.hThread);
system("pause");
}
//写入stdin
BOOL WriteToPipe()
{
// 本例子中这样写入参数 没有用
DWORD dwWritten;
BOOL bSuccess = FALSE;
CHAR in_buffer[100] = "/c ping 127.0.0.1";
//用WriteFile,从hStdInWrite写入数据,数据在in_buffer中,长度为dwSize
bSuccess = WriteFile(hStdInWrite, in_buffer, 100, &dwWritten, NULL);
return bSuccess;
}
// 读出stdout
BOOL ReadFromPipe()
{
char out_buffer[4096] = { 0 };
DWORD dwRead;
BOOL bSuccess = FALSE;
//用WriteFile,从hStdOutRead读出子进程stdout输出的数据,数据结果在out_buffer中,长度为dwRead
bSuccess = ReadFile(hStdOutRead, out_buffer, 4096, &dwRead, NULL);
if ((bSuccess) && (dwRead != 0)) //如果成功了,且长度>0
{
// 此处加入你自己的代码
// 比如:将数据写入文件或显示到窗口中
cout << endl << "```-得到的消息是```" << endl << out_buffer;
}
return bSuccess;
}
运行截图--