To be or not to be (a console app)
Although I'm not a great Linux fan, I often find myself building Windows apps that were originally written for Linux. The code is usually sprinkled with printf() statements and the like which can occasionally be useful at run time.
One of the nicer features of Linux is that apps aren't tied to being either a console app or a GUI app. If you double-click an app's icon it launches as a GUI app. However, if you open a terminal and launch the app from that, you'll see the GUI app but also see its console output.
AFAIK this isn't easy to achieve on Windows. Whether or not an app has a console is a build time decision, not a run time decision. So if you specify System:Console you'll always get a console, no matter how you launch the app. OTOH if you specify System:Windows you'll never see any console output, not even if you launch from a terminal.
The Linux approach is superior IMHO. Anyone know of any tricks for emulating it in a Windows app?
Re: To be or not to be (a console app)
This seems like what you want:
Code:
#include <windows.h>
#include <iostream>
#include <cstdio>
bool IsAConsole( HANDLE Handle )
{
DWORD Mode;
return GetConsoleMode( Handle, &Mode ) != 0;
}
FILE* MapStdToConsole()
{
FILE* File = NULL;
HANDLE StdOut = GetStdHandle( STD_OUTPUT_HANDLE );
if( StdOut && AttachConsole( ATTACH_PARENT_PROCESS ) )
{
if( IsAConsole( StdOut ) )
File = freopen( "CONOUT$", "w", stdout );
}
return File;
}
class cConsoleInitializer
{
FILE* File;
public:
cConsoleInitializer()
{
File = MapStdToConsole();
}
~cConsoleInitializer()
{
if( File )
{
INPUT_RECORD InputRecord;
InputRecord.EventType = KEY_EVENT;
InputRecord.Event.KeyEvent.bKeyDown = TRUE;
InputRecord.Event.KeyEvent.dwControlKeyState = 0;
InputRecord.Event.KeyEvent.uChar.UnicodeChar = VK_RETURN;
InputRecord.Event.KeyEvent.wRepeatCount = 1;
InputRecord.Event.KeyEvent.wVirtualKeyCode = VK_RETURN;
InputRecord.Event.KeyEvent.wVirtualScanCode = MapVirtualKey( VK_RETURN, 0 );
DWORD Written = 0;
WriteConsoleInput( GetStdHandle( STD_INPUT_HANDLE ), &InputRecord, 1, &Written );
fclose( File );
FreeConsole();
}
}
};
Just construct a cConsoleInitializer.
Re: To be or not to be (a console app)
Completing what Joeman already answered:
If you really need that kind of ostrich-camel, no problem:
- In a console application (built using /SUBSYSTEM:CONSOLE), you can add any GUI stuff your muscles want.
To hide/show the console window, you can get a hadle with GetConsoleWindow, then call ShowWindow. - In a non-console application you can create and attach a console with AllocConsole.
No sweat, like a walking in the park.
// I'm wondering how easy the *nix guys can do the same. ;)
Re: To be or not to be (a console app)
Thanks guys. AllocConsole() and AttachConsole() are two functions I'd never heard of but they do seem quite promising. I'll try Joeman's suggestion first.
Ovidiucucu - yours is a good idea but I've seen that done before and it tends to look clumsy at runtime. If you double-click to open the app, a console window appears very briefly then shuts down which doesn't tend to look nice. It's quite common in apps built with MinGW I've found. Your 2nd suggestion about AllocConsole() looks a bit more promising.
In any case, the key to success here lies in the GUI app being able to detect "how" it was launched (i.e. was it launched by double-clicking its icon / was it launched by some other process / or was it launched from a command line). Any ideas about how to test for that at run time?
Re: To be or not to be (a console app)
I found some ideas at stackoverflow that seems to do the trick http://stackoverflow.com/questions/5...-explorer-or-n
Re: To be or not to be (a console app)
Quote:
Originally Posted by
John E
... I've seen that done before and it tends to look clumsy at runtime. If you double-click to open the app, a console window appears very briefly then shuts down which doesn't tend to look nice.
One solutin is to make a little "launcher" application which creates the console in "hidden" mode.
Quote:
Originally Posted by
John E
In any case, the key to success here lies in the GUI app being able to detect "how" it was launched (i.e. was it launched by double-clicking its icon / was it launched by some other process / or was it launched from a command line). Any ideas about how to test for that at run time?
You can enumerate the processes (using WMI or Tool Help Library) and find the parent process (the process which launched the current one).
But this is not very reliable. Just imagine the parent process is no longer running.
Anyhow, why do you need that? I can't get any practical reason.
Re: To be or not to be (a console app)
Quote:
Originally Posted by
ovidiucucu
Anyhow, why do you need that? I can't get any practical reason.
In Linux it's genereally used so that Release builds which don't work properly can give some feedback to the user. It can be especially helpful if the app fails while launching. In Windows we'd usually display a suitable dialog box maybe - or write to a log file but most Linux programs simply write something to stderr or stdout. When you launch the app normally (by double-clicking its icon) you don't see the output. But if the app encounters some kind of problem while launching you can retry it from a command line which lets you see the program's output. It's not the way I'd write a Windows program but it can be useful if I'm converting a program that was originally written for Linux.
Re: To be or not to be (a console app)
On Windows you can use OutputDebugString and DebugView to achieve that.
Re: To be or not to be (a console app)
Well then, try "Thinking in Windows" and get rid of linux-specific stuff. ;)
[ later edit ]
I think, D_Drmmr got better what you want to accomplish. This case, you don't need console at all..
Re: To be or not to be (a console app)
Quote:
Originally Posted by
ovidiucucu
Well then, try "Thinking in Windows" and get rid of linux-specific stuff. ;)
Oh, if only life were that simple.... :) I'm being slowly driven mad by Linux and its quirks but just occasionally, it has some neat ideas! :D
Quote:
Originally Posted by
ovidiucucu
[ later edit ]
I think, D_Drmmr got better what you want to accomplish. This case, you don't need console at all..
Unfortunately, the same code (i.e. the printfs) still need to still work on Linux and OS-X.
But if someone could come up with a cross-platform version of DebugView. Hmmm.... that's a money spinning opportunity if ever I heard one..! :thumb:
Re: To be or not to be (a console app)
Quote:
Originally Posted by
John E
But if someone could come up with a cross-platform version of DebugView.
You mean something like printf? It's quite portable... :D
Anyway, I think that the *nix way of doing something "similar" to DebugView is syslog (vast more than just a DebugView). Google for syslog client.
Re: To be or not to be (a console app)
Quote:
Originally Posted by
S_M_A
You mean something like printf? It's quite portable... :D.
:D - no, I meant that a solution using OutputDebugString() wouldn't be suitable for the other platforms.
Re: To be or not to be (a console app)
I just had to post that because of the Windows focus on that post. It would be an amusing moment to watch someone tell Linus that they really need to add OutputDebugString functionality to the kernel :D
I've never seen any cross platform libraries that route log text to either OutputDebugString or syslog depending on platform but that shouldn't be hard to do (or to console if possible).
Re: To be or not to be (a console app)
Quote:
Originally Posted by
John E
Unfortunately, the same code (i.e. the printfs) still need to still work on Linux and OS-X.
Then you need to abstract the calls to printf. Separate the I/O from the rest of the program. Then you can use something like a callback function to configure how the output is treated. If you're on windows, set the callback to a function that calls OutputDebugString, otherwise set it to a function that calls printf.
Re: To be or not to be (a console app)
Additional reading, for tricks like using a .com and .exe - http://blogs.msdn.com/b/oldnewthing/...1/9259142.aspx
gg