Konsolen-Ausgabe eines Win32-GUI Programms
-
Hi,
viele von Euch kennen sicherlich die Eingabeaufforderung (unter WinXP zu finden unter Startmenü -> Programme -> Zubehör -> Eingabeaufforderung), auch Win32-Konsole genannt.
Man kann die Eingabeaufforderung durch Eingabe mit "exit" verlassen.Nun, ich habe ein Problem mit der Ausgabe meiner Win32-GUI Applikation in diese Eingabeaufforderung.
Ich möchte eine Kurzhilfe zu den verfügbaren Kommandozeilen-Optionen anzeigen.
Dazu verwende ich printf(), um genauer zu sein die TCHAR-Variante _tprintf(). Diese geben einen formatierten String an den standard output stream "stdout" aus.Szenario 1 (Eingabeaufforderung normal):
Eingabe von "programm.exe -help"Szenario 2 (Eingabeaufforderung mit Umlenkung in eine Textdatei):
Eingabe von "programm.exe -help > output.txt"Wenn ich eine Applikation als Win32-Konsole mit dem Einsprungpunkt main() programmiere, ist die Ausgabe in beiden Szenarien einwandfrei.
Habe ich jedoch eine (andere) Applikation als Win32-GUI mit dem Einsprungpunkt WinMain() programmiert, funktioniert die Ausgabe leider nur in Szene 2 einwandfrei. Die Datei "output.txt" enthält den vollständigen Text meiner Ausgabe.
Die Ausgabe in Szene 1 bleibt dagegen unsichtbar (oder wird irgendwohin umgeleitet), auch sind keine Zeilenvorschübe zu erkennen.Der Programmname und die Kommandozeilen-Optionen werden in beiden Szenen einwandfrei erkannt, ich verwende GetCommandLine().
Woran könnte das liegen?
Muß ich irgendwelche Pipes einrichten?
Oder kann man den "standard output stream" konfigurieren?
(Win XP SP2, Win32-API, kein MFC o.ä.)Martin
P.S.: Da es sich um eine Win32-API GUI Applikation ist, habe ich deshalb die Frage hier und nicht in den Forum-Bereich "DOS und Win32-Konsole" gestellt.
-
GUI-Applikationen können per default nicht auf die Console schreiben...
Wenn Du ein Consolen-Programm brauchst, dann Rate ich zu folgendem:
Erstelle eine Consolen-Anwendung, welche die Kommandozeilenparameter einliest und optional den Hilfetextausgibt und sich beendet. Ansonsten soll dies Programm das "echte" GUI-Programm starten.
Dieses Consolen-Programm benennst Du genau glaich wie das GUI-Programm, ausser dass Du die Dateiendung von "exe" nach "com" änderst!Das hat jetzt genau das Verhalten was Du suchst...
-
Hya!
Programmier ne Win32 Anwendung. Checke Parameter. Schreibe in die Konsole, indem du AllocConsole, (FreeConsole) aufrufst.
MfG
-
so? schrieb:
Schreibe in die Konsole, indem du AllocConsole, (FreeConsole) aufrufst.
Danke für den Hinweis, werde ich am Wochenende ausprobieren und testen.
Martin
-
Jochen Kalmbach schrieb:
Erstelle eine Consolen-Anwendung, welche die Kommandozeilenparameter einliest und optional den Hilfetextausgibt und sich beendet. Ansonsten soll dies Programm das "echte" GUI-Programm starten.
Dieses Consolen-Programm benennst Du genau glaich wie das GUI-Programm, ausser dass Du die Dateiendung von "exe" nach "com" änderst!Das hat jetzt genau das Verhalten was Du suchst...
Danke für den Vorschlag.
Irgendwie klingt das trotzdem eher mehr nach einer "Krückenlösung", denn nach einer "nahtlosen" Integration.
Martin
-
Nachtrag:
Durch die Suche nach dem Begriff AllocConsole() bin ich auf die folgenden weiterführenden Themen gestoßen:"INFO: Calling CRT Output Routines from a GUI Application" http://support.microsoft.com/kb/105305
"How To Attach a Console Window to Your Visual Basic Program" http://support.microsoft.com/kb/171654
Es sieht auf den ersten Blick so aus, daß ich nun genug Infos beisammen habe, um mein Problem elegant lösen zu können.
(Ohne ein Zweit-Programm nach Jochen's Vorschlag zu Hilfe nehmen müssen).Martin
-
Deine Vermeindliche Lösung ist keine!
Der große Haken an Deiner Lösung ist: Dein Programm *wartet* nicht, bis die Ausgabe beendet wurde!!! sondern führt sofort die nächste Consolen-Anweisung aus (z.B. in einer Batch-Datei).
Dies ist sehr unschön.Lass es Dir sagen... die einzige vernünftige Lösung ist via *.com-Anwendung.
So machen es alle mir bekannten GUI&Consolen-Applikatonen (z.B: Visual Studios "devenv").
-
Jochen Kalmbach schrieb:
Deine Vermeindliche Lösung ist keine!
Der große Haken an Deiner Lösung ist: Dein Programm *wartet* nicht, bis die Ausgabe beendet wurde!!! sondern führt sofort die nächste Consolen-Anweisung aus (z.B. in einer Batch-Datei).
Dies ist sehr unschön.Lass es Dir sagen... die einzige vernünftige Lösung ist via *.com-Anwendung.
So machen es alle mir bekannten GUI&Consolen-Applikatonen (z.B: Visual Studios "devenv").
Von Haus aus wartet da nichts, aber man kann es so programmieren -> Der Konsolen-Hilfe-Funktion einen eigenen Thread spendieren.
Im Falle von myProg.exe -help kann doch mittels WaitForSingleObject auf die Konsolenantwort gewartet und je nach Rückgabewert des Konsolenthreads mit dem Programm fortgefahren, bzw. dieses beendet werden.
-
so? schrieb:
Von Haus aus wartet da nichts, aber man kann es so programmieren -> Der Konsolen-Hilfe-Funktion einen eigenen Thread spendieren.
Im Falle von myProg.exe -help kann doch mittels WaitForSingleObject auf die Konsolenantwort gewartet und je nach Rückgabewert des Konsolenthreads mit dem Programm fortgefahren, bzw. dieses beendet werden.Bitte erklär mir mal wie das gehen soll?
-
Die Umleitung in eine Textdatei wäre dann allerdings selbst zu schreiben ( Parameter parsen. )
#include <windows.h> #include <stdio.h> /* Declare Windows procedure */ LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM); /* Make the class name into a global variable */ char szClassName[ ] = "Big Brohters Help-Console-Demo"; HANDLE hOut, hIn; int MyHelp() { // TODO: implement function. return 0; } DWORD WINAPI HelpFuncThread ( LPVOID pt ) { DWORD dummy; char* BBwelcome = "Hi Brother! Wecome to my Help-Console-Demo!\n\n"; char* Menu = "1: Quit\n" "2: Continue"; // "3: Show Help // TODO: implement help. INPUT_RECORD ir = {0}; COORD CursorPos = {0,4}; WriteConsole( hOut, BBwelcome, strlen(BBwelcome), &dummy, NULL ); WriteConsole( hOut, Menu, strlen(Menu), &dummy, NULL ); SetConsoleCursorPosition( hOut, CursorPos ); do { ReadConsoleInput( hIn, &ir, 1, &dummy ); WriteConsoleOutputCharacter( hOut, &ir.Event.KeyEvent.uChar.AsciiChar, 1, CursorPos, &dummy ); } while ( ir.Event.KeyEvent.uChar.AsciiChar != '1' && ir.Event.KeyEvent.uChar.AsciiChar != '2' ); // && ir.Event.KeyEvent.uChar.AsciiChar != '3' ); return ir.Event.KeyEvent.wVirtualKeyCode - 48; } int WINAPI WinMain (HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nFunsterStil) { HWND hwnd; /* This is the handle for our window */ MSG messages; /* Here messages to the application are saved */ WNDCLASSEX wincl; /* Data structure for the windowclass */ HANDLE hHelpFuncThread; DWORD dw; char* disclaimer= "Usage: call this program with the -help parameter " "in the console."; if ( lpszArgument && ( 0 == strcmp ( lpszArgument, "-help" ))) { AllocConsole(); hOut = GetStdHandle ( STD_OUTPUT_HANDLE ); hIn = GetStdHandle ( STD_INPUT_HANDLE ); hHelpFuncThread = CreateThread ( NULL, 0, HelpFuncThread, NULL, 0, &dw ); WaitForSingleObject ( hHelpFuncThread, INFINITE ); GetExitCodeThread( hHelpFuncThread, &dw ); FreeConsole(); if ( dw == 1 ) ExitProcess (0); if ( dw == 3 ) MyHelp(); // To be written // Implizites 'auto continue', wenn dw == 2 :) } /* The Window structure */ wincl.hInstance = hThisInstance; wincl.lpszClassName = szClassName; wincl.lpfnWndProc = WindowProcedure; /* This function is called by windows */ wincl.style = CS_DBLCLKS; /* Catch double-clicks */ wincl.cbSize = sizeof (WNDCLASSEX); /* Use default icon and mouse-pointer */ wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION); wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION); wincl.hCursor = LoadCursor (NULL, IDC_ARROW); wincl.lpszMenuName = NULL; /* No menu */ wincl.cbClsExtra = 0; /* No extra bytes after the window class */ wincl.cbWndExtra = 0; /* structure or the window instance */ /* Use Windows's default color as the background of the window */ wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND; /* Register the window class, and if it fails quit the program */ if (!RegisterClassEx (&wincl)) return 0; /* The class is registered, let's create the program*/ hwnd = CreateWindowEx ( 0, /* Extended possibilites for variation */ szClassName, /* Classname */ "Big Brohters Help-Console-Demo", /* Title Text */ WS_OVERLAPPEDWINDOW, /* default window */ CW_USEDEFAULT, /* Windows decides the position */ CW_USEDEFAULT, /* where the window ends up on the screen */ 544, /* The programs width */ 375, /* and height in pixels */ HWND_DESKTOP, /* The window is a child-window to desktop */ NULL, /* No menu */ hThisInstance, /* Program Instance handler */ NULL /* No Window Creation data */ ); /* Make the window visible on the screen */ ShowWindow (hwnd, nFunsterStil); if ( lpszArgument && ( 0 != strcmp ( lpszArgument, "-help" ))) TextOut ( GetDC(hwnd), 0, 0, disclaimer, strlen(disclaimer)); /* Run the message loop. It will run until GetMessage() returns 0 */ while (GetMessage (&messages, NULL, 0, 0)) { /* Translate virtual-key messages into character messages */ TranslateMessage(&messages); /* Send message to WindowProcedure */ DispatchMessage(&messages); } /* The program return-value is 0 - The value that PostQuitMessage() gave */ return messages.wParam; } /* This function is called by the Windows function DispatchMessage() */ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) /* handle the messages */ { case WM_DESTROY: PostQuitMessage (0); /* send a WM_QUIT to the message queue */ break; default: /* for messages that we don't deal with */ return DefWindowProc (hwnd, message, wParam, lParam); } return 0;
-
Ich glaube Du hast nicht verstanden was der OP will... Wo steht das was von Eingaben?
Was ändert das daran, dass die Console sofort wieder freigegeben wird und in einer Batch-Datei der nächste Befehl ausgeführt wird?
-
Die Eingabe ist doch nur eine weiter Möglichkeit der Interaktion.
Klar kann man die weglassen.
Den Zeitpunkt zum Beenden des Threads kann man doch auch ändern. Von sofort, auf später bis zum Programmende, z.B.
-
Und was hat der Thread damit zu run, dass die COnsoel nicht *wartet* bis der Prozess beendet wird?
-
War doch deine Frage. *grins*
-
Möglicherweise sollte man mal von der Konsole komplett Abstand nehmen und sich nur die Anforderungsliste anschauen. Kommandozeilenparameter "-help" gibt die Hilfe auf den Bildschirm aus und "-help >file.txt" gibt die Hilfe in eine Datei aus. Frage: welche Möglichkeiten haben wir, das zu realisieren?
-
Ich habe meine Antwort schon gegeben... mir sind keine andere Lösungen bekannt... das ">" setzt eine Consolen-Anwenung voraus...
-
Jochen Kalmbach schrieb:
Ich habe meine Antwort schon gegeben... mir sind keine andere Lösungen bekannt... das ">" setzt eine Consolen-Anwenung voraus...
Wenn ich dich richtig verstehe, akzeptiert eine Winapi Anwendung kein ">" in der Kommandozeile?
-
Was ist denn eine WinAPI Anwendung? Sowohl Consolen- and auch Windows-Anwendungen sind WinAPI-Anwendungen...
Und das ">" hat primär nichts mit der Anwendung zu tun, sondern ist ein Feature des "Command-Prozessors" (i.d.R. cmd.exe).
-
Jochen Kalmbach schrieb:
Was ist denn eine WinAPI Anwendung? Sowohl Consolen- and auch Windows-Anwendungen sind WinAPI-Anwendungen...
Und das ">" hat primär nichts mit der Anwendung zu tun, sondern ist ein Feature des "Command-Prozessors" (i.d.R. cmd.exe).Ok dann formuliere ich meine Frage eben so: was mache eine normale Windowsfensteranwendung wenn man ">file.txt" in die Kommandozeile schreibt?
-
winapi noob schrieb:
Ok dann formuliere ich meine Frage eben so: was mache eine normale Windowsfensteranwendung wenn man ">file.txt" in die Kommandozeile schreibt?
Nix. Die Datei ist genau 0 Byte groß.
Und probier endlich mal selber aus, was Du uns hier weismachen willst!