From: Andre Hamilton Andre on
I am currently trying to redirect stdin/stdout from the cmd process so I can
execute commands analize the results in a seperate program.

I followed the instrcutions found on msdn with anonymous
pipes(http://msdn.microsoft.com/en-us/library/ms682499(VS.85).aspx), but this
only works temporarily.

1)I am able to read and write to the console, but it is out of order. I use
2 function to read and write to the console:

bool readFromPipe(string* pipeString);//reads string from pipe and stores
it in string
bool writeToPipe(string writeString);//write the string to
stdin(hChildStdinWr) of console


I first call writeToPipe(), then readFromPipe(), and then print the results
to the screen. But the results from readFromPipe doesnt get printed onscreen
untill a second call to writeToPipe() and readFromPipe. Below is sample
output of my program(what I typed in is in red).

//------------------------------------------------------------------------

>>
dir

Copyright (c) 2006 Microsoft Corporation. All rights reserved.

C:\Users\jadmin\Documents\Borland Studio Projects\Debug_Build>any text
dir
Volume in drive C has no label.
Volume Serial Number is 80D7-0AEC

Directory of C:\Users\jadmin\Documents\Borland Studio Projects\Debug_Build

06/27/2008 11:43 AM <DIR> .
06/27/2008 11:43 AM <DIR> ..
06/27/2008 11:43 AM 128,871 DevConUtil.obj
06/27/2008 11:39 AM 251,671 PipeTest.obj
06/27/2008 11:43 AM 31,744 Project1.exe
06/27/2008 11:43 AM 1,114,112 Project1.tds
4 File(s) 1,526,398 bytes
2 Dir(s) 79,994,851,328 bytes free

C:\Users\jadmin\Documents\Borland Studio Projects\Debug_Build>dir
More?

//-------------------------------------------------------------------------------------

2)After the second dir is entered, the console outputs the word "More?" and
then the cmd process exists. Does anyone know why the console would be
ouputting the word more, and if it is at all possible to keep the pipes open
for more than one read and write?


//Below is a snippet of the code used

Below is the main class which creates the process and the pipes
1 <devConUtil.h>
2
//---------------------------------------------------------------------------

3
4 #ifndef DevConUtilH
5 #define DevConUtilH
6
//---------------------------------------------------------------------------

7
8 #include "windows.h"
9 #include <vcl.h>
10
11
12 #define BUFSIZE 4098
13
14
15
16 class DevConUtil
17 {
18 public:
19
20 DevConUtil(HANDLE hwd);
21 ~DevConUtil();
22 std::string sendCommand(std::string cmdString);
23
24 bool wasConstructedProperly() { return constructedProperly; }
25 DWORD getExitStatus(){
GetExitCodeProcess(piProcInfo.hProcess,&exitStat);
26 return exitStat;
27 }
28
29
30 private:
31 HANDLE hChildStdinRd;
32 HANDLE hChildStdinWr;
33 HANDLE hChildStdoutRd;
34 HANDLE hChildStdoutWr;
35 HANDLE hInputFile;
36 HANDLE hSaveStdout;
37 HANDLE hStdout;
38 HANDLE hSaveStdin;
39
40 PROCESS_INFORMATION piProcInfo;
41 DWORD exitStat;
42
43 bool constructedProperly;
44
45
46
47 BOOL createCMDProcess(HANDLE hwnd);
48 bool readFromPipe(std::string* pipeString);
49 bool writeToPipe(std::string writeString);
50
51
52
53
54 };
55
56 #endif

//-----------------------------------------
below is the cpp implementation
1
//---------------------------------------------------------------------------

2
3
4 #pragma hdrstop
5
6 #include "DevConUtil.h"
7 #include <iostream>
8
//---------------------------------------------------------------------------

9
10 #pragma package(smart_init)
11
12
13 DevConUtil::DevConUtil(HANDLE hwnd)
14 {
15 SECURITY_ATTRIBUTES saAttr;
16 BOOL fSuccess;
17 constructedProperly = true;
18
19 // Set the bInheritHandle flag so pipe handles are inherited.
20
21 saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
22 saAttr.bInheritHandle = TRUE;
23 saAttr.lpSecurityDescriptor = NULL;
24
25 // Get the handle to the current STDOUT.
26
27 hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
28
29 // Create a pipe for the child process's STDOUT.
30
31 if (! CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0))
32 {
33 MessageBox(hwnd,"Stdout pipe creation failed","ERROR",MB_OK);
34 constructedProperly = false;
35
36 }
37
38
39 // Ensure that the read handle to the child process's pipe for STDOUT is
not inherited.
40
41 SetHandleInformation( hChildStdoutRd, HANDLE_FLAG_INHERIT, 0);
42
43
44 // Create a pipe for the child process's STDIN.
45
46 if (! CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0))
47 {
48 MessageBoxA(NULL,"Stdin pipe creation failed\n","ERROR",MB_OK);
49 constructedProperly = false;
50
51 }
52
53
54 // Ensure that the write handle to the child process's pipe for STDIN is
not inherited.
55
56 SetHandleInformation( hChildStdinWr, HANDLE_FLAG_INHERIT, 0);
57
58 // Now create the child process.
59
60
61 BOOL rslt = createCMDProcess(hwnd);
62 if(!(rslt))
63 {
64 constructedProperly = false;
65 }
66
67 std::string tmp;
68 readFromPipe(&tmp);
69 //std::cout<<tmp.c_str();
70 }
71
72 DevConUtil::~DevConUtil()
73 {
74 if (! CloseHandle(hChildStdinWr))
75 MessageBox(NULL,"Close pipe failed","ERROR",MB_OK);
76 // Close the write end of the pipe before reading from the
77 // read end of the pipe.
78
79 if (!CloseHandle(hChildStdoutWr))
80 MessageBox(NULL,"Closing handle failed","ERROR",MB_OK);
81
82 //std
83
84 }
85
86 std::string DevConUtil::sendCommand(std::string cmdString)
87 {
88 //std
89 bool wrSuccess = false;
90 bool readSucess = false;
91 bool con = true;
92 std::string result("");
93 std::string tmp("Hellow World");
94 wrSuccess = writeToPipe(cmdString);
95
96 readSucess = readFromPipe(&result);
97
98 //readSucess =
99
100 return result;
101
102 }
103
104
105 BOOL DevConUtil::createCMDProcess(HANDLE hwnd)
106 {
107 TCHAR szCmdline[]=TEXT("cmd -ka ");
108
109 STARTUPINFO siStartInfo;
110 BOOL bFuncRetn = FALSE;
111
112 // Set up members of the PROCESS_INFORMATION structure.
113
114 ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );
115
116 // Set up members of the STARTUPINFO structure.
117
118 ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
119 siStartInfo.cb = sizeof(STARTUPINFO);
120 siStartInfo.hStdError = hChildStdoutWr;
121 siStartInfo.hStdOutput = hChildStdoutWr;
122 siStartInfo.hStdInput = hChildStdinRd;
123 siStartInfo.wShowWindow = SW_SHOW;
124 siStartInfo.dwFlags |= STARTF_USESTDHANDLES |STARTF_USESHOWWINDOW;
125
126 // Create the child process.
127
128 bFuncRetn = CreateProcess(NULL,
129 szCmdline, // command line
130 NULL, // process security attributes
131 NULL, // primary thread security attributes
132 TRUE, // handles are inherited
133 0, // creation flags
134 NULL, // use parent's environment
135 NULL, // use parent's current directory
136 &siStartInfo, // STARTUPINFO pointer
137 &piProcInfo); // receives PROCESS_INFORMATION
138
139 if (bFuncRetn == 0)
140 {
141 MessageBox(hwnd,"CreateProcess failed","ERROR",MB_OK);
142 return FALSE;
143 }
144 else
145 {
146 CloseHandle(piProcInfo.hProcess);
147 CloseHandle(piProcInfo.hThread);
148 return bFuncRetn;
149 }
150
151 //std
152 }
153
154 bool DevConUtil::readFromPipe(std::string * pipeString )
155 {
156 //std
157 DWORD dwRead, dwWritten;
158 CHAR chBuf[BUFSIZE];
159 std::string returnString;
160
161 ZeroMemory(chBuf,BUFSIZE);
162
163
164 if( ReadFile( hChildStdoutRd, chBuf, BUFSIZE, &dwRead,
165 NULL) ||dwRead != 0)
166 {
167 (*pipeString) = chBuf;
168
169 return true;
170
171 }
172 else
173 {
174 (*pipeString) = "Could not read from Pipe";
175 return false;
176 }//else
177
178
179 }
180
181 bool DevConUtil::writeToPipe(std::string writeString)
182 {
183 //std
184 DWORD dwRead, dwWritten;
185 CHAR chBuf[BUFSIZE];
186 DWORD err;
187
188 writeStringwriteString = writeString + "\n\r" ;
189 if (WriteFile(hChildStdinWr, writeString.c_str(),
writeString.Length() +1,
190 &dwWritten, NULL))
191 {
192 //CloseHandle(hChildStdinWr);
193 return true;
194 }
195 else
196 {
197 err = GetLastError();
198 }
199
200 return false;
201
202
203 }

//----------------------------
and this is the main file 1
//---------------------------------------------------------------------------

2
3 #pragma hdrstop
4
5
//---------------------------------------------------------------------------

6
7 #pragma argsused
8
9 #include "DevConUtil.h"
10 #include <iostream>
11 #include <string>
12
13 int main(int argc, char* argv[])
14 {
15 DevConUtil* pipe = new DevConUtil(NULL);
16 std::string exitString("");
17 std::cout<<">>\n";
18
19 bool con = true;
20 do
21 {
22 std::cin>>exitString;
23 if(ll.AnsiCompare("exit") == 0)
24 con = false;
25 exitString = pipe->sendCommand(exitString);
26
27 std::cout<<exitString.c_str();
28 // std::cout<<"\n-----\n"<<std::endl;
29 std::flushall();
30
31 }while(con);
32
33 return 0;
34
35 }
36
37
38
//---------------------------------------------------------------------------