小女子弱问关于管道的问题

langefeizhou1983 2005-07-18 10:19:00
我们现在的工程是这样的:在vb或vc下截取现有的c或者汇编的编译器(界面dos的)的输入输出。一次来做一个win32的exe. 用到管道技术。请问各位大虾能否指点谜津。那些资料可以借鉴。小女子不胜感激:-)
...全文
222 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
humourHM 2005-07-19
  • 打赏
  • 举报
回复
(接上面)
三. 子 进 程Child
---- Child 启 动 之 后, 立 刻 创 建 一 个 新 的 线 程, 并 在 新 线 程 中 执 行 读 管 道 操 作, 利 用 读 得 的 参 数 使 主 窗 口 绘 出 形 状。 读 管 道 函 数 为:

BOOL ReadFile(
HANDLE hFile, //读入文件句柄
LPVOID lpBuffer, //读入数据缓冲区地址
DWORD nNumberOfBytesToRead, //要读入字节数量
LPDWORD lpNumberOfBytesRead, //已读入字节数地址
LPOVERLAPPED lpOverlapped ); //异步I/O结构指针

---- 首 先 从MFC 类 库 创 建 新 线 程, 使 用ClassWizard 工 具: 选 择AddClassNew, 输 入 类 名CThr, 在 基 类 列 表 框 中 选 择"CWinThread", 按 下Create 按 钮, 生 成 线 程 类CThr。 然 后 修 改 程 序 代 码, 下 面 给 出 部 分 源 程 序:

///////////////////Thr.h线程类头文件
class CThr : public CWinThread
{//operations
public:
LONG PipeThread();
void DoRead(void);
HANDLE hpipeRead;
HANDLE hThread;
DWORD dwThreadID;
int iShape;
BOOL bTerminate;
};
////////////Thr.cpp线程类实现文件
#include
CThr::CThr()
{HWND hwnd=GetActiveWindow();
//检索管道句柄
hpipeRead=GetStdHandle(STD_INPUT_HANDLE);
if(hpipeRead==INVALID_HANDLE_VALUE)
::MessageBox(hwnd,"Invalid Handle!",NULL,MB_OK);
}
BOOL CThr::InitInstance()
{ bTerminate=FALSE;
//设置线程优先权
SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
ResumeThread();
PipeThread();
return TRUE;
}
LONG CThr::PipeThread()
{ while(!bTerminate){ DoRead(); }
return 0L;
}
void CThr::DoRead(void)
{ FIGURE Figure;
DWORD dwRead;
BOOL bTest;
//读管道
bTest=ReadFile(hpipeRead,&Figure,
sizeof(Figure),&dwRead,NULL);
if(bTest){
if(Figure.iShape==ID_TERMINATE) bTerminate=TRUE;
else{ iShape=Figure.iShape;
HWND hwndMain=GetActiveWindow();
InvalidateRect(hwndMain,NULL,TRUE);
UpdateWindow(hwndMain); //更新窗口
}
}
else{ bTerminate=TRUE; }
return;
}
//////////////Childview.cpp视类实现文件
#include"global.h"
#include"thr.h"
CThr* m_pThr; //定义新线程对象
……
CChildView::CChildView()
{ m_pThr=new CThr; } //产生新线程对象
CChildView::~CChildView()
{ delete m_pThr; } //删除线程
BOOL CChildView::PreCreateWindow(CREATESTRUCT& cs)
{ m_pThr- >CreateThread();
return CView::PreCreateWindow(cs);
}
void CChildView::OnDraw(CDC* pDC)
{……
//根据所读参数绘图
Cbrush brush(RGB(0,0,0));
pDC- >SelectObject(&brush);
if(m_pThr- >iShape==ID_RECT) pDC- >Rectangle(12,45,200,178);
if(m_pThr- >iShape==ID_ELLIPSE) pDC- >Ellipse(12,45,200,178);
}

四. 结 论
---- 运 行 以 上 例 程, 在 父 进 程Parent 窗 口 中 按 一 下 鼠 标 左 键, 就 会 产 生 一 个Pipe 并 启 动 子 进 程Child, 在Parent 中 选 中 菜 单 项Rect 或Ellipse 时,Child 窗 口 中 就 会 分 别 绘 出 矩 形 和 椭 圆, 选 中Terminate 时, 就 会 中 断 通 信。 以 上 介 绍 的 是 匿 名 管 道, 若 要 增 加 通 信 的 灵 活 性 还 可 采 用 命 名 管 道NamedPipe。
humourHM 2005-07-19
  • 打赏
  • 举报
回复
我也贴个简单的列子(很久以前下的),希望对你有帮助
VC++ 环 境 下 利 用 管 道 和 线 程 实 现 进 程 间 通 信
电 子 部 第 二 十 八 研 究 所 一 部
张 杰
一. 引 言
---- Windows95 作 为 一 个 优 先 多 任 务 操 作 系 统, 其 重 要 特 征 之 一 是 引 入 了 多 进 程 和 多 线 程 机 制。 其 中 每 个 进 程 都 有 私 有 的 虚 拟 地 址 空 间, 可 以 创 建 多 个 线 程, 每 个 线 程 被 分 配 一 个 时 间 片, 且 当 前 执 行 的 线 程 在 其 时 间 片 耗 尽 时 挂 起, 让 其 他 线 程 运 行。 由 于 各 时 间 片 很 小, 所 以 这 时 看 起 来 就 象 是 多 个 线 程 在 同 时 工 作。 我 们 这 里 将 会 在 子 进 程Child 中 产 生 一 个 工 作 线 程, 它 只 在 后 台 处 理 任 务, 而 不 会 影 响 程 序 的 使 用。

---- 有 时 用 户 运 行 的 进 程 之 间 毫 无 关 系, 但 是 进 程 之 间 信 息 的 交 换 则 能 产 生 协 作 效 果, 这 样 就 可 以 完 成 某 些 单 个 进 程 所 不 能 完 成 的 任 务。Windows95 可 以 使 用 多 种 通 信 手 段, 包 括 剪 贴 板、DDE、OLE, 而 且 还 增 加 了 一 些 新 的 手 段, 其 中 管 道 是 用 来 在 不 同 程 序 之 间 交 换 信 息 的 另 一 个 新 的 简 便 的 通 信 机 制。 与 其 它 手 段 不 同, 管 道 没 有 正 式 的 标 准 或 协 议 来 控 制 信 息 传 递, 所 以 与DDE 会 话 这 样 的 机 制 相 比, 管 道 更 易 于 使 用、 更 加 灵 活。 管 道 实 际 上 是 一 段 共 享 内 存 区, 进 程 把 共 享 消 息 放 在 那 里。 因 为 管 道 专 用 于 进 程 间 的 通 信, 所 以Win32API 提 供 了 一 组 函 数 以 方 便 信 息 交 换。

---- 本 文 我 们 将 在VC++4.1 环 境 下 介 绍 一 个 父 进 程 和 其 子 进 程 的 通 信 实 例。 在 父 进 程Parent 窗 口 中 按 一 下 鼠 标 左 键, 就 会 产 生 一 个Pipe 和 启 动 子 进 程Child, 并 从Pipe 一 端 发 送 信 息, 同 时Child 启 动 后 会 创 建 一 个 工 作 线 程, 专 门 用 来 从 管 道 的 另 一 端 读 入 数 据。 通 过 父 进 程 菜 单 项 的 控 制 来 改 变 图 形 形 状 参 数, 并 传 给Child 使 之 在 自 己 的 窗 口 中 绘 出 响 应 的 图 形。 下 面 分 别 就 父 进 程Parent 和 子 进 程Child 来 进 行 说 明。

二. 父 进 程Parent
---- 在 父 进 程Parent 中, 我 们 将 创 建 管 道 和 启 动 子 进 程。 首 先 说 明 几 个 相 关 函 数。 创 建 进 程 函 数:

BOOL CreateProcess(
LPCTSTR lpApplicationName, //应用模式指针
LPTSTR lpCommandLine, //命令行字符串
LPSECURITY_ATTRIBUTES lpProcessAttributes,
//进程安全性指针
LPSECURITY_ATTRIBUTES lpThreadAttributes,
//主线程安全性指针
BOOL bInheritHandles, //是否继承句柄
DWORD dwCreationFlags, //进程类型与优先级
LPVOID lpEnvironment, //环境块指针
LPCTSTR lpCurrentDirectory, //当前目录
LPSTARTUPINFO lpStartupInfo,
// STARTUPINFO结构指针
LPPROCESS_INFORMATION
lpProcessInformation //); //新进程信息
创建管道函数:
BOOL CreatePipe(
PHANDLE hReadPipe, //读句柄变量地址
PHANDLE hWritePipe, //写句柄变量地址
LPSECURITY_ATTRIBUTES lpPipeAttributes,
//安全属性指针
DWORD nSize ); //管道缓冲区大小
写管道函数:
BOOL WriteFile(
HANDLE hFile, //写入文件句柄
LPCVOID lpBuffer, //写入数据指针
DWORD nNumberOfBytesToWrite, //要写入字节数量
LPDWORD lpNumberOfBytesWritten, //已写入字节数地址
LPOVERLAPPED lpOverlapped ); //异步I/O结构指针

---- 下 面 从 编 程 角 度 讨 论 其 实 现 步 骤:

---- 1. 利 用AppWizard(EXE) 产 生Parent 应 用 框 架, 然 后 再 文 件Parentview.cpp 头 部 加 入#include, 其 中 文 件global.h 定 义 了 两 个 进 程 用 于 相 互 通 信 的 结 构 和 常 量 值。 代 码 如 下:

//////////////////Global.h共享变量头文件
typedef struct Figure
{ int iShape; //图形控制参数
} FIGURE,*PFIGURE;
#define ID_RECT 32771
#define ID_ELLIPSE 32772
#define ID_TERMINATE 32773

---- 2. 使 用ClassWizard 工 具: 选 择 对 应 于CParentView 类 的 消 息WM_LBUTTONDOWN, 选 择AddFunction 键, 增 加 函 数OnLButtonDown()。 在 主 菜 单 资 源 中 加 入Rect、Ellipse、Terminate 菜 单 项,ID 分 别 为IDC_RECT、IDR_ELLIPSE、IDR_TERMINATE, 并 在ClassWizard 中 加 入 相 应 函 数。

在文件Parentview.h中加入如下代码:
public:
BOOL SendCommand(); //发送信息
HANDLE hProcess; //进程句柄
HANDLE hpipeWrite; //管道写句柄
FIGURE figure;
文件Parentview.cpp中部分程序代码如下:
//////////////////////Parentview.cpp视类实现文件
void CParnetView::OnLButtonDown(UINT nFlags,Cpoint piont)
{ SECURITY_ATTRIBUTES sa; //安全性结构
STARTUPINFO sui; //子进程窗口属性结构
PROCESS_INFORMATION pi; //子进程信息
BOOL bTest;
HANDLE hpipeRead; //管道写句柄
//填充安全性结构使句柄被继承
sa.nLength=sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor=NULL;
sa.bInheritHandle=TRUE;
bTest=CreatePipe(&hpipeRead,
&hpipeWrite,&sa,0); //创建管道
if(!bTest){
MessageBox("CreatePipe failed!",NULL,MB_OK);
return;
}
//修改写句柄,使不被继承
bTest=DuplicateHandle(GetCurrentProcess(),
hpipeWrite, GetCurrentProcess(),
NULL,0,FALSE,DUPLICATE_SAME_ACCESS);
if(!bTest){
MessageBox("Dup Handle failed!",NULL,MB_OK);
CloseHandle(hpipeRead);
CloseHandle(hpipeWrite);
return;
}
//填充进程启动信息
memset(&sui,0,sizeof(STARTUPINFO));
sui.cb =sizeof(STARTUPINFO);
sui.dwFlags=STARTF_USESTDHANDLES;
sui.hStdInput=hpipeRead;
sui.hStdOutput=GetStdHandle(STD_OUTPUT_HANDLE);
sui.hStdError=GetStdHandle(STD_ERROR_HANDLE);
//创建子进程Child
bTest=CreateProcess(NULL,"child.exe",NULL,
NULL,TRUE,0,NULL,NULL,&sui,&pi);
if(!bTest){
MessageBox("CreateProcess failed!",NULL,MB_OK);
CloseHandle(hpipeWrite); //删除管道
}
else{ hProcess=pi.hProcess;
CloseHandle(pi.hThread);
figure.iShape=ID_RECT;
SendCommand();
}
CloseHandle(hpipeRead);
return;
Cview::OnLButtonDown(nFlags,point);
}
void CParentView::OnRect()
{ figure.iShape=ID_RECT;
SendCommand();
}
void CParentView::OnEllipse()
{ figure.iShape=ID_ELLIPSE;
SendCommand();
}
BOOL CParentView::SendCommand()
{ BOOL bTest;
DWORD dwWritten;
//写管道
bTest=WriteFile(hpipeWrite,&figure,
sizeof(FIGURE),&dwWritten,NULL);
if(!bTest){
MessageBox("WriteFile failed!",NULL,MB_OK);
if((!bTest)||(figure.iShape==ID_TERMINATE)){
CloseHandle(hProcess);
hProcess=NULL;
CloseHandle(hpipeWrite);
}
} return (bTest);
}
void CParentView::OnTerminate()
{ figure.iShape=ID_TERMINATE;
SendCommand();
}
linur 2005-07-19
  • 打赏
  • 举报
回复
嘿,很久前做了和你一样的事, 就是用重定向技术啦,下面是微软写的
The following is the code for the parent process. It takes a single command-line argument: the name of a text file.


#include <stdio.h>
#include <windows.h>

#define BUFSIZE 4096

HANDLE hChildStdinRd, hChildStdinWr, hChildStdinWrDup,
hChildStdoutRd, hChildStdoutWr, hChildStdoutRdDup,
hInputFile, hStdout;

BOOL CreateChildProcess(VOID);
VOID WriteToPipe(VOID);
VOID ReadFromPipe(VOID);
VOID ErrorExit(LPTSTR);
VOID ErrMsg(LPTSTR, BOOL);

DWORD main(int argc, char *argv[])
{
SECURITY_ATTRIBUTES saAttr;
BOOL fSuccess;

// Set the bInheritHandle flag so pipe handles are inherited.

saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr.bInheritHandle = TRUE;
saAttr.lpSecurityDescriptor = NULL;

// Get the handle to the current STDOUT.

hStdout = GetStdHandle(STD_OUTPUT_HANDLE);

// Create a pipe for the child process's STDOUT.

if (! CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0))
ErrorExit("Stdout pipe creation failed\n");

// Create noninheritable read handle and close the inheritable read
// handle.

fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdoutRd,
GetCurrentProcess(), &hChildStdoutRdDup , 0,
FALSE,
DUPLICATE_SAME_ACCESS);
if( !fSuccess )
ErrorExit("DuplicateHandle failed");
CloseHandle(hChildStdoutRd);

// Create a pipe for the child process's STDIN.

if (! CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0))
ErrorExit("Stdin pipe creation failed\n");

// Duplicate the write handle to the pipe so it is not inherited.

fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdinWr,
GetCurrentProcess(), &hChildStdinWrDup, 0,
FALSE, // not inherited
DUPLICATE_SAME_ACCESS);
if (! fSuccess)
ErrorExit("DuplicateHandle failed");

CloseHandle(hChildStdinWr);

// Now create the child process.

fSuccess = CreateChildProcess();
if (! fSuccess)
ErrorExit("Create process failed");

// Get a handle to the parent's input file.

if (argc == 1)
ErrorExit("Please specify an input file");

hInputFile = CreateFile(argv[1], GENERIC_READ, 0, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);

if (hInputFile == INVALID_HANDLE_VALUE)
ErrorExit("CreateFile failed\n");

// Write to pipe that is the standard input for a child process.

WriteToPipe();

// Read from pipe that is the standard output for child process.

ReadFromPipe();

return 0;
}

BOOL CreateChildProcess()
{
PROCESS_INFORMATION piProcInfo;
STARTUPINFO siStartInfo;
BOOL bFuncRetn = FALSE;

// Set up members of the PROCESS_INFORMATION structure.

ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );

// Set up members of the STARTUPINFO structure.

ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
siStartInfo.cb = sizeof(STARTUPINFO);
siStartInfo.hStdError = hChildStdoutWr;
siStartInfo.hStdOutput = hChildStdoutWr;
siStartInfo.hStdInput = hChildStdinRd;
siStartInfo.dwFlags |= STARTF_USESTDHANDLES;

// Create the child process.

bFuncRetn = CreateProcess(NULL,
"child", // command line
NULL, // process security attributes
NULL, // primary thread security attributes
TRUE, // handles are inherited
0, // creation flags
NULL, // use parent's environment
NULL, // use parent's current directory
&siStartInfo, // STARTUPINFO pointer
&piProcInfo); // receives PROCESS_INFORMATION

if (bFuncRetn == 0)
ErrorExit("CreateProcess failed");
else
{
CloseHandle(piProcInfo.hProcess);
CloseHandle(piProcInfo.hThread);
return bFuncRetn;
}
}

VOID WriteToPipe(VOID)
{
DWORD dwRead, dwWritten;
CHAR chBuf[BUFSIZE];

// Read from a file and write its contents to a pipe.

for (;;)
{
if (! ReadFile(hInputFile, chBuf, BUFSIZE, &dwRead, NULL) ||
dwRead == 0) break;
if (! WriteFile(hChildStdinWrDup, chBuf, dwRead,
&dwWritten, NULL)) break;
}

// Close the pipe handle so the child process stops reading.

if (! CloseHandle(hChildStdinWrDup))
ErrorExit("Close pipe failed");
}

VOID ReadFromPipe(VOID)
{
DWORD dwRead, dwWritten;
CHAR chBuf[BUFSIZE];

// Close the write end of the pipe before reading from the
// read end of the pipe.

if (!CloseHandle(hChildStdoutWr))
ErrorExit("CloseHandle failed");

// Read output from the child process, and write to parent's STDOUT.

for (;;)
{
if( !ReadFile( hChildStdoutRdDup, chBuf, BUFSIZE, &dwRead,
NULL) || dwRead == 0) break;
if (! WriteFile(hStdout, chBuf, dwRead, &dwWritten, NULL))
break;
}
}

VOID ErrorExit (LPTSTR lpszMessage)
{
fprintf(stderr, "%s\n", lpszMessage);
ExitProcess(0);
}

The following is the code for the child process. It uses the inherited handles for STDIN and STDOUT to access the pipe created by the parent. The parent process reads from its input file and writes the information to a pipe. The child receives text through the pipe using STDIN and writes to the pipe using STDOUT. The parent reads from the read end of the pipe and displays the information to its STDOUT.


#include <windows.h>
#define BUFSIZE 4096

VOID main(VOID)
{
CHAR chBuf[BUFSIZE];
DWORD dwRead, dwWritten;
HANDLE hStdin, hStdout;
BOOL fSuccess;

hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
hStdin = GetStdHandle(STD_INPUT_HANDLE);
if ((hStdout == INVALID_HANDLE_VALUE) ||
(hStdin == INVALID_HANDLE_VALUE))
ExitProcess(1);

for (;;)
{
// Read from standard input.
fSuccess = ReadFile(hStdin, chBuf, BUFSIZE, &dwRead, NULL);
if (! fSuccess || dwRead == 0)
break;

// Write to standard output.
fSuccess = WriteFile(hStdout, chBuf, dwRead, &dwWritten, NULL);
if (! fSuccess)
break;
}
}

AntonlioX 2005-07-18
  • 打赏
  • 举报
回复
呵呵 只能连贴3个帖子 您继续吧 哈哈
idAnts 2005-07-18
  • 打赏
  • 举报
回复
你还没帖全呢,嘿嘿
AntonlioX 2005-07-18
  • 打赏
  • 举报
回复
我写的一个gui程序控制cmd的控制台:
线程函数:
char cmdbuffer[1024];
HANDLE hReadPipe;
HANDLE hReadPipe2;
HANDLE hWritePipe;
HANDLE hWritePipe2;

DWORD __stdcall ThreadFun(void *pVoid)
{
HWND hwnd = *((HWND *)pVoid);

SECURITY_ATTRIBUTES sat;
STARTUPINFO startupinfo;
PROCESS_INFORMATION pinfo;
BYTE buffer[1024];
DWORD byteRead;
CString rString;


sat.nLength=sizeof(SECURITY_ATTRIBUTES);
sat.bInheritHandle=true;
sat.lpSecurityDescriptor=NULL;
if(!CreatePipe(&hReadPipe,&hWritePipe,&sat,NULL))
{
MessageBox(NULL,"Create Pipe Error!","error!",MB_OK);
return 0;
}
if(!CreatePipe(&hReadPipe2,&hWritePipe2,&sat,NULL))
{
MessageBox(NULL,"Create Pipe2 Error!","error!",MB_OK);
return 0;
}
startupinfo.cb=sizeof(STARTUPINFO);
GetStartupInfo(&startupinfo);
startupinfo.hStdError=hWritePipe;
startupinfo.hStdOutput=hWritePipe;
startupinfo.hStdInput=hReadPipe2;
startupinfo.dwFlags=STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
startupinfo.wShowWindow=SW_HIDE;
if(!CreateProcess(NULL,"c:\\winnt\\system32\\cmd.exe",NULL, NULL, TRUE, NULL, NULL, NULL,&startupinfo,&pinfo))
{
MessageBox(NULL,"create process error!","Error!",MB_OK);
return 0;
}
CloseHandle(hWritePipe);
CloseHandle(hReadPipe2);

while(true)
{
RtlZeroMemory(buffer,1024);
if(ReadFile(hReadPipe,buffer,1023,&byteRead,NULL)==NULL)
break;
::SendMessage(GetDlgItem(hwnd,IDC_MSG),EM_SETSEL,-1,0);
::SendMessage(GetDlgItem(hwnd,IDC_MSG),EM_REPLACESEL,false,(long)buffer);
}
CloseHandle(hReadPipe);
CloseHandle(hWritePipe2);
return 0;
}
AntonlioX 2005-07-18
  • 打赏
  • 举报
回复
再给你一个 英文的资料吧


I have the thought of redirecting output of WIN32 console programs to a pipe or a file long ago, but I don't know to do at all at first, finally I searched through Microsoft MSDN and found a way, the code pasted below was copied from MSDN sample code except some changes in function CreateChildProcess(), where I stressed in the code.
In the demo source, I redirect the stdout of CMD.exe to a pipe and start a thread to read from this pipe, then all that CMD.EXE output was redirected to the pipe where I am reading.


BOOL CShellView::CreateShellRedirect()
{
SECURITY_ATTRIBUTES saAttr;
BOOL fSuccess;

// Set the bInheritHandle flag so pipe handles are inherited.
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr.bInheritHandle = TRUE;
saAttr.lpSecurityDescriptor = NULL;

// The steps for redirecting child process's STDOUT:
// 1. Save current STDOUT, to be restored later.
// 2. Create anonymous pipe to be STDOUT for child process.
// 3. Set STDOUT of the parent process to be write handle to
// the pipe, so it is inherited by the child process.
// 4. Create a noninheritable duplicate of the read handle and
// close the inheritable read handle.

// Save the handle to the current STDOUT.
hSaveStdout = GetStdHandle(STD_OUTPUT_HANDLE);

// Create a pipe for the child process's STDOUT.
if( !CreatePipe( &hChildStdoutRd, &hChildStdoutWr, &saAttr, 0) )
{
TRACE0( _T("Stdout pipe creation failed\n") );
return FALSE;
}

// Set a write handle to the pipe to be STDOUT.
if( !SetStdHandle(STD_OUTPUT_HANDLE, hChildStdoutWr) )
{
TRACE0( _T("Redirecting STDOUT failed\n") );
return FALSE;
}

// Create noninheritable read handle and close the inheritable read handle.
fSuccess = DuplicateHandle( GetCurrentProcess(), hChildStdoutRd,
GetCurrentProcess(), &hChildStdoutRdDup ,
0, FALSE,
DUPLICATE_SAME_ACCESS );
if( !fSuccess )
{
TRACE0( _T("DuplicateHandle failed\n") );
return FALSE;
}
CloseHandle( hChildStdoutRd );

// The steps for redirecting child process's STDIN:
// 1. Save current STDIN, to be restored later.
// 2. Create anonymous pipe to be STDIN for child process.
// 3. Set STDIN of the parent to be the read handle to the
// pipe, so it is inherited by the child process.
// 4. Create a noninheritable duplicate of the write handle,
// and close the inheritable write handle.

// Save the handle to the current STDIN.
hSaveStdin = GetStdHandle(STD_INPUT_HANDLE);

// Create a pipe for the child process's STDIN.
if( !CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0) )
{
TRACE0( _T("Stdin pipe creation failed\n") );
return FALSE;
}
// Set a read handle to the pipe to be STDIN.
if( !SetStdHandle(STD_INPUT_HANDLE, hChildStdinRd) )
{
TRACE0( _T("Redirecting Stdin failed\n") );
return FALSE;
}
// Duplicate the write handle to the pipe so it is not inherited.
fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdinWr,
GetCurrentProcess(), &hChildStdinWrDup,
0, FALSE, // not inherited
DUPLICATE_SAME_ACCESS );
if( !fSuccess )
{
TRACE0( _T("DuplicateHandle failed\n") );
return FALSE;
}
CloseHandle(hChildStdinWr);

// Now create the child process.
if( !CreateChildProcess(dwProcessId) )
{
TRACE0( _T("CreateChildProcess failed\n") );
return FALSE;
}
// After process creation, restore the saved STDIN and STDOUT.
if( !SetStdHandle(STD_INPUT_HANDLE, hSaveStdin) )
{
TRACE0( _T("Re-redirecting Stdin failed\n") );
return FALSE;
}
if( !SetStdHandle(STD_OUTPUT_HANDLE, hSaveStdout) )
{
TRACE0( _T("Re-redirecting Stdout failed\n") );
return FALSE;
}
m_pReadThread =
fxBeginThread( (AFX_THREADPROC)ReadPipeThreadProc,(LPVOID)this );
if( !m_pReadThread )
{
TRACE0( _T("Cannot start read-redirect thread!\n") );
return FALSE;
}
return TRUE;
}

BOOL CShellView::CreateChildProcess(DWORD& dwProcessId)
{
PROCESS_INFORMATION piProcInfo;
STARTUPINFO siStartInfo;

// Set up members of STARTUPINFO structure.
ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
siStartInfo.cb = sizeof(STARTUPINFO);
/////////////////////////////////////////
/*
Note here the
dwFlags should be STARTF_USESTDHANDLES, which is descripted in WIN32 API
document, but this was
omitted in MSDN sample
*/
siStartInfo.dwFlags = STARTF_USESTDHANDLES;
siStartInfo.hStdInput = hChildStdinRd;
siStartInfo.hStdOutput = hChildStdoutWr;
siStartInfo.hStdError = hChildStdoutWr;

///////////////////////////////////////////////////
TCHAR shellCmd[_MAX_PATH];
if( !GetEnvironmentVariable(_T("ComSpec"), shellCmd, _MAX_PATH) )
return FALSE;
#ifdef _UNICODE
_tcscat( shellCmd, _T(" /U") );
#else
_tcscat( shellCmd, _T(" /A") );
#endif
// Create the child process.
BOOL ret = CreateProcess( NULL,
shellCmd, // applicatin name
NULL, // process security attributes
NULL, // primary thread security attributes
TRUE, // handles are inherited
DETACHED_PROCESS, // creation flags
NULL, // use parent's environment
NULL, // use parent's current directory
&siStartInfo, // STARTUPINFO pointer
&piProcInfo); // receives PROCESS_INFORMATION
if( ret )
dwProcessId = piProcInfo.dwProcessId;
return ret;
}
langefeizhou1983 2005-07-18
  • 打赏
  • 举报
回复
我们现在的工作是:
在VB中调用C语言和汇编语言的编译器可执行文件,作出一个集成开发环境.
我们要在自己设计的集成开发环境编辑器重输入C或汇编语言的源程序,然后调用前面说过的可执行文件,完成对源程序的编译,连接以及运行.
请问如何在VB 中调用其他可执行文件以及如何通过管道截取输入输出流?将有效的信息反馈到我们的集成开发环境上面来?
AntonlioX 2005-07-18
  • 打赏
  • 举报
回复
VC++下对匿名管道的编程实现

概述

  管道(Pipe)实际是用于进程间通信的一段共享内存,创建管道的进程称为管道服务器,连接到一个管道的进程为管道客户机。一个进程在向管道写入数据后,另一进程就可以从管道的另一端将其读取出来。匿名管道(Anonymous Pipes)是在父进程和子进程间单向传输数据的一种未命名的管道,只能在本地计算机中使用,而不可用于网络间的通信。

  匿名管道实施细则

  匿名管道由CreatePipe()函数创建,该函数在创建匿名管道的同时返回两个句柄:管道读句柄和管道写句柄。CreatePipe()的函数原型为:  

  BOOL CreatePipe(PHANDLE hReadPipe, // 指向读句柄的指针

   PHANDLE hWritePipe, // 指向写句柄的指针

   LPSECURITY_ATTRIBUTES lpPipeAttributes, // 指向安全属性的指针

   DWORD nSize // 管道大小

  );

  通过hReadPipe和hWritePipe所指向的句柄可分别以只读、只写的方式去访问管道。在使用匿名管道通信时,服务器进程必须将其中的一个句柄传送给客户机进程。句柄的传递多通过继承来完成,服务器进程也允许这些句柄为子进程所继承。除此之外,进程也可以通过诸如DDE或共享内存等形式的进程间通信将句柄发送给与其不相关联的进程。

  在调用CreatePipe()函数时,如果管道服务器将lpPipeAttributes 指向的SECURITY_ATTRIBUTES数据结构的数据成员bInheritHandle设置为TRUE,那么CreatePipe()创建的管道读、写句柄将会被继承。管道服务器可调用DuplicateHandle()函数改变管道句柄的继承。管道服务器可以为一个可继承的管道句柄创建一个不可继承的副本或是为一个不可继承的管道句柄创建一个可继承的副本。CreateProcess()函数还可以使管道服务器有能力决定子进程对其可继承句柄是全部继承还是不继承。

  在生成子进程之前,父进程首先调用Win32 API SetStdHandle()使子进程、父进程可共用标准输入、标准输出和标准错误句柄。当父进程向子进程发送数据时,用SetStdHandle()将管道的读句柄赋予标准输入句柄;在从子进程接收数据时,则用SetStdHandle()将管道的写句柄赋予标准输出(或标准错误)句柄。然后,父进程可以调用进程创建函数CreateProcess()生成子进程。如果父进程要发送数据到子进程,父进程可调用WriteFile()将数据写入到管道(传递管道写句柄给函数),子进程则调用GetStdHandle()取得管道的读句柄,将该句柄传入ReadFile()后从管道读取数据。

  如果是父进程从子进程读取数据,那么由子进程调用GetStdHandle()取得管道的写入句柄,并调用WriteFile()将数据写入到管道。然后,父进程调用ReadFile()从管道读取出数据(传递管道读句柄给函数)。

  在用WriteFile()函数向管道写入数据时,只有在向管道写完指定字节的数据后或是在有错误发生时函数才会返回。如管道缓冲已满而数据还没有写完,WriteFile()将要等到另一进程对管道中数据读取以释放出更多可用空间后才能够返回。管道服务器在调用CreatePipe()创建管道时以参数nSize对管道的缓冲大小作了设定。

  匿名管道并不支持异步读、写操作,这也就意味着不能在匿名管道中使用ReadFileEx()和WriteFileEx(),而且ReadFile()和WriteFile()中的lpOverLapped参数也将被忽略。匿名管道将在读、写句柄都被关闭后退出,也可以在进程中调用CloseHandle()函数来关闭此句柄。



总的来说,匿名管道程序是比较简单的。在下面将要给出的程序示例中,将由父进程(管道服务器)创建一个子进程(管道客户机),子进程回见个其全部的标准输出发送到匿名管道中,父进程再从管道读取数据,一直到子进程关闭管道的写句柄。其中,匿名管道服务器程序的实现清单如下:  

  STARTUPINFO si;

  PROCESS_INFORMATION pi;

  char ReadBuf[100];

  DWORD ReadNum;

  HANDLE hRead; // 管道读句柄

  HANDLE hWrite; // 管道写句柄

  BOOL bRet = CreatePipe(&hRead, &hWrite, NULL, 0); // 创建匿名管道

  if (bRet == TRUE)

   printf("成功创建匿名管道!\n");

  else

   printf("创建匿名管道失败,错误代码:%d\n", GetLastError());

   // 得到本进程的当前标准输出

   HANDLE hTemp = GetStdHandle(STD_OUTPUT_HANDLE);

   // 设置标准输出到匿名管道

   SetStdHandle(STD_OUTPUT_HANDLE, hWrite);

   GetStartupInfo(&si); // 获取本进程的STARTUPINFO结构信息

   bRet = CreateProcess(NULL, "Client.exe", NULL, NULL, TRUE, NULL, NULL, NULL, &si, &pi); // 创建子进程

   SetStdHandle(STD_OUTPUT_HANDLE, hTemp); // 恢复本进程的标准输出

   if (bRet == TRUE) // 输入信息

    printf("成功创建子进程!\n");

   else

    printf("创建子进程失败,错误代码:%d\n", GetLastError());

    CloseHandle(hWrite); // 关闭写句柄

    // 读管道直至管道关闭

    while (ReadFile(hRead, ReadBuf, 100, &ReadNum, NULL))

    {

     ReadBuf[ReadNum] = '\0';

     printf("从管道[%s]读取%d字节数据\n", ReadBuf, ReadNum);

    }

    if (GetLastError() == ERROR_BROKEN_PIPE) // 输出信息

     printf("管道被子进程关闭\n");

    else

     printf("读数据错误,错误代码:%d\n", GetLastError());

  在本示例中,将当前进程的标准输出设置为使用匿名管道,再创建子进程,子进程将继承父进程的标准输出,然后再将父进程的标准输出恢复为其初始状态。于是父进程便可从管道读取数据,直到有错误发生或关闭管道写入端的所有句柄。创建的子进程只是向标准输出和标准错误发送一些文本信息,其中发送给标准输出的文本将重定向输出到管道,发送给标准错误的文本将不改变输出。下面给出子进程的实现代码:  

  int main(int argc, char* argv[])

  {

   for (int i = 0; i < 100; i++= // 发送一些数据到标准输出和标准错误

   {

    printf("i = %d\n", i); // 打印提示

    cout << "标准输出:" << i << endl; // 打印到标准输出

    cerr << "标准错误:" << i << endl; // 打印到标准错误

   }
   return 0;

  }  

16,550

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Creator Browser
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧