Skip to main content
GameDev.net gamedev.net
🔒 Locked

printf output in a windows application

Started by johndirect Apr 25, 2008 at 12:08 PM 11 replies 25.7k views
Original Post
johndirect
johndirect
I have a Windows application. For debug purposes, I added printf statements. However, when I run the app from the command prompt (from a commadn window), I dont see the printf output on the command window. Where is printf redirecting the output to? Any help is appreciated. Thanks!
linternet
linternet
printf only outputs to the console for console applications.

I don't know what stdout is when used in a windows application, but, for debugging purposes, you could use MessageBox:

ex:

{     char buffer[8192]; // sufficently large buffer     sprintf (buffer, "Message here %d", intvar);     MessageBox (NULL, buffer, "Debug Message", MB_OK);}


or:

{     std::stringstream buffer;     buffer << "Message here " << intvar;     MessageBox (NULL, buffer.str().c_str(), "Debug Message", MB_OK);     buffer.clear();     buffer.str("");}




fnm
fnm
try something like:

AllocConsole();
freopen("conin$","r",stdin);
freopen("conout$","w",stdout);
freopen("conout$","w",stderr);
tksuoran
tksuoran
Google OutputDebugString
Oluseyi
Oluseyi
Within a Win32 subsystem application (ie, non-console), the standard input and output streams are not defined. You'll need to do a couple of things.
  1. Create your own console, using AllocConsole.

  2. Redirect the input and output streams for the C stdio system to the input and output streams of the console. It involves filehandle duplication and preferably switching off virtual buffering.


Sounds complicated? Well I come bearing gifts: Adding Console I/O to a Win32 GUI App. You're welcome!
HeartattacK
HeartattacK
You can go into project settings and change the application type to Win32 console application. That way, you'll get the Windows (you created) as usual, but will also get a console, to which printf can write to.

Hope this helps.

Edit: Sorry, it doesn't help. It only works with C#, VB.Net etc. with Windows Forms, not for native projects.
Molle85
Molle85
The reason why printf doesn't work for you ( since no one else answered ) is because starting a windows application through the command prompt doesn't mean that your application now is attached to it, you have to allocate your own command window to be able to print out your debug info.

try running this in your WinMain() function:

note that 'if ( strcmp(lpCmdLine, "-console") == 0 )' checks the parameters.

Quote:
if ( strcmp(lpCmdLine, "-console") == 0 ){	// Create a console	AllocConsole();	int hConHandle;	long lStdHandle;	CONSOLE_SCREEN_BUFFER_INFO coninfo;	FILE *fp;	const unsigned int MAX_CONSOLE_LINES = 500;	// set the screen buffer to be big enough to let us scroll text	GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE),	&coninfo);	coninfo.dwSize.Y = MAX_CONSOLE_LINES;	SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE),	coninfo.dwSize);	// redirect unbuffered STDOUT to the console	lStdHandle = (long)GetStdHandle(STD_OUTPUT_HANDLE);	hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);	fp = _fdopen( hConHandle, "w" );	*stdout = *fp;	setvbuf( stdout, NULL, _IONBF, 0 );	// redirect unbuffered STDIN to the console	lStdHandle = (long)GetStdHandle(STD_INPUT_HANDLE);	hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);	fp = _fdopen( hConHandle, "r" );	*stdin = *fp;	setvbuf( stdin, NULL, _IONBF, 0 );	// redirect unbuffered STDERR to the console	lStdHandle = (long)GetStdHandle(STD_ERROR_HANDLE);	hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);	fp = _fdopen( hConHandle, "w" );	*stderr = *fp;	setvbuf( stderr, NULL, _IONBF, 0 );	// make cout, wcout, cin, wcin, wcerr, cerr, wclog and clog	// point to console as well	std::ios::sync_with_stdio();}
nhatkthanh
nhatkthanh
You can change the subsystem in win32 project settings to Console subsystem. It is under Linker->System->Subsystem.
HeartattacK
HeartattacK
Quote:
Original post by nhatkthanh
You can change the subsystem in win32 project settings to Console subsystem. It is under Linker->System->Subsystem.



I thought that would work. Tried it on a Windows application. Guess what:
Error 3 error LNK2019: unresolved external symbol _main referenced in function ___tmainCRTStartup MSVCRTD.lib hello
Evil Steve
Evil Steve
Quote:
Original post by HeartattacK
Quote:
Original post by nhatkthanh
You can change the subsystem in win32 project settings to Console subsystem. It is under Linker->System->Subsystem.



I thought that would work. Tried it on a Windows application. Guess what:
Error 3 error LNK2019: unresolved external symbol _main referenced in function ___tmainCRTStartup MSVCRTD.lib hello


Yeah, you almost certainly don't want to change the subsystem.

Or if you do, you could add this I suppose (although it's not very nice):
int main(int, char**){   return WinMain(GetModuleHandle(NULL), NULL, GetCommandLineA(), SW_SHOWNORMAL);}
But don't do that, it's very hacky - and I don't know how to get the nCmdShow parameter out from thin air like the command line and HINSTANCE[smile]
Oluseyi
Oluseyi
Different entry points are defined for the Win32 and console subsytems - WinMain and main, respectively.

If you want to have a Win32 window, etc in a console subsystem application, you'll need to obtain the application instance handle explicitly, as it won't be passed in the way it is with WinMain:
int main(int argc, char * argv[]){    HINSTANCE hInstance = (HINSTANCE)GetModuleHandle(NULL);    ...    WNDCLASSEX wc;    wc.hInstance = hInstance;    ...    HWND hWnd = CreateWindowEx(..., hInstance, NULL);    ...}
MJP
MJP
Quote:
Original post by Evil Steve
Quote:
Original post by HeartattacK
Quote:
Original post by nhatkthanh
You can change the subsystem in win32 project settings to Console subsystem. It is under Linker->System->Subsystem.



I thought that would work. Tried it on a Windows application. Guess what:
Error 3 error LNK2019: unresolved external symbol _main referenced in function ___tmainCRTStartup MSVCRTD.lib hello


Yeah, you almost certainly don't want to change the subsystem.

Or if you do, you could add this I suppose (although it's not very nice):
*** Source Snippet Removed ***But don't do that, it's very hacky - and I don't know how to get the nCmdShow parameter out from thin air like the command line and HINSTANCE[smile]


Ehh, it's hacky but doable (I've done it before, with MFC no less!). As for nCmdShow, you can use GetStartupInfo.

Evil Steve
Evil Steve
Quote:
Original post by MJP
Ehh, it's hacky but doable (I've done it before, with MFC no less!). As for nCmdShow, you can use GetStartupInfo.
Yeah, I've done it before too. I didn't know about GetStartupInfo, thanks [smile]

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.