Redirecting standard output to a namedpiped

Answered Redirecting standard output to a namedpiped

  • Friday, June 15, 2012 1:06 PM
     
     

    Hello,

    I know that with freopen() I can redirect the standard output to a file, now question is there anyway to use freopen() and give it a named pipe. This way instead of redirecting to a file I will redirect it to the named pipe.

    cheers,

    Ehsan 

All Replies

  • Friday, June 15, 2012 1:24 PM
     
     

    CODEPROJECT:

    The technique of redirecting the input/output of a console process is very sample: The CreateProcess() API through the STARTUPINFO structure enables us to redirect the standard handles of a child console based process. So we can set these handles to either a pipe handle, file handle, or any handle that we can read and write. The detail of this technique has been described clearly in MSDN: HOWTO: Spawn Console Processes with Redirected Standard Handles.


    If you find this p☺st helpful please remember to hit <Vote As Helpful> √ 1. Whiter than the white is UV bright! 2. Eat your vegetables or you are going to turn in to blobs of lazy fat! 3. Fruits won't cut it 4 wheel drive with levers to lock differentials was a hack


    • Edited by D3F84U Friday, June 15, 2012 1:26 PM
    • Marked As Answer by ehsansad Monday, June 18, 2012 10:33 AM
    • Unmarked As Answer by ehsansad Monday, June 18, 2012 1:21 PM
    •  
  • Monday, June 18, 2012 10:34 AM
     
     Proposed Answer

    I would appreciate the answer as well. I am not aware of mechanism that can reroute all console IO. Even for above example it works for C++ conio commands, and I had never heard how to do it for C functions like printf.

    I am exploring following option:

    CMDLINE:

    ProcessThatUsesConsole.exe > MyExeThatReceivesAndManagesConsoleInput.exe

    where ">MyExeThatReceivesAndManagesConsoleInput.exe" is added to command line parameters

    In case you are not familiar with syntax, I am talking [dir >listing.txt] where you will get output to file listing.txt


    If you find this p☺st helpful please remember to hit <Vote As Helpful> √ 1. Whiter than the white is UV bright! 2. Eat your vegetables or you are going to turn in to blobs of lazy fat! 3. Fruits won't cut it 4 wheel drive with levers to lock differentials was a hack


  • Monday, June 18, 2012 7:20 PM
     
     Proposed Answer

    On 6/15/2012 9:06 AM, ehsansad wrote:

    I know that with freopen() I can redirect the standard output to a file, now question is there anyway to use freopen() and give it a named pipe. This way instead of redirecting to a file I will redirect it to the named pipe.

    Try something like this:

    HANDLE pipe = CreateNamedPipe(...);
    int stream = _open_osfhandle(intptr_t(pipe), 0);
    stdout = _fdopen(stream, "wt");


    Igor Tandetnik

  • Tuesday, June 19, 2012 1:35 PM
     
      Has Code

    I have been trying to make this work without any result, this is the code:

    #include <windows.h>
    #include <process.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <io.h>
    
    
    int     Buffer_out;
    int     count,i;
    int     stream;
    int     old;
    LPCTSTR pipeName = "\\\\.\\pipe\\ehsan";
    HANDLE  hPipe;
    FILE    *freOpenstream = NULL;
    FILE    *test = NULL;
    
    int main(int argc, char* argv[])
    {	
       hPipe = CreateNamedPipe(pipeName, 
                                PIPE_ACCESS_OUTBOUND,
                                PIPE_TYPE_BYTE | PIPE_WAIT,
                                10, 0, sizeof(Buffer_out), 
                                10000, 
                                NULL);    
       if(INVALID_HANDLE_VALUE == hPipe)
       {
         printf("Server Pipe not created\n");
         exit(0);
       }
       else
         printf("Successful in creating server pipe\n");
       
       old = _dup(1);
       if( old == -1 )
       {
          perror( "_dup( 1 ) failure" );
          exit( 1 );
       }
       stream = _open_osfhandle((long)hPipe, 0);
       if(stream != -1)
           test = _fdopen(stream, "wt");   
      
      
       // stdout now refers to file "test" 
       if(_dup2(_fileno( test), 1 ) == -1 )
       {
          perror( "Can't _dup2 stdout" );
          exit( 1 );
       }
       
      /* if((freOpenstream = freopen(test, "w", stdout)) == NULL)
           exit(-1);
       */
        
       // wait of a  connection.
       while (!ConnectNamedPipe(hPipe, (LPOVERLAPPED) NULL)); printf("Client has connected\n");
       
      for(Buffer_out=0;; Buffer_out++)
      {
      // printf("sending %d\n", Buffer_out);
       WriteFile(hPipe,&Buffer_out, sizeof(Buffer_out),(LPDWORD) &count, NULL);
       printf("sending printf to pipe\n");
       Sleep(1000);
      }
     
        printf("press 'c' to quit\n");
        while( toupper(getchar()) != 'C');
        CloseHandle(hPipe);
     return 0;
    }

    the stdout = _fdopen(stream, "wt"); gave me a lvaue error. My problem here is that the printf("sending to pipe") which I thought would be sent to the pipe is not working, it's not going to the stdout  or to the pipe. 

    so any suggestions?

    with regards,

    ehsan

  • Tuesday, June 19, 2012 11:12 PM
     
     Answered

    On 6/19/2012 9:35 AM, ehsansad wrote:

    My problem here is that the printf("sending to pipe") which I thought

    would be sent to the pipe is not working, it's not going to the stdout or to the pipe.

    I bet the output gets buffered by the run-time. There's some magic in the CRT that detects whether the stream is attached to the console (as opposed to, say, being redirected to a file), and automatically disables buffering.

    Try calling fflush() after printf, and/or use setvbuf to suppress buffering.


    Igor Tandetnik

    • Marked As Answer by ehsansad Wednesday, June 20, 2012 7:10 AM
    •  
  • Wednesday, June 20, 2012 3:21 AM
    Moderator
     
     
     

    Hello,

     

    For addition, you should use multithread for write and read name pipe. Or you can use a named Pipe client to read. Please check these sample

    Multithreaded Pipe Server

    http://msdn.microsoft.com/en-us/library/windows/desktop/aa365588(v=vs.85).aspx

    Named Pipe Client

    http://msdn.microsoft.com/en-us/library/windows/desktop/aa365592(v=vs.85).aspx

     

    Best regards,

    Jesse


    Jesse Jiang [MSFT]
    MSDN Community Support | Feedback to us

  • Wednesday, June 20, 2012 7:13 AM
     
      Has Code

    This is the changes to the code:

      // stdout now refers to file "test" 
       if(_dup2(_fileno( test), 1 ) == -1 )
       {
          perror( "Can't _dup2 stdout" );
          exit( 1 );
       }
       setvbuf(stdout, NULL, _IONBF, 0);
       
    while (!ConnectNamedPipe(hPipe, (LPOVERLAPPED) NULL));   
      for(Buffer_out=0;; Buffer_out++)
      {
       printf("sending printf to pipe\n");
       fflush(NULL);
    
      }
     

    and its working, the client is receiving the printf() string  in the for loop. NOW another question how safe is this code?

    -ehsan

  • Wednesday, June 20, 2012 2:02 PM
     
     

    It looks safe because you are not using single buffer or pointer to array. More interesting than server would be client.

    I assume that last 6 lines of code are meant to be nonsense in terms it would fill endlessly fill the pipe with test message. They are still safe.


    If you find this p☺st helpful please remember to hit <Vote As Helpful> √ 1. Whiter than the white is UV bright! 2. Eat your vegetables or you are going to turn in to blobs of lazy fat! 3. Fruits won't cut it 4 wheel drive with levers to lock differentials was a hack


    • Edited by D3F84U Wednesday, June 20, 2012 2:07 PM
    •  
  • Wednesday, June 20, 2012 2:31 PM
     
      Has Code
    The client is a standard  client  
    #include <windows.h>
    #include <process.h>
    #include <stdio.h>
    
    
    HANDLE    hPipe;
    const int BUFSIZE = 10;
    int Buffer_in;
    int       count;
    
    int main(int argc, char* argv[])
    {
     
      hPipe = CreateFile("\\\\.\\pipe\\ehsan", // this machine
      GENERIC_READ, 0,
      NULL, OPEN_EXISTING,
      FILE_ATTRIBUTE_NORMAL,
      (HANDLE) NULL);
      if(INVALID_HANDLE_VALUE == hPipe)
        {
         printf("Server Pipe not found\n");
         goto done;
        }
      else
         printf("Successful in finding server pipe\n");
        for (;;)
         {
          ReadFile(hPipe,(LPVOID) &Buffer_in, (DWORD) sizeof(Buffer_in), (LPDWORD) &count, (LPOVERLAPPED) NULL);	     	  	  
    	  if (Buffer_in != '\n')
    	     printf("%c", Buffer_in);
    	  else
    		 printf("\n");
    
         } 
    
      CloseHandle(hPipe);
    
    return 0;
    
    } 

  • Wednesday, June 20, 2012 5:24 PM
     
     

    On 6/20/2012 3:13 AM, ehsansad wrote:

    NOW another question how safe is this code?

    Safe from what threat? I suppose I don't understand the question.


    Igor Tandetnik

  • Wednesday, June 20, 2012 6:35 PM
     
      Has Code
      ReadFile(hPipe,(LPVOID) &Buffer_in, (DWORD) sizeof(Buffer_in),

    is potential threat. Since you are not using any arrays, and you write fixed size that is determined from variable it self,  you can't cause buffer overrun. Your code seems safe from managed vs. native perspective.

      I hope I understood your question correctly.


    If you find this p☺st helpful please remember to hit <Vote As Helpful> √ 1. Whiter than the white is UV bright! 2. Eat your vegetables or you are going to turn in to blobs of lazy fat! 3. Fruits won't cut it 4 wheel drive with levers to lock differentials was a hack

  • Thursday, June 21, 2012 2:05 PM
     
     
    I was just thinking if the whole system will collapse or not, based on this  code.
  • Thursday, June 21, 2012 7:32 PM
     
     

    On 6/21/2012 10:05 AM, ehsansad wrote:

    I was just thinking if the whole system will collapse or not, based on this  code.

    Highly unlikely. The worst that could happen is your process could crash.


    Igor Tandetnik

  • Friday, June 22, 2012 7:25 AM
     
     
    Thanks for the help.