Overview
Features
Download
Documentation
Community
Add-Ons & Services

How to redirect cmd.exe STDIN, STDOUT and STDERR?

Please post support and help requests here.

How to redirect cmd.exe STDIN, STDOUT and STDERR?

Postby changire » 25 Jan 2013, 11:45

Environment: WinXP SP3, poco-1.4.3p1-all

I'm trying to launch cmd.exe using Poco::launch(...)
I'm passing Pipe objects so that the STDIN, STDOUT and STDERR of the cmd.exe can be written and read from.
Code: Select all
Poco::Process::launch("cmd.exe", args, &m_inPipe, &m_outPipe, &m_outPipe);

Is this a correct approach to redirect the stdin/out/err of cmd.exe?
Is this at all possible with Poco?

I do get to see the console window but without any text being printed (as expected)
This is followed by a write of a "dir\r\n" to the m_inPipe.
Code: Select all
m_inPipe.writeBytes("dir\r\n", 5);

The program blocks on attempt to read from m_outPipe.

I'd like to write commands to the m_inPipe and read output from m_outPipe just as a user would type commands in an interactive session.

Regards,
Milind
changire
 
Posts: 7
Joined: 07 Dec 2012, 09:40

Re: How to redirect cmd.exe STDIN, STDOUT and STDERR?

Postby changire » 30 Jan 2013, 10:21

The process launching, sending input to the cmd.exe and reading output parts remained the same.

I found a good reference to the solution at Microsoft site http://support.microsoft.com/kb/q190351

And then something more at Code Project site explaining the deficiencies inherent in the Microsoft example http://www.codeproject.com/Articles/5531/Redirecting-an-arbitrary-Console-s-Input-Output

These helped me come up with a non-threaded copyPipe(...) implementation for WIN32 and __linux as below
Code: Select all
void copyPipe(Poco::Pipe & pipe, std::ostream & ostr)
{
   char ch;

   try {
#if WIN32
      DWORD dwAvail = 0;
#elif __linux
      int dwAvail = 0;
#endif
      int retries = 3;
      while (retries)
      {
#if WIN32
         if (PeekNamedPipe(pipe.readHandle(), NULL, 0, NULL, &dwAvail, NULL) && dwAvail > 0)
#elif __linux // add defines for other *nix appropriately
         if (ioctl(pipe.readHandle(), FIONREAD, &dwAvail) != -1)
#endif
         {
            int bytesRead = 0;
            while (true)
            {
               if (bytesRead != dwAvail)
               {
                  bytesRead += pipe.readBytes(&ch, 1);
                  ostr << ch;
               }
               else
                  break;
            }
         }
         Poco::Thread::sleep(1000);
         if (dwAvail == 0)
            retries--;
         else
            dwAvail = 0;
      }
   }
   catch (Poco::ReadFileException& rfe)
   {
   }
}


I wonder if using a PipeInputStream and StreamCopier::CopyStream(...) would be more efficient and not block than my implementation of the byte by byte copy from the Pipe the the std::ostream
changire
 
Posts: 7
Joined: 07 Dec 2012, 09:40


Return to Support

Who is online

Users browsing this forum: No registered users and 3 guests