管道怎么搞啊?

CyDev 2005-07-14 10:13:51
我要搞个在线杀毒程序 使用别人的杀毒引擎 命令行的 调用该引擎来杀毒 但是将其结果用图形界面显示 怎么搞啊? 听说需要用管道来搞。谁能给个例子啊
...全文
83 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
AntonlioX 2005-07-14
  • 打赏
  • 举报
回复
Ok 我的email antonliox@yahoo.com.cn
CyDev 2005-07-14
  • 打赏
  • 举报
回复
谢谢啊。搞定了 再给你加分啊
AntonlioX 2005-07-14
  • 打赏
  • 举报
回复
再给你一个 英文的资料吧


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;
}

AntonlioX 2005-07-14
  • 打赏
  • 举报
回复
我想你看看上面的资料 照着上面的去实现 应该可以的
AntonlioX 2005-07-14
  • 打赏
  • 举报
回复

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;

  }  
CyDev 2005-07-14
  • 打赏
  • 举报
回复
最好给个具体的例子
CyDev 2005-07-14
  • 打赏
  • 举报
回复
谢谢 能不能具体点啊?
AntonlioX 2005-07-14
  • 打赏
  • 举报
回复
How to Redirect ?

1 Create a anonymous pipe
use CreatePipe();
2 Create noninheritable read handle and close the inheritable read handle.
use DuplicateHandle();
3 Modify “STARTUPINFO si”
…….
si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
si.hStdOutput = hPipeWrite;
si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
……
4 call CreateProcess();
AntonlioX 2005-07-14
  • 打赏
  • 举报
回复
我以前搞过这个:
我把写的文档中的一点内容抄到下面啊:

基本的步骤:

1 Create subthread to call subprocess
2 Create the command line.
3 Redirect the output of subprocess
4 Call the CreateProcess()
5 Show the output

3,245

社区成员

发帖
与我相关
我的任务
社区描述
ATL,Active Template Library活动(动态)模板库,是一种微软程序库,支持利用C++语言编写ASP代码以及其它ActiveX程序。
社区管理员
  • ATL/ActiveX/COM社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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