[Gelöst] CreateProcess/StdIn/StdOut für Kindprozess
-
Hi zusammen,
bin mit meinem Latein am Ende... habe jetzt 3h das Inet nach einer Lösung durchsucht. Habe zwar jede Menge Code gefunden, aber keiner davon funktioniert.
Ich möchte programmgesteuert einen postgreSQL dump ausführen und dazupg_dump.exe
mit entsprechenden Parametern aufrufen. Dazu möchte ich das zu benutzende Kennwort an denpg_dump
Prozess übergeben und danach dessen Ausgaben im Parent Prozess verarbeiten. Das Starten des Kindprozesses funktioniert, aber die Übergabe des Passwortes nicht (und damit bleibt der pg_dump Prozess bei der Eingabe des Passwortes stehen).Hier ist der Code, wenn jemand weiß, wie ich das Problem lösen kann fände ich das super.
void dump_db() { SECURITY_ATTRIBUTES sa; ::ZeroMemory( &sa, sizeof( SECURITY_ATTRIBUTES ) ); sa.nLength = sizeof( SECURITY_ATTRIBUTES ); sa.bInheritHandle = TRUE; // Pipe für Input erzeugen HANDLE ChildInputRead = NULL; HANDLE ChildInputWrite = NULL; if( !::CreatePipe( &ChildInputRead, &ChildInputWrite, &sa, 0 ) ) { return; } // Pipe für Output erzeugen HANDLE ChildOutputRead = NULL; HANDLE ChildOutputWrite = NULL; if( !::CreatePipe( &ChildOutputRead, &ChildOutputWrite, &sa, 0 ) ) { ::CloseHandle( ChildInputRead ); ::CloseHandle( ChildInputWrite ); return; } ::SetHandleInformation( ChildInputRead , HANDLE_FLAG_INHERIT, 0); ::SetHandleInformation( ChildOutputWrite, HANDLE_FLAG_INHERIT, 0); STARTUPINFO si; ::ZeroMemory( &si, sizeof( STARTUPINFO ) ); si.cb = sizeof( STARTUPINFO ); si.dwFlags = STARTF_USESTDHANDLES; si.hStdInput = ChildInputRead; si.hStdOutput = ChildOutputWrite; si.hStdError = ChildOutputWrite; PROCESS_INFORMATION pi; ::ZeroMemory( &pi, sizeof( PROCESS_INFORMATION ) ); BOOL Result = ::CreateProcess( NULL, "pg_dump.exe", // Parameter für Forum entfernt NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi ); if( Result ) { // Kennwort in Input Pipe schreiben DWORD BytesWritten = 0; ::WriteFile( ChildInputWrite, "password\n", strlen( "password\n") , &BytesWritten, NULL ); // Byteswritten ist hier > 0 ::WaitForSingleObject( pi.hProcess, INFINITE ); ::CloseHandle( pi.hThread ); ::CloseHandle( pi.hProcess ); } ::CloseHandle( ChildInputRead ); ::CloseHandle( ChildInputWrite ); ::CloseHandle( ChildOutputRead ); ::CloseHandle( ChildOutputWrite ); }
Hab´ für die Handles schon alles Mögliche probiert (
GetStdHandle/CreatePipe
mit und ohneDuplicateHandle
), ohne dass irgendwas funktioniert hätte.
-
Ein Schuss ins Blaue, vielleicht musst noch ein flush (weiß nicht mehr, wie die Win32 Funktion heißt) aufrufen?
-
Wenn pg_dump das Kennwort zwingend von der Konsole list undnicht aus stdin, dann hast Du keine Chance.
Warum arbeitest Du nicht mit eine .pgpass Datei wie empfohlen?
-
@Martin
Genau das ist mir gestern Abend noch eingefallen. Da pg_dump die Eingabe nicht spiegelt glaube ich nicht, dass sie von stdin gelesen wird. Die .pgpass Datei wollte ich nicht verwenden, da sie Benutzernamen und Kennwort im Klartext enthält.
Ich setzte jetzt vor demCreateProcess
Aufruf die PGPASSWORD Umgebungsvariable setze und danch wieder lösche.
Schade, dass postgreSQL nicht sowas wie ein verschlüsselte Key Datei unterstützt, in der die Anmeldeinformationen verschlüsselt abgelegt sind. Ist vielleicht eine Anregung für das postgreSQL Entwicklerteam.
-
der Aufruf von SetHandleInformation muss so aussehen
::SetHandleInformation( ChildInputRead , HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT);
Martin Richter schrieb:
Wenn pg_dump das Kennwort zwingend von der Konsole list undnicht aus stdin, dann hast Du keine Chance.
Wie soll denn das gehen?