Ausgabe in Dosbox/Konsole von der ein Windows Programm gestartet wurde...



  • Ich habe im Moment ein kleines Problem mit meiner Windows Applikation unter Visual C++ 2003:

    Wenn das Programm ohne Parameter gestartet wird, soll es sich wie ein normales Windows Programm verhalten. Wird das Programm allerdings von einer Windows Dosbox bzw. Konsole gestartet, dann soll es unsichtbar im Hintergrund arbeiten und nur ein paar logging Informationen auf der Konsole ausgeben.

    Das Problem ist jedoch, dass der stdout Kanal im Gegensatz zu einer Win32 Konsolenapplikation deaktiviert ist. Man kann zwar eine neue Konsole erstellen, was angesichts eines bestehenden Konsolenfensters aber ziemlich überflüssig ist.

    Im Prinzip sollte es zwei Lösungen für dieses Problem geben:

    1.) Man findet einen Weg den Handle zur aufrufenden Dosbox zu bekommen und den stdout Kanal dann auf diesen zu linken. Ist das mit vertretbarem Aufwand machbar?

    2.) Man wandelt das ganze Win32 Programm einfach in eine Win32 Konsolenapplikation um, da es ja anscheinend möglich ist aus einer Konsolenanwendung auch Windows Fenster zu starten.
    Die Frage ist jedoch zum einen ob das nachträglich noch mit Visual C++ geht und wenn wie, und zum anderen, wo wäre da der Haken? Es gäbe sicherlich keine speziellen Windows Applikationen, wenn ich mit einer Win32 Konsolenanwendung die vollen Window Interface Features und die vollen Konsolenfeatures zur Verfügung hätte. Da würde ja keiner mehr eine reine Windows Applikation benutzen.



  • Zu 1 habe ich mal eine Lösung im Netz gefunden. Kompilieren und die Objektdatei mit der Windows-Anwendung zusammenlinken. In der Windows-Anwendung die Funktion deklarieren und einmal aufrufen. Fortan kannst Du via printf/cout auf die Konsole schreiben:

    #include <windows.h>
    #include <stdio.h>
    #include <fcntl.h>
    #include <io.h>
    #include <iostream>
    #include <fstream>
    
    using namespace std;
    
    // maximum mumber of lines the output console should have
    const WORD MAX_CONSOLE_LINES = 500;
    
    void RedirectIOToConsole()
    {
    	int hConHandle;
    	long lStdHandle;
    	CONSOLE_SCREEN_BUFFER_INFO coninfo;
    	FILE *fp;
    
    	// allocate a console for this app
    	AllocConsole();
    
    	// set the screen buffer to be big enough to let us scroll text
    	GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE),	&coninfo);
    	coninfo.dwSize.Y = MAX_CONSOLE_LINES;
    	SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE),	coninfo.dwSize);
    
    	// redirect unbuffered STDOUT to the console
    	lStdHandle = (long)GetStdHandle(STD_OUTPUT_HANDLE);
    	hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
    
    	fp = _fdopen( hConHandle, "w" );
    
    	*stdout = *fp;
    	setvbuf( stdout, NULL, _IONBF, 0 );
    
    	// redirect unbuffered STDIN to the console
    	lStdHandle = (long)GetStdHandle(STD_INPUT_HANDLE);
    	hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
    
    	fp = _fdopen( hConHandle, "r" );
    
    	*stdin = *fp;
    	setvbuf( stdin, NULL, _IONBF, 0 );
    
    	// redirect unbuffered STDERR to the console
    	lStdHandle = (long)GetStdHandle(STD_ERROR_HANDLE);
    	hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
    
    	fp = _fdopen( hConHandle, "w" );
    
    	*stderr = *fp;
    	setvbuf( stderr, NULL, _IONBF, 0 );
    
    	// make cout, wcout, cin, wcin, wcerr, cerr, wclog and clog
    	// point to console as well
    	ios::sync_with_stdio();
    }
    


  • Ja diese Lösung habe ich auch schon probiert. Allerdings wird hierbei ein neues Konsolenfenster gestartet und nicht das alte benutzt.

    Im Moment benutze ich daher gezwungenermaßen ein log file.



  • wenn du deine application über cmd startest gibts die konsole doch eh shon ?
    die console ist mindestens ein fenster des desktop fensters, kannst dan FindWindowEx machen, oder du machst es so:

    zuerst den consolen Titel finden dann, deine Console einen neuen namen geben und dann über FindWindow dein fenster suchen.. dann gibts den window Handle ab.

    oder die genauere variante:

    #include <windows.h>
    #include <stdio.h>
    #pragma comment(lib, "user32.lib")
    
    //---------------------------------------------------------------------------
    
    BOOL CALLBACK EnumThreadWndProc(HWND hwnd, LPARAM lParam); 
    #pragma argsused
    
    BOOL CALLBACK EnumThreadWndProc(HWND hwnd, LPARAM lParam) // gibt das Handle der Console zurück
    {
    LPDWORD lpdwProcessId;
    // zum vergleichen die Process ID des Gefundenen Handle suchen
    GetWindowThreadProcessId(hwnd,lpdwProcessId); 
    printf("%d",lpdwProcessId); // zum vergleich nochmal die Prozess id
    return TRUE;
    }
    
    int main(int argc, char* argv[])
    {
       printf("%d \n",GetCurrentThreadId()); // dein CallingProcessThreadID
      EnumThreadWindows(GetCurrentThreadId(), EnumThreadWndProc, 0);
      getc(stdin); 
      return 0;
    }
    


  • oder so:

    //---------------------------------------------------------------------------
    
    #pragma hdrstop
    #define STRICT 0x0001
    #include <windows.h>
    #include <stdio.h>
    #include <stdarg.h>
    #pragma comment(lib, "user32.lib")
    
    DWORD ProcessID;
    BOOL CALLBACK EnumThreadWndProc(HWND hwnd, LPARAM lParam);
    
    BOOL CALLBACK EnumThreadWndProc(HWND hwnd, LPARAM lParam)
    {
    int cTxtLen;
    PSTR pszMem;
    DWORD lpdwProcessId;
    LPTSTR  windowName;
    
    GetWindowThreadProcessId(hwnd,&lpdwProcessId);
    if (ProcessID==lpdwProcessId) {
    pszMem = (PSTR) VirtualAlloc((LPVOID) NULL,
    					(DWORD) (cTxtLen + 1), MEM_COMMIT,
    					PAGE_READWRITE);
    GetWindowText(hwnd, pszMem,cTxtLen + 1);
    printf("%s ",pszMem); //gibt dann den Namen des Gefundenen Fensters aus
    return FALSE; // beende Enumaration da eh gefunden was gesucht
    }
    
    return TRUE;
    }
    
    int main(int argc, char* argv[])
    {
    ProcessID=GetCurrentProcessId();
    EnumWindows(EnumThreadWndProc, 0);
    	getc(stdin);
    	return 0;
    }
    //---------------------------------------------------------------------------
    

Anmelden zum Antworten