Okay below is the entire function. I added some more commenting so you can see what I'm attempting but basically my main program automatically reads back from the server each time it sends out an instruction from my instructionQueue. Depending on what flags I have set, the information read back is sent to specific handler, which uses this information to adjust the instruction queue or in this case, start parsing info of the screen one line at a time. I'm trying to do this because of the stupid limitations of the server program I'm trying to retrieve reports from. You can view them, but not save them, so I'm trying to come up with a reasonable way of doing that. Hope that helps some...
Code:
private: void reportHandler (String ^read){
String ^tmp = read; //copy the passed in string to a temp string.
if(tmp->Contains("Performing")){ //if the report is being generated
instructionTimer->Stop(); //stop sending instructions
while (!tmp->Contains("tmp")) //keep reading until the report is shown (need to account for possible infinite loop)
tmp = gcnew String(connector.ReadFromPipe().c_str());
String^ path = "c:\\MyTest.txt"; //once the report is up, setup the log file.
// Delete the file if it exists.
if (File::Exists(path))
File::Delete(path);
//Create the file.
StreamWriter^ sw = File::CreateText(path);
int cnt = 0; //setup a count for debugging/no infinite loop
try{
//at the first loop iteration tmp must contain at least "tmp" so its not "NULL"
while (!tmp->Contains("(END)") && cnt < 10){ //while we are not at the end of the report
connector.WriteToPipe("\r"); //send 'Enter'
sw->WriteLine("This is a test line"); //write out whatever we just recieved (for right now a test string)
tmp = gcnew String(connector.ReadFromPipe().c_str()); //read into tmp again
cnt++; //increment
}
sw->Flush(); //flush stream
sw->Close(); //close stream
}
catch ( Exception^ e ) //catch any IO Exception
{
MessageBox::Show(e->ToString(), "Exception Occured", MessageBoxButtons::OK);
exit(1);
}
instructionTimer->Start(); //restart our timer
}
if(instructionQueue.empty()){ //check for empty queue
instructionTimer->Stop(); //stop timer
RTRV_REPORT = false; //disable flag
MessageBox::Show("All reports retrieved.", //success
"Report Retrieval", MessageBoxButtons::OK);
return;
}
}
^read is picked up from ReadFromPipe() as well, it just occurs on each tick of the instructionTimer.
Here is ReadFromPipe() :
Code:
string Pconnect::ReadFromPipe(){
DWORD dwRead;
string ret = "NULL";
CHAR chBuf[BUFSIZE];
// Close the write end of the pipe before reading from the
// read end of the pipe.
if (!CloseHandle(hChildStdoutWr))
std::cerr << "Closing handle failed.\n";
// Read output from the child process, and write to parent's STDOUT.
while(true){
DWORD dwAvail = 0;
//check if child process ended
if (!::PeekNamedPipe(hChildStdoutRd, NULL, 0, NULL, &dwAvail, NULL))
break;
//check if there was no data
if (!dwAvail)
break;
//read the file and break once the reading is complete
if(!ReadFile( hChildStdoutRd, chBuf, BUFSIZE, &dwRead, NULL) || dwRead == 0)
break;
}
//make sure there is data to put in the string
if(dwRead > 0)
ret = chBuf;
return ret;
}
My Connector code was written in unmanaged but so far it has been working okay with my newer VC++ managed code. I hope this helps, this bug is driving me crazy.
Also even if tmp was NULL, wouldnt that throw some kind of error when it hit the loop at a certain iteration? The exception is being thrown at sw->flush or sw->close. If I remove those lines no exception is ever thrown, but my file never gets any output either obviously.