How to close a console created with AttachConsole() by a GUI app without exiting the GUI app
I created a Windows GUI app (for example, it has a taskbar icon) that also uses a console. (console as in conhost.exe) Yes, I am aware this doesn't work as well on Windows as it does on Linux. On program launch the app does not create an attached console. One of the menu items of the taskbar icon, however, does allow you to create an attached console. When created, this attached console displays information from the program as it runs. I want to have a way to completely get rid of the console without exiting my app when I am done reading that information. My problem is that if I click the Close button (little "X" on the top right of the window) on the console then both the console AND my app terminate. Right now I am hiding the console window using ShowWindow() WinAPI as a work around but this leaves the console running in the background - i.e. it is visible in Task Manager.
Potential solutions that I am aware of:
1) Create a separate child program that owns the Console. Then send messages from the main app to the child app when I want to write to the console. That way when I completely close the console only the child app will be terminated. Then if I need the console again I can respawn the child app. The downside seems to be that I would need to write and maintain the code for this separate child app and that debugging would become more complicated. Also, I would want to write the child app to automatically close itself if the parent app gets closed which is additional functionality I would need to implement. Basically, this option adds complexity.
2) Use a "fake" console window that merely approximate the visual appearance and behavour of a console but is not actually a console. Unfortunately the examples of these "fake" consoles that I have found online are not great and I don't want to implement one from scratch.
20 Replies
3) Try to launch conhost.exe as a child process (instead of using AttachConsole()) and somehow send my text to it for display if possible.
4) Find a way to actually disconnect and completely close (i.e. terminate the conhost.exe console process) without terminating my app even though my app owns the console via AttachConsole(). I have tried to do this but haven't found a solution yet. Everything I try causes the main app to also terminate.
Question: Any ideas how to get option #4 above working? If not, how about option #3? I really want to avoid options #1 and #2 if possible.
Thank you for any help!
Does the console just display information? Or does it take user input as well?
Hi Andrew, it only displays information
I would always question why you need a console to display information 🙂 . Otherwise, option 3 isn't too bad.
Basically I want to avoid doing the equivalent "tailing" a log file. How would I go about option #3?
Process Class (System.Diagnostics)
Provides access to local and remote processes and enables you to start and stop local system processes.
it has input/output as properties that are streams https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.process.standardinput?view=net-8.0
Process.StandardInput Property (System.Diagnostics)
Gets a stream used to write the input of the application.
Ok, I understand what you are saying. And conshost.exe actually allows you to run it without "attaching" it? Also, I am wondering if conhost.exe is actually even the correct executable name depending on the version of Windows the user is on?
I guess it depends. Are you using a built in tool to tail a log file? If you're just trying to avoid the idea of having a "tail" function that's fairly easy to do in UI with a limit size queue
Right now I write messages to a ring buffer. If the user decides to open the console then any information in the ring buffer gets sent to the console and then subsequent message go directly to the console and the ring buffer is no longer used. I am not writing anything to a file and I want to avoid using a log file and a tool to tail a log file. I don't want to build my own "fake" console (which is what I think you are saying is fairly easy) which would be option #2. The reason I don't want option #2 is because I actually like the functionality of the "real" console such as changing font size on the fly, easy multiline select for copying text, etc. Does that make sense?
what UI technology are you using?
Winforms
TextBox should already have good multiline select etc, is the font scaling the only thing you're missing?
The console also has a limited buffer size so that if I dump a lot of text to it of the course of several days then only the last N messages are kept. That's nice so I don't run out of memory. I don't know if the "limit size queue" thing you mentioned applies to the TextBox and might provide the same functionality?
yup, the easiest implementation would be straight forward
There may be more performant ways but that should be sufficient and get you going in the right direction
Thank you. But my understanding is that if you use a TextBox (with the queue you are showing) you end up needing to blow away the entire contents of the TextBox each time you write to it in order to fake the "limited buffer size" which is not ideal if you are trying to watch the information scroll by, right?
Is that correct or am I missing something?
this is where I'm less familiar with Winforms than WPF. I would do a databinding view of the queue in WPF and always scroll to bottom. Unfortunately I don't know the equivalent in winforms, but I do know it probably exists.
if you're still stuck with always wanting a console,
Process
is the way to go instead of AttachConsole
. Likely with cmd.exe
hmmmm, I also have the option of using WPF, but I know almost nothing about WPF and know Winforms reasonably well - the reverse for you. I like your idea about using Process with cmd.exe though - I think that might be my best option
@Andrew (ryzngard | they/them) Any chance I could get your opion on my two questions from earlier today? https://discord.com/channels/143867839282020352/1210662648241197116 and https://discord.com/channels/143867839282020352/1210625651393175664
it may be a bit, I'm about to be heads down coding for a few things.
I'll take a look later if I can though
Ok, thank you for the help
bump