Redirect Output von Konsolenprogramm an Winapi Anwendung



  • Hallo ich hab mir hier versucht eine Funktion zu basteln die mir die Ausgabe eines Konsolenfensters umleitet. Leider bleibt der Code an folgender Stelle stehen:

    if((ReadFile(hOutputRead, lpBuffer, sizeof(lpBuffer) - 1, &nBytesRead, NULL) == FALSE) || (nBytesRead == 0)){
    				if(GetLastError() == ERROR_BROKEN_PIPE){
    					break;
    				}
    			}
    

    Hier jetzt mal die ganze Funktion, wobei "void (*ptrOutPut)(char *text)" die Funktion ist die die Ausgabe in einem Multiline Editfeld ausgibt. Zur Ausgabe ist zu sagen, dass der Text auch korrekt ausgegeben wird, nur nach oben genanter Stelle im Programm ist dann Feierabend und der nachfolgende Teil im Code wird nicht ausgeführt. Was mach ich falsch? Wer kann helfen?

    boolean ExecProggyWithRedirectOutput(char *appname, char *cmdline, char *workingdir, boolean showwnd, int *returncode, void (*ptrOutPut)(char *text)){
    
    	STARTUPINFO			si ={0};
    	PROCESS_INFORMATION	pi ={0};
    	SECURITY_ATTRIBUTES	sa ={0};
    	HANDLE			hOutputReadTmp = 0, hInputWriteTmp = 0;
    	HANDLE			hOutputWrite = 0, hInputWrite = 0, hErrorWrite = 0;
    	HANDLE			hOutputRead = 0, hInputRead = 0;
    	boolean				back = TRUE;
    
    	si.cb = sizeof( STARTUPINFO);
    	if(ptrOutPut){
    		sa.nLength= sizeof(SECURITY_ATTRIBUTES);
    		sa.lpSecurityDescriptor = NULL;
    		sa.bInheritHandle = TRUE;
    		 if(!CreatePipe(&hOutputReadTmp, &hOutputWrite, &sa,0)){
    		 	return FALSE;
    		}
    		 if(!DuplicateHandle(GetCurrentProcess(), hOutputWrite, GetCurrentProcess(),&hErrorWrite,0, TRUE, DUPLICATE_SAME_ACCESS)){
    		 	back = FALSE;
    		 	goto END;
    		}
    		 if(!CreatePipe(&hInputRead, &hInputWriteTmp, &sa,0)){
    		 	back = FALSE;
    		 	goto END;
    		}
    		 if(!DuplicateHandle(GetCurrentProcess(), hOutputReadTmp, GetCurrentProcess(), &hOutputRead, 0, FALSE, DUPLICATE_SAME_ACCESS)){
    		 	back = FALSE;
    		 	goto END;
    		}
    		if(!DuplicateHandle(GetCurrentProcess(), hInputWriteTmp, GetCurrentProcess(), &hInputWrite, 0, FALSE, DUPLICATE_SAME_ACCESS)){
    		 	back = FALSE;
    		 	goto END;
    		}
    		CloseHandle(hOutputReadTmp);
    		CloseHandle(hInputWriteTmp);
    		si.dwFlags |= STARTF_USESTDHANDLES;
    		si.hStdOutput = hOutputWrite;
    		si.hStdError = hErrorWrite;
    		si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
    	}
    	if(showwnd == FALSE){
    		si.dwFlags |= STARTF_USESHOWWINDOW;
    		si.wShowWindow = SW_HIDE;
    	}
    	if(CreateProcess(appname, cmdline, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, workingdir, &si, &pi) == 0){
    		int i = GetLastError();
    	 	back = FALSE;
    	 	goto END;
    	}
    	WaitForInputIdle(pi.hProcess, INFINITE);
     	if(ptrOutPut){
    		char			lpBuffer[1024];
    		DWORD			nBytesRead;
    
    		while(TRUE){
    			memset(&lpBuffer, 0, sizeof(lpBuffer));
    			if((ReadFile(hOutputRead, lpBuffer, sizeof(lpBuffer) - 1, &nBytesRead, NULL) == FALSE) || (nBytesRead == 0)){
    				if(GetLastError() == ERROR_BROKEN_PIPE){
    					break;
    				}
    			}
    			lpBuffer[nBytesRead] = '\0';
    			ptrOutPut(lpBuffer);
    			nBytesRead = 0;
    		}
    	}
    	WaitForSingleObject(pi.hProcess, INFINITE);
    	if(returncode){
    		GetExitCodeProcess(pi.hProcess, returncode);
    	}
    
    END:;
     	if(ptrOutPut){
    	 	CloseHandle(hOutputReadTmp);
    	 	CloseHandle(hInputWriteTmp);
    	 	CloseHandle(hOutputWrite);
    	 	CloseHandle(hInputWrite);
    	 	CloseHandle(hErrorWrite);
    	 	CloseHandle(hOutputRead);
    	 	CloseHandle(hInputRead);
    	}
    	CloseHandle(pi.hProcess);
    	CloseHandle(pi.hThread);
    	return back;
    }
    


  • Kanns sein dass deine Zielanwendung einfach nichts ausgibt?



  • Nein, die Zielanwendung gibt genau das in dem Redirected Fenster aus, was sie auch in der Konsole ausgibt. Aber wenn die Ausgabe rum ist geht es in meiner Funktion laut Debugger nicht weiter. An genau der Codestelle, die ich in meinem Post als erstes aufgeführt habe.



  • Hat niemand eine Ahnung was falsch sein könnte?


  • Mod

    In der Pipe kommt von Deiner Anwendnung nichts an. Punkt. Vermutlich gibt die andere Anwendung nichts aus...



  • Was soll denn das WaitForInputIdle?
    Deine Lösung ist auch nicht korrekt. Je nachdem wie viele Daten ausgegeben werden, kann es bei Dir zu einen Dead-Lock kommen. Du musst einen eigenen Therad verwenden um die Ausgabe zu lesen.

    Eine korrekte Implementierung findest Du hier:
    http://support.microsoft.com/kb/190351

    Beachte auch, dass die Anwendung es explizit verhindern kann, dass die Ausgaben umgeleitet werden. SIehe auch obiger Link.

    Probiere es zuerst in der Commandozeile via < / > aus. Wenn es da geht, dann geht es auch mit der Lösung im Link.



  • Martin Richter schrieb:

    In der Pipe kommt von Deiner Anwendnung nichts an. Punkt. Vermutlich gibt die andere Anwendung nichts aus...

    Du hast schon beide Posts von mir gelesen? Auf Anmerkung von dot habe ich bereits explizit gesagt, dass das Fenster das die Redirect Nachrichten erhalten soll, diese auch erhält und ausgibt. Lediglich, wenn das Child Programm fertig ist werden keine Nachrichten mehr ausgegeben (was ja logisch ist) , aber an besagter Codestelle guggst du oben verliert sich die Ausführung des Codes.

    @Jochen Kalmbach
    danke, der Beispielcode der auf der von dir verlinkten Seite steht funktioniert einwandfrei. Ich werde versuchen mir daraus eine entsprechende Funktion zu schreiben. good job!



  • CloseHandle wird an falscher Stelle ausgeführt, dadurch läuft dein ReadFile nach Beenden des Child Processes ins Leere. Führe

    CloseHandle(hOutputReadTmp);
                CloseHandle(hInputWriteTmp);
                CloseHandle(hOutputWrite);
                CloseHandle(hErrorWrite);
                CloseHandle(hInputRead);
    

    vor

    if((ReadFile(hOutputRead, lpBuffer, sizeof(lpBuffer) - 1, &nBytesRead, NULL) == FALSE) || (nBytesRead == 0)){
                    if(GetLastError() == ERROR_BROKEN_PIPE){
                        break;
                    }
                }
    

    aus


Anmelden zum Antworten