How can you view printf output in a Win32 application (entering with a WinMain) in Visual Studio 2010?
问题:
回答1:
Strictly answering your question, you may use printf-like functions in a Win32 application in Visual Studio 2010 using the winbase.h OutputDebugString
function.
I wrote a simple program that shows how to do it.
#include <windows.h>
#include <stdio.h>
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdShow, int nCmdShow)
{
int number = 10;
char str[256];
sprintf_s(str, "It works! - number: %d \n", number);
OutputDebugString(str);
return 0;
}
The OutputDebugString
function takes an LPCSTR
as a parameter. I used the sprintf_s
to format the string before printing.
This would print the result to the Visual Studio 2010 output window.
I hope it helps!
回答2:
You'll need a console window. By far the easiest way to get one is to change a linker option: Project + Properties, Linker, System, SubSystem = Console. Add a main() method:
int main() {
return _tWinMain(GetModuleHandle(NULL), NULL, GetCommandLine(), SW_SHOW);
}
回答3:
I know that I have done this in the past using the AllocConsole function, but I also recall that it was just a little trickier than I expected.
A quick Google search on AllocConsole yields what is apparently a Windows Developer Journal article that seems relevant. From there, the following seems similar to what I recall, vague as it is.
void SetStdOutToNewConsole()
{
int hConHandle;
long lStdHandle;
FILE *fp;
// Allocate a console for this app
AllocConsole();
// 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);
}
回答4:
Thanks torak for your answer. It helped me a lot.
I needed a bigger scroll back buffer so made a few additions after taking a look at the API functions. Shared here in case it helps anybody else:
void SetStdOutToNewConsole()
{
// allocate a console for this app
AllocConsole();
// redirect unbuffered STDOUT to the console
HANDLE consoleHandle = GetStdHandle(STD_OUTPUT_HANDLE);
int fileDescriptor = _open_osfhandle((intptr_t)consoleHandle, _O_TEXT);
FILE *fp = _fdopen( fileDescriptor, "w" );
*stdout = *fp;
setvbuf( stdout, NULL, _IONBF, 0 );
// give the console window a nicer title
SetConsoleTitle(L"Debug Output");
// give the console window a bigger buffer size
CONSOLE_SCREEN_BUFFER_INFO csbi;
if ( GetConsoleScreenBufferInfo(consoleHandle, &csbi) )
{
COORD bufferSize;
bufferSize.X = csbi.dwSize.X;
bufferSize.Y = 9999;
SetConsoleScreenBufferSize(consoleHandle, bufferSize);
}
}
This increases the scroll back (screen buffer) height to 9999 lines.
Tested on Windows XP and Windows 7.
回答5:
Another way which wouldn't require changing existing printf's and also print to VS output window would go something like this:
#define printf printf2
int __cdecl printf2(const char *format, ...)
{
char str[1024];
va_list argptr;
va_start(argptr, format);
int ret = vsnprintf(str, sizeof(str), format, argptr);
va_end(argptr);
OutputDebugStringA(str);
return ret;
}
...
printf("remains %s", "the same");
回答6:
Here is a page that will tell you how to do this, including sample code.
You must create a console window using AllocConsole(), then associate the C standard file handles to the HANDLEs of the new console window.
回答7:
For MinGW use "_A_SYSTEM" instead "_O_TEXT". So ported Quintin Willison answer is as follows:
#include <io.h>
void SetStdOutToNewConsole()
{
// allocate a console for this app
AllocConsole();
// redirect unbuffered STDOUT to the console
HANDLE consoleHandle = GetStdHandle(STD_OUTPUT_HANDLE);
int fileDescriptor = _open_osfhandle((intptr_t)consoleHandle, _A_SYSTEM);
FILE *fp = _fdopen( fileDescriptor, "w" );
*stdout = *fp;
setvbuf( stdout, NULL, _IONBF, 0 );
// give the console window a nicer title
SetConsoleTitle(L"Debug Output");
// give the console window a bigger buffer size
CONSOLE_SCREEN_BUFFER_INFO csbi;
if ( GetConsoleScreenBufferInfo(consoleHandle, &csbi) )
{
COORD bufferSize;
bufferSize.X = csbi.dwSize.X;
bufferSize.Y = 9999;
SetConsoleScreenBufferSize(consoleHandle, bufferSize);
}
}