A Delphi console application can be run from the command line of an existing console window, and it can be run by double-clicking on its icon. In the latter case it will create its own console window, and close it once the application terminates.
How can I tell if my console application has created its own window?
I want to detect this so that I can display a message like "Press Enter to close the window", to let the user read what's displayed before the window closes. Obviously, it wouldn't be appropriate to do that if the application is being run from the command line.
I'm using Delphi 2010, in case that's significant.
I use (can't remember where I found it):
And then use it as such:
Wow Nick, that is really impressive! I have test your solution and works great.
So you can do something like this:
And finally:
Cheers mate!
Erwin Haantjes
I know, this is a old thread but i have a nice solution to this.
You don't have to mess around with batch files. The trick is in the type of exe, it's subsystem attribute. After compiling the exe as GUI application (without the {$APPTYPE CONSOLE} directive, you must change it's subsystem attribute IMAGE_SUBSYSTEM_WINDOWS_GUI to IMAGE_SUBSYSTEM_WINDOWS_CUI. Nice thing is when you execute the console app from a console it doesn't show an extra console window and at that point you don't need a message like "Press Enter to close the window". EDIT: In case you starting another console app inside a console app like i did in a project of mine)
When you run it from explorer etc by clicking it or by start|run, Windows opens automaticly a console window when the subsystem attribute is IMAGE_SUBSYSTEM_WINDOWS_CUI. You don't need to specify {$APPTYPE CONSOLE} directive, it's all about the subsystem attribute.
The solution of RRUZ is a solution i also using but with one important difference. I check the subsystem of the parent process to show a "Press Enter to close this window". RUZZ it's solution only works in two cases, when it is cmd or explorer. By simply check if it's parent process has the attribute is NOT IMAGE_SUBSYSTEM_WINDOWS_CUI, you can display the message.
But how to check the exe subsystem? I found a solution on torry tips (http://www.swissdelphicenter.ch/torry/showcode.php?id=1302) to get the PE Header info and modify it into two functions: setExeSubSys() and getExeSubSys(). With the setExeSubSys() i made a little console app so that i can change the exe's subsystem attribute after compiling (it is only 50 kb!).
After you have the parent/potential process filename, you can simply do something like this:
Here are the two functions i made but it is not working with streams (like the torry example), i use my own easy unit for files for it without the silly exeption stuff. But basically i think you get the idea around it.
To set (and also to get when you not specifying a pointer to a longint (nil)):
To get:
If you want more info at the subsystem, just google or go to the MSDN website. Hope it was helpful to anyone.
Greetz, Erwin Haantjes
I've used something like the below in the past:
You have basically two things to test for:
Is the application console shared between processes? If you use
cmd.exe
to run a console application it will per default share the console, so you won't need to show the "Press Enter to close the window" message.Is the output redirected to a file? If so it's not necessary to show the message either.
For the first one there is a simple solution in form of the
GetConsoleProcessList()
Windows API function. Unfortunately it is available only on Windows XP and later versions, but maybe that's good enough for you. It's not in the Delphi 2009Windows
unit, so you will have to import it yourself:Of course, if your software is otherwise able to run on earlier Windows versions you should use
LoadLibrary()
andGetProcAddress()
instead.Since you are only interested in whether the number of process handles is higher than 1 you can call it with a very small buffer for the handles, for example like this:
If your handle count is larger than 1 you have other processes keeping the console open, so you can skip showing the message.
You can use the
GetFileInformationByHandle()
Windows API function to check whether your console output handle references a real file or not:This code is intended to get you started only, I'm sure there are some corner cases not handled properly.
For a program foo.exe, make a batch file named foo_runner.bat. Don't document that command, since it's not intended to be used by name by anyone, but use it as the target of any shortcut icons your installer makes. Its contents will be simple:
That
%~dp0
part gives the directory where the batch file lives, so you're ensured of running the foo.exe in the batch file's directory instead of grabbing one from some other place on the search path.