I often (really, very often) write console programs. Most of them are simple test programs to test algorithms, calculations or language features, or stuff copied from StackOverflow.
But console programs, if run from the IDE, or from the Windows Explorer, have one annoying feature: they close immediately if they are finished. So if my program has many
Writelns in it, they simply rush by and the console window closes before I can inspect the output. To avoid that, I often put
Readln; in the last line of the program. If the program is finished, it pauses and waits for me to press Enter.
But such a
Readln; is annoying if I really want to run the program from an existing console window (aka a Windows command line). Then I don't want to have to press Enter, because the output is shown in the current console window already, and that won't close until I tell it to.
To get the best of both worlds, I wrote my simple
Velthuis.AutoConsole unit. Put it in the
uses clause of your console program and, if the program is a console program and it was started from the command line, or if it is not a console program, it will do nothing. But if it is a console program and it was started any other way (from the Windows Explorer, from the Delphi IDE with or without debugger, from another non-console program), then, before the console window can close, it will display:
Press any key...
Then I really only have to press a key (it does not have to be Enter, it can be any key) and the program will end, closing the console Window.
I placed the new unit in the zip for my Console unit. You can download it from the page I linked to.
Here is the code of this simple unit. I think I may have to add a
ConsoleCtrlHandler, so the window is not closed when the user presses Ctrl+C or closes the console window with the
x close button on the window frame. But I am not sure if that is necessary. If I press those, I usually want to stop the program anyway. Comments on this are welcome.
unit Velthuis.AutoConsole; interface implementation uses Velthuis.Console, // as described in the link above Winapi.Windows; function GetConsoleWindow: HWnd; stdcall; external 'kernel32.dll' name 'GetConsoleWindow'; function StartedFromConsole: Boolean; var ConsoleHWnd: THandle; ProcessId: DWORD; begin ConsoleHwnd := GetConsoleWindow; if ConsoleHWnd <> 0 then begin GetWindowThreadProcessId(ConsoleHWnd, ProcessId); Result := GetCurrentProcessId <> ProcessId; end else Result := False; end; procedure Pause; begin if IsConsole and not StartedFromConsole then begin Write('Press any key... '); ReadKey; end; end; initialization finalization Pause; end.
I removed the reliance on the
Velthuis.Console unit. I added this piece, a simplified version of
ReadKey, which does not try to translate the key, making things a lot simpler:
procedure WaitForInput; var InputRec: TInputRecord; NumRead: Cardinal; OldKeyMode: DWORD; StdIn: THandle; begin StdIn := GetStdHandle(STD_INPUT_HANDLE); GetConsoleMode(StdIn, OldKeyMode); SetConsoleMode(StdIn, 0); repeat ReadConsoleInput(StdIn, InputRec, 1, NumRead); until (InputRec.EventType and KEY_EVENT <> 0) and InputRec.Event.KeyEvent.bKeyDown; SetConsoleMode(StdIn, OldKeyMode); end;
and changed the
Pause procedure a little:
procedure Pause; begin if IsConsole and not StartedFromConsole then begin Write('Press any key... '); WaitForInput; end; end;