UPDATE Frage: So konnte ich den Prozess erstellen und die Programme kompilieren. Ich stoße jedoch auf ein neues Problem. Wenn ich versuche, das Source-Programm in das Filter-Programm zu leiten. Es scheint keine Eingabe für das Senkenprogramm zu liefern. Es gibt keine Fehlermeldung. Ich habe auch mein ganzes Programm mit dem Pipe-Operator in Windows 'cmd getestet.Prozess und anonyme Leitung erstellen
Ich versuche dieses kleine Projekt zu tun, um über anonyme Pipe zu lernen und Prozess zu erstellen. Ich habe 3 kleine Standalone-Programme namens Source, Filter und Sink erstellt. Diese 3 sind bereits kompiliert und laufen gut. Hier sind die Beschreibungen für die 3 Standalone-Programme.
Quelle: Ermittelt den Dateinamen einer Quelltextdatei von der Befehlszeile, öffnet die Datei und liest und kopiert den Inhalt der Datei ein Zeichen nach dem anderen direkt in die Standardausgabe (stdout). Wenn die Datei kopiert wurde, wird Source beendet (alle geöffneten Dateihandles werden geschlossen).
Das Filterprogramm verwendet keine Dateinamen-Befehlszeilenparameter. Stattdessen liest Filter eine Textdatei von der Standardeingabe (stdin) und schreibt eine Standardausgabe (stdout) einer Kopie der Eingabe, wobei alle Großbuchstaben in Kleinbuchstaben konvertiert werden. Der Filter muss speziell dafür ausgelegt sein, ein Zeichen zu lesen, es zu konvertieren, auszugeben und dann zu wiederholen, bis die eingehenden Daten beendet sind.
Sink-Programm ruft einen Zieltextdateidateinamen von seiner Befehlszeile ab, öffnet die Datei zum Schreiben und liest dann nacheinander Zeichen aus der Standardeingabedatei (stdin) und schreibt jedes eingehende Zeichen direkt in die Zielsenkdatei .
Als nächstes fahre ich separat ein Haupttreiberprogramm, das 2 Pipes erstellt und 3 unabhängige Childs mit Ein- und Ausgängen spawnt, die so konfiguriert sind, dass sie die angegebene gleichzeitige Ausführung und den gleichen Datenfluss ausführen. Etwas wie folgt aus:
- srcfile -> Quelle -> PIPE1 -> Filter -> PIPE2 -> Sink -> destfile
Der Fahrer Programm erfordert zwei Kommandozeilenparameter:
C:\> Driver.exe srcfile destfile
wo srcfile ist eine bestehende Daten Text-Datei, und Zieldatei ist der Dateiname einer neuen Zieldatei, die von der Sink-Anwendung erstellt werden soll.
Hier ist mein Code für das Treiberprogramm. Es ist noch nicht fertig. Aber ich habe einen Schluckauf beim Versuch, einen Prozess für das Source-Programm zu erstellen.
AKTUALISIERT Code:
#include <windows.h>
#include <WinBase.h>
#include <stdio.h>
#define DELAY_A_WHILE() {volatile long j; for(j = 1; j< 10000; j++) ; }
int main(int argc, char *argv[])
{
HANDLE hPipeRead, hPipeWrite, hPipeRead2, hPipeWrite2;
STARTUPINFO StartupInfoSource;
STARTUPINFO StartupInfoFilter;
STARTUPINFO StartupInfoSink;
PROCESS_INFORMATION ProcInfoSource;
PROCESS_INFORMATION ProcInfoFilter;
PROCESS_INFORMATION ProcInfoSink;
SECURITY_ATTRIBUTES PipeAttributes;
SECURITY_ATTRIBUTES PipeAttributes2;
char cmdline[200];
PipeAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
PipeAttributes.lpSecurityDescriptor = NULL; //ignore
PipeAttributes.bInheritHandle = TRUE; //child can inherit
//Create first pipe
if (!CreatePipe(&hPipeRead, &hPipeWrite, &PipeAttributes, 0)) {
fprintf(stderr, "Error creating pipe: %d\n", GetLastError());
exit(1);
}
sprintf_s(cmdline, 200, "Source.exe %s", argv[1]);
printf("Create process: %s\n", cmdline);
GetStartupInfo(&StartupInfoSource);
StartupInfoSource.dwFlags = StartupInfoSource.dwFlags | STARTF_USESTDHANDLES;
//Mapping
StartupInfoSource.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
StartupInfoSource.hStdOutput = hPipeWrite;
StartupInfoSource.hStdError = GetStdHandle(STD_ERROR_HANDLE);
if (!CreateProcess(
NULL, cmdline, NULL, NULL,
TRUE,
CREATE_NEW_CONSOLE, NULL, NULL,
&StartupInfoSource,
&ProcInfoSource))
{
fprintf(stderr, "Error creating child process: %d",GetLastError());
exit(1);
}
CloseHandle(hPipeWrite);
CloseHandle(ProcInfoSource.hProcess);
CloseHandle(ProcInfoSource.hThread);
PipeAttributes2.nLength = sizeof(SECURITY_ATTRIBUTES);
PipeAttributes2.lpSecurityDescriptor = NULL; //ignore
PipeAttributes2.bInheritHandle = TRUE; //child can inherit
//Create Second Pipe
if (!CreatePipe(&hPipeRead2, &hPipeWrite2, &PipeAttributes2, 0)) {
fprintf(stderr, "Error creating pipe: %d\n", GetLastError());
exit(1);
}
GetStartupInfo(&StartupInfoFilter);
StartupInfoFilter.dwFlags = StartupInfoFilter.dwFlags | STARTF_USESTDHANDLES;
//Mapping
StartupInfoFilter.hStdInput = hPipeRead;
StartupInfoFilter.hStdOutput = hPipeWrite2;
StartupInfoFilter.hStdError = GetStdHandle(STD_ERROR_HANDLE);
sprintf_s(cmdline, 200, "Filter.exe");
printf("Create process: %s\n", cmdline);
//Filter
GetStartupInfo(&StartupInfoFilter);
if (!CreateProcess(
NULL, cmdline, NULL, NULL,
TRUE,
CREATE_NEW_CONSOLE, NULL, NULL,
&StartupInfoFilter,
&ProcInfoFilter))
{
fprintf(stderr, "Error creating child process: %d", GetLastError());
exit(1);
}
// int exitStatus;
// GetExitCodeProcess(ProcInfoFilter.hProcess, &exitStatus);
CloseHandle(hPipeRead);
CloseHandle(hPipeWrite2);
CloseHandle(ProcInfoFilter.hProcess);
CloseHandle(ProcInfoFilter.hThread);
GetStartupInfo(&StartupInfoSink);
StartupInfoSink.dwFlags = StartupInfoSink.dwFlags | STARTF_USESTDHANDLES;
//Mapping
StartupInfoSink.hStdInput = hPipeRead2;
StartupInfoSink.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
StartupInfoSink.hStdError = GetStdHandle(STD_ERROR_HANDLE);
sprintf_s(cmdline, 200, "Sink.exe %s", argv[2]);
printf("Create process: %s\n", cmdline);
GetStartupInfo(&StartupInfoSink);
if (!CreateProcess(
NULL, cmdline, NULL, NULL,
TRUE,
CREATE_NEW_CONSOLE, NULL, NULL,
&StartupInfoSink,
&ProcInfoSink))
{
fprintf(stderr, "Error creating child process: %d", GetLastError());
exit(1);
}
CloseHandle(hPipeRead2);
CloseHandle(ProcInfoSink.hProcess);
CloseHandle(ProcInfoSink.hThread);
return 0;
}
Das Programm stellt in Ordnung. Wenn es jedoch versucht, den Prozess zu erstellen, schlägt er immer fehl und wird beendet. Der Wert cmdline
beim Parsen ist "Source.exe test.txt", was genau das ist, was ich benutzt habe, um mein eigenständiges Source-Programm auszuführen. Kann jemand erklären, warum meine CreateProcess
scheitern? Liegt es daran, dass ich den falschen Parameter parse?
Sie sagen also, CreateProcess' scheitert? Dann sollten Sie sich den Fehlercode ansehen, der von 'GetLastError' zurückgegeben wird. Übrigens, ist es richtig, dass Sie den 'STARTUPINFO' des aufrufenden Prozesses übergeben? Soll das die Griffe zu stdin und stdout übergeben? –
Wenn ich versuche, zu debuggen, führt das Programm immer das Stück Code innerhalb der If (! CreateProcess()) aus, die den Fehler drucken soll, wenn es das Programm nicht schafft und verläßt. –