Ich hatte hier mal nach dem Umleiten von Consolestreams gefragt.
Ich habe nun aber folgende Situation:
Der Child Prozess startet wie geplant und macht, was er soll (schreibt in Datei), beendet sich dann aber sofort, er ignoriert alle inputabfragen und schließt sich. Zudem bleibt das Fenster schwarz (keine Outputs), ich nehme mal an, das das normal ist, weil ich nun den Output am Parent habe.
Wenn ich eine Dauerschleife mit Ausgaben im Kindprozess habe, dann passiert einfach gar nichts bei lesen oder schreiben.
Ich hab mittlerweile mitbekommen, dass wenn schreibe und lese pipe offen sind, dass dann das lesen stehen bleibt (macht ja auch Sinn).
Wann muss ich die Pipes erstellen / schließen ?
Müssen sie bei der Erstellung des Prozesses schon existieren ?
Sind Output in der Console möglich und in meinem Programm ?
Naja, ihr könnt die Glaskugel wieder einpacken, hier kommt der Code:
(auch unter Benutzung der VCL, aber das sollte hier kaum stören)
Struktur für die Konsole Anwendung:
struct ConsoleApplication
{
String FileName;
bool StartVisible;
String StartingParameters;
String DirectoryOfStart;
STARTUPINFO StartInfo;
PROCESS_INFORMATION ProcInfo;
};
Die Klasse für die Pipes:
class ConsolePipeHandler
{
private:
HANDLE PIPE_STANDARD_ERROR;
HANDLE PIPE_STANDARD_INPUT; // WRITE CONSOLE INPUT
HANDLE PIPE_STANDARD_CATCHER; // READ CONSOLE INPUT
HANDLE PIPE_STANDARD_OUTPUT; // READ CONSOLE OUTPUT
HANDLE PIPE_STANDARD_DISPLAY; // WRITE CONSOLE OUTPUT
ConsoleApplication* Applic;
bool ProcessCreated;
static const unsigned int MAX_BUFFER = 32786;
public:
ConsolePipeHandler();
~ConsolePipeHandler();
void __fastcall CreateConsoleProcess(ConsoleApplication* Appi);
void __fastcall WriteToPipe(UnicodeString Message, __int64 Position = -1);
UnicodeString __fastcall ReadFromPipe(__int64 Position, __int64 Length);
void __fastcall CreatePipes(); // NOT USED - TRASH
void __fastcall SendErrorToPipe(); // NOT USED - TRASH
};
Prozesserstellung:
void __fastcall ConsolePipeHandler::CreateConsoleProcess(ConsoleApplication* Appi)
{
this->Applic = Appi;
CreatePipes();
// ZERO MEMORY CALLS
ZeroMemory( &Applic->ProcInfo, sizeof(PROCESS_INFORMATION) );
ZeroMemory( &Applic->StartInfo, sizeof(STARTUPINFO) );
// Startinformationen setzen
Applic->StartInfo.cb = sizeof(STARTUPINFO);
Applic->StartInfo.hStdError = PIPE_STANDARD_ERROR;
Applic->StartInfo.hStdOutput = PIPE_STANDARD_OUTPUT;
Applic->StartInfo.hStdInput = PIPE_STANDARD_INPUT;
Applic->StartInfo.dwFlags |= STARTF_USESTDHANDLES;
Applic->StartInfo.dwFlags |= STARTF_USESHOWWINDOW;
if (!Applic->StartVisible)
{
Applic->StartInfo.wShowWindow = SW_HIDE;
}
else
{
Applic->StartInfo.wShowWindow = SW_MINIMIZE;
}
bool Success = false;
// Prozess erstellen
Success = CreateProcess(
NULL,
Applic->FileName.c_str(),
NULL,
NULL,
TRUE,
CREATE_NEW_CONSOLE,
NULL,
NULL,
&Applic->StartInfo,
&Applic->ProcInfo
);
if (Success)
{
ProcessCreated = true; // unlock read and write
}
else
throw Exception("Creation Failed: " + IntToStr(static_cast <__int64> (GetLastError())));
}
Konstruktor und Destruktor:
ConsolePipeHandler::~ConsolePipeHandler()
{
TerminateProcess(Applic->ProcInfo.hProcess,9);
CloseHandle(Applic->ProcInfo.hProcess);
CloseHandle(Applic->ProcInfo.hThread);
delete Applic;
}
//---------------------------------------------------------------------------
ConsolePipeHandler::ConsolePipeHandler()
{
ProcessCreated = false;
}
Write:
void __fastcall ConsolePipeHandler::WriteToPipe(UnicodeString Message, __int64 Position)
{
SECURITY_ATTRIBUTES saAttr;
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr.bInheritHandle = TRUE;
saAttr.lpSecurityDescriptor = NULL;
if (! CreatePipe(&PIPE_STANDARD_CATCHER, &PIPE_STANDARD_INPUT, &saAttr, 32786))
throw Exception("Could not create PIPE_STANDARD_INPUT: " + IntToStr((__int64)GetLastError()));
if ( ! SetHandleInformation(PIPE_STANDARD_CATCHER, HANDLE_FLAG_INHERIT, 0) )
throw Exception("Could not create PIPE_STANDARD_INPUT: " + IntToStr((__int64)GetLastError()));
unsigned long WrittenLen = 0;
if (Position != -1)
{
SetFilePointer(PIPE_STANDARD_INPUT, Position, 0, FILE_BEGIN);
}
WriteFile(PIPE_STANDARD_INPUT, Message.c_str(), Message.Length(), &WrittenLen, NULL);
CloseHandle(PIPE_STANDARD_INPUT);
}
Read:
UnicodeString __fastcall ConsolePipeHandler::ReadFromPipe(__int64 Position, __int64 Length)
{
SECURITY_ATTRIBUTES saAttr;
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr.bInheritHandle = TRUE;
saAttr.lpSecurityDescriptor = NULL;
if ( ! CreatePipe(&PIPE_STANDARD_OUTPUT, &PIPE_STANDARD_DISPLAY, &saAttr, 32786) )
throw Exception("Could not create PIPE_STANDARD_OUTPUT: " + IntToStr((__int64)GetLastError()));
if ( ! SetHandleInformation(PIPE_STANDARD_OUTPUT, HANDLE_FLAG_INHERIT, 0) )
throw Exception("Could not create PIPE_STANDARD_OUTPUT: " + IntToStr((__int64)GetLastError()));
unsigned long ReadLen = 0;
SetFilePointer(PIPE_STANDARD_OUTPUT, Position, 0, FILE_BEGIN);
char Buffer[MAX_BUFFER];
PathSystems Psys;
if (Length > MAX_BUFFER)
{
__int64 RemainingLength = Length;
String Output = "";
for (unsigned int i = 0; i < Length; i++)
{
if (MAX_BUFFER > RemainingLength)
{
RemainingLength -= MAX_BUFFER;
ReadFile(PIPE_STANDARD_OUTPUT, &Buffer, MAX_BUFFER, &ReadLen, NULL);
Output += Psys.CopyStringFrom(Buffer,ReadLen);
}
else
{
ReadFile(PIPE_STANDARD_OUTPUT, &Buffer, RemainingLength, &ReadLen, NULL);
Output += Psys.CopyStringFrom(Buffer,ReadLen);
break;
}
}
return Output;
}
else
{
ReadFile(PIPE_STANDARD_OUTPUT, &Buffer, Length, &ReadLen, NULL);
return Psys.CopyStringFrom(Buffer,ReadLen);
}
CloseHandle(PIPE_STANDARD_OUTPUT);
}
Starten:
Interface = new PipeInterface(true);
ConsoleApplication* CA = new ConsoleApplication();
CA->FileName = Psys->ExtractFrom() + "Child_Simple.exe";
CA->StartVisible = true;
Interface->CreatePipes(CA);
Interface->Resume();
Im Thread (simple):
void __fastcall PipeInterface::Execute()
{
//---- Thread-Code hier einfügen ----
String OMG = Pipes->ReadFromPipe(0,5);
Pipes->WriteToPipe("Hello");
OMG = Pipes->ReadFromPipe(0,10);
}
//---------------------------------------------------------------------------
void __fastcall PipeInterface::CreatePipes(ConsoleApplication* CA)
{
Pipes->CreateConsoleProcess(CA);
}
Kind:
int _tmain(int argc, _TCHAR* argv[])
{
std::cout << "Simple" << std::endl;
ofstream Writer("Output.txt");
string str = "";
system("Pause");
cin >> str;
Writer << "Done";
Writer.close();
return 0;
}
Sagt wenn ihr mehr Informationen braucht.