全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:2803
推到 Plurk!
推到 Facebook!

Using anonymous pipes to redirect standard input/o

 
axsoft
版主


發表:681
回覆:1056
積分:969
註冊:2002-03-13

發送簡訊給我
#1 引用回覆 回覆 發表時間:2002-12-13 22:09:25 IP:61.218.xxx.xxx 未訂閱

Using anonymous pipes to redirect standard input/output of a child process.

資料來源: http://www.Borland.com How to create a process and control its flow by redirecting its standard input/output to your parent process In this article, I will explain how to spawn a console application and redirect its standard input/output using anonymous pipes. An anonymous pipe is a pipe that goes only in one direction (read pipe, write pipe, etc.). Maybe you are asking, "why would I ever need to do this sort of thing?" One example would be a Windows telnet server, where you spawn a shell and listen on a port and send and receive data between the shell and the socket client. (Windows does not really have a built-in remote shell). First, we should talk about pipes. A pipe in Windows is simply a method of communication, often between process. The SDK defines a pipe as "a communication conduit with two ends; a process with a handle to one end can communicate with a process having a handle to the other end." In our case, we are using "anonymous" pipes, one-way pipes that "transfer data between a parent process and a child process or between two child processes of the same parent process." It's easiest to imagine a pipe as its namesake. An actual pipe running between processes that can carry data. We are using anonymous pipes because the console app we are spawning is a child process. We use the CreatePipe function which will create an anonymous pipe and return a read handle and a write handle. We will create two pipes, on for stdin and one for stdout. We will then monitor the read end of the stdout pipe to check for display on our child process. Every time there is something availabe for reading, we will display it in our app. Consequently, we check for input in our app and send it off to the write end of the stdin pipe. Sample app that spawns a shell and redirects its i/o
//------------Sample using CreateProcess and Anonymous Pipes-----------------
//---------------------childspawn.cpp----------------------------------------
//---------------------use freely--------------------------------------------
#include < windows.h >
#include < stdio.h >
#include < conio.h >
#include < string.h >
#pragma hdrstop
#include < condefs.h >
 
#define bzero(a) memset(a,0,sizeof(a)) //easier -- shortcut
 
bool IsWinNT()  //check if we're running NT
{
  OSVERSIONINFO osv;
  osv.dwOSVersionInfoSize = sizeof(osv);
  GetVersionEx(&osv);
  return (osv.dwPlatformId == VER_PLATFORM_WIN32_NT);
}
 
void ErrorMessage(char *str)  //display detailed error info
{
  LPVOID msg;
  FormatMessage(
    FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
    NULL,
    GetLastError(),
    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
    (LPTSTR) &msg,
    0,
    NULL
  );
  printf("%s: %s\n",str,msg);
  LocalFree(msg);
}
 
//---------------------------------------------------------------------------
void main()
{
  char buf[1024];           //i/o buffer
 
  STARTUPINFO si;
  SECURITY_ATTRIBUTES sa;
  SECURITY_DESCRIPTOR sd;               //security information for pipes
  PROCESS_INFORMATION pi;
  HANDLE newstdin,newstdout,read_stdout,write_stdin;  //pipe handles
 
  if (IsWinNT())        //initialize security descriptor (Windows NT)
  {
    InitializeSecurityDescriptor(&sd,SECURITY_DESCRIPTOR_REVISION);
    SetSecurityDescriptorDacl(&sd, true, NULL, false);
    sa.lpSecurityDescriptor = &sd;
  }
  else sa.lpSecurityDescriptor = NULL;
  sa.nLength = sizeof(SECURITY_ATTRIBUTES);
  sa.bInheritHandle = true;         //allow inheritable handles
 
  if (!CreatePipe(&newstdin,&write_stdin,&sa,0))   //create stdin pipe
  {
    ErrorMessage("CreatePipe");
    getch();
    return;
  }
  if (!CreatePipe(&read_stdout,&newstdout,&sa,0))  //create stdout pipe
  {
    ErrorMessage("CreatePipe");
    getch();
    CloseHandle(newstdin);
    CloseHandle(write_stdin);
    return;
  }
 
  GetStartupInfo(&si);      //set startupinfo for the spawned process
  /*
  The dwFlags member tells CreateProcess how to make the process.
  STARTF_USESTDHANDLES validates the hStd* members. STARTF_USESHOWWINDOW
  validates the wShowWindow member.
  */
  si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
  si.wShowWindow = SW_HIDE;
  si.hStdOutput = newstdout;
  si.hStdError = newstdout;     //set the new handles for the child process
  si.hStdInput = newstdin;
  char app_spawn[] = "d:\\winnt\\system32\\cmd.exe"; //sample, modify for your
                                                     //system
 
  //spawn the child process
  if (!CreateProcess(app_spawn,NULL,NULL,NULL,TRUE,CREATE_NEW_CONSOLE,
                     NULL,NULL,&si,&pi))
  {
    ErrorMessage("CreateProcess");
    getch();
    CloseHandle(newstdin);
    CloseHandle(newstdout);
    CloseHandle(read_stdout);
    CloseHandle(write_stdin);
    return;
  }
 
  unsigned long exit=0;  //process exit code
  unsigned long bread;   //bytes read
  unsigned long avail;   //bytes available
 
  bzero(buf);
  for(;;)      //main program loop
  {
    GetExitCodeProcess(pi.hProcess,&exit);      //while the process is running
    if (exit != STILL_ACTIVE)
      break;
    PeekNamedPipe(read_stdout,buf,1023,&bread,&avail,NULL);
    //check to see if there is any data to read from stdout
    if (bread != 0)
    {
      bzero(buf);
      if (avail > 1023)
      {
        while (bread >= 1023)
        {
          ReadFile(read_stdout,buf,1023,&bread,NULL);  //read the stdout pipe
          printf("%s",buf);
          bzero(buf);
        }
      }
      else {
        ReadFile(read_stdout,buf,1023,&bread,NULL);
        printf("%s",buf);
      }
    }
    if (kbhit())      //check for user input.
    {
      bzero(buf);
      *buf = (char)getche();
      //printf("%c",*buf);
      WriteFile(write_stdin,buf,1,&bread,NULL); //send it to stdin
      if (*buf == '\r') {
        *buf = '\n';
        printf("%c",*buf);
        WriteFile(write_stdin,buf,1,&bread,NULL); //send an extra newline char,
                                                  //if necessary
      }
    }
  }
  CloseHandle(pi.hThread);
  CloseHandle(pi.hProcess);
  CloseHandle(newstdin);            //clean stuff up
  CloseHandle(newstdout);
  CloseHandle(read_stdout);
  CloseHandle(write_stdin);
}
聯盟----Visita網站http://www.vista.org.tw ---[ 發問前請先找找舊文章 ]--- 發表人 - axsoft 於 2002/12/13 22:34:30
系統時間:2024-03-29 22:19:46
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!