I am trying to use CreateProcess
and CreatePipe
to execute a process from within a Windows Forms C++/CLR application in Visual Studio 2010.
Thanks to Hans Passant for the lead that got me to this clear and simple piece of code that does exactly what I was looking for.
/// this namespace call is necessary for the rest of the code to work
using namespace System::Diagnostics;
using namespace System::Text;/// added for encoding
Process^ myprocess = gcnew Process;
Encoding^ Encoding;/// added for encoding
Encoding->GetEncoding(GetOEMCP());/// added for encoding
myprocess->StartInfo->FileName = "ping.exe";
myprocess->StartInfo->Arguments = "127.0.0.1";
myprocess->StartInfo->UseShellExecute = false;
/// added the next line to keep a new window from opening
myprocess->StartInfo->CreateNoWindow = true;
myprocess->StartInfo->RedirectStandardOutput = true;
myprocess->StartInfo->StandardOutputEncoding = Encoding;/// added for encoding
myprocess->Start();
String^ output = gcnew String( myprocess->StandardOutput->ReadToEnd() );
myprocess->WaitForExit();
/// OutputBox is the name of a Windows Forms text box in my app.
OutputBox->Text = output;
EDIT: Added encoding information. See above code.
You are not making correct use of the ::ReadFile()
function.
Read about it here: http://msdn.microsoft.com/en-us/library/ms891445.aspx
Basically, you want to fail with an error if the function ever does not return TRUE, and you want to keep looping until it yields a zero reDword.
Also, ::ReadFile()
will not zero-terminate your data for you, so you have to do it yourself, like this: buf[reDword] = '\0';
(make sure your buf
is 101 chars long before doing that.)
EDIT: Since I was asked to provide some example code, here it is, though I have not gone through the trouble of actually compiling it to make sure it works, so please beware of syntax errors, and generally consider it only as a rough pointer to the direction in which it should be done:
#define BUFFER_SIZE 100
string csoutput;
for( ;; )
{
char buf[BUFFER_SIZE+1];
DWORD redword;
if( !::ReadFile(rPipe,buf,BUFFER_SIZE,&redword,0) )
{
DWORD error = ::GetLastError();
//throw new Exception( "Error " + error ); //or something similar
}
if( redword == 0 )
break;
buf[redword] = '\0';
string cstemp = buf;
csoutput += cstemp;
}
return csoutput;