110

I've got a win32 project that I've loaded into Visual Studio 2005. I'd like to be able to print things to the Visual Studio output window, but I can't for the life of me work out how. I've tried 'printf' and 'cout <<' but my messages stay stubbornly unprinted.

Is there some sort of special way to print to the Visual Studio output window?

Martin Liversage
  • 104,481
  • 22
  • 209
  • 256
izb
  • 50,101
  • 39
  • 117
  • 168
  • 12
    Note that the Visual Studio output Window is not the console. They're both "windows with text in them", but are different behind the scenes. – MSalters Aug 26 '09 at 09:56
  • If the VS output window defaults to showing the full path of the source cpp before each message, consider the [workaround](https://stackoverflow.com/questions/8487986/file-macro-shows-full-path/848820) for __ FILE __. – Laurie Stearn Sep 10 '20 at 14:22

10 Answers10

152

You can use OutputDebugString. OutputDebugString is a macro that depending on your build options either maps to OutputDebugStringA(char const*) or OutputDebugStringW(wchar_t const*). In the later case you will have to supply a wide character string to the function. To create a wide character literal you can use the L prefix:

OutputDebugStringW(L"My output string.");

Normally you will use the macro version together with the _T macro like this:

OutputDebugString(_T("My output string."));

If you project is configured to build for UNICODE it will expand into:

OutputDebugStringW(L"My output string.");

If you are not building for UNICODE it will expand into:

OutputDebugStringA("My output string.");
Martin Liversage
  • 104,481
  • 22
  • 209
  • 256
  • 2
    Perfect! Thanks. For completeness though, it turned out I had to do this: OutputDebugString(TEXT("Hello console world")); .. presumably due to some sort of unicode-related build option. – izb Aug 26 '09 at 10:18
  • @izb: I expanded my answer a bit to include information about the two versions of the function. – Martin Liversage Aug 26 '09 at 10:43
  • +1. In general, you use the macro version and enclose the string in `_T` (which is the same as `TEXT` only shorter). – avakar Aug 26 '09 at 10:46
  • 1
    note that you will find it useful to have debugview from sysinternals. This allows you to see the ODS output even if Visual Studio is not running (or even installed) on the box – pm100 Oct 15 '10 at 00:23
  • +1 - much better than messing with console windows. I also had to use TEXT instead of _T - probably defined in some !@#$% .h file. – Tom Bushell Apr 03 '12 at 22:53
  • How can I output some string variable ? Like OutputDebugString(myStr); – CDT May 22 '13 at 08:17
  • 4
    @CDT: It depends on the type of `myStr`. Is it `char*`, `wchar_t*` or `LPTSTR`? Assuming that it is `char*` you simply call `OutputDebugStringA(myStr)` or use `OutputDebugStringW` with `wchar_t*` and `OutputDebugString` with `LPTSTR` as explained in my answer. – Martin Liversage May 22 '13 at 08:44
  • @MartinLiversage Really appreciated. It seems there's just no simple method to output debug information with VS. – CDT May 22 '13 at 08:46
  • 1
    @CDT: What is simpler than calling a function having a single parameter that is the message you want to output? Is it the ANSI/UNICODE complexity? Just use `OutputDebugString` and either define the appropriate preprocessor symbols to match the width of the characters you use or go with the flexible "T" types which allows you to compile to both 8 and 16 bit characters. – Martin Liversage May 22 '13 at 09:05
  • I was needed to see the output of existing program. – vlad Aug 18 '16 at 19:18
  • any idea why this doesn't output any string on the screen when I debug my code line by line? `OutputDebugStringW(L"My output string.");` ? – Mona Jalal Jun 02 '17 at 04:04
  • 1
    @MonaJalal: It is not clear from your comment what _screen_ is so it is a bit hard to give you specific advice. If you debug your process the debugger will have a way to display the debug output. If you are using Visual Studio as your debugger the output is shown in the __Output__ window. To actually see the output you have to select __Debug__ from the _Show output from_ dropdown. If you for some reason are running your process outside a debugger you can use [DebugView](https://technet.microsoft.com/en-us/sysinternals/debugview.aspx) to see debug output from all processes. – Martin Liversage Jun 02 '17 at 08:06
36

If the project is a GUI project, no console will appear. In order to change the project into a console one you need to go to the project properties panel and set:

  • In "linker->System->SubSystem" the value "Console (/SUBSYSTEM:CONSOLE)"
  • In "C/C++->Preprocessor->Preprocessor Definitions" add the "_CONSOLE" define

This solution works only if you had the classic "int main()" entry point.

But if you are like in my case (an openGL project), you don't need to edit the properties, as this works better:

AllocConsole();
freopen("CONIN$", "r",stdin);
freopen("CONOUT$", "w",stdout);
freopen("CONOUT$", "w",stderr);

printf and cout will work as usual.

If you call AllocConsole before the creation of a window, the console will appear behind the window, if you call it after, it will appear ahead.

Update

freopen is deprecated and may be unsafe. Use freopen_s instead:

FILE* fp;

AllocConsole();
freopen_s(&fp, "CONIN$", "r", stdin);
freopen_s(&fp, "CONOUT$", "w", stdout);
freopen_s(&fp, "CONOUT$", "w", stderr);
Leon Storey
  • 3,274
  • 2
  • 25
  • 40
Zac
  • 4,510
  • 3
  • 36
  • 44
  • `EDITBIN` can set subsystem to `CONSOLE` even if you are using `WinMain` rather than `int main()`. – Ben Voigt Oct 16 '13 at 14:57
  • 1
    @Zac. Thanks! The 4 lines starting with AllocConsole() worked great. Plus 1 for that. Nothing else was working, although I have gotten consoles to show up before in Win32 projects before using the /SUBSYSTEM:CONSOLE and/or _CONSOLE macros before. Don't know why the macros didn't work this evening. Could it have anything to do with using *Common Language Runtime Support (/clr)*? – riderBill Jan 27 '15 at 08:22
  • Microsoft is playing Embrace, Extend, Extinguish again if they claim `freopen` is deprecated in favor of `freopen_s`. `freopen` is a standard C function required to be present in every hosted implementation, while `freopen_s` is not required by the standard and in practice only exists on Windows. – Joseph Sible-Reinstate Monica Jun 03 '22 at 03:35
  • If startet from a console you can use ou could use `if (!AttachConsole(ATTACH_PARENT_PROCESS)) { AllocConsole(); }`. First try to attach to the parent's console. If this fails create a new one. – urbanSoft Nov 18 '22 at 08:37
13

To print to the real console, you need to make it visible by using the linker flag /SUBSYSTEM:CONSOLE. The extra console window is annoying, but for debugging purposes it's very valuable.

OutputDebugString prints to the debugger output when running inside the debugger.

Mona Jalal
  • 34,860
  • 64
  • 239
  • 408
Ringding
  • 2,856
  • 17
  • 10
8

If you want to print decimal variables:

wchar_t text_buffer[20] = { 0 }; //temporary buffer
swprintf(text_buffer, _countof(text_buffer), L"%d", your.variable); // convert
OutputDebugString(text_buffer); // print
svensito
  • 81
  • 1
  • 1
7

Consider using the VC++ runtime Macros for Reporting _RPTN() and _RPTFN()

You can use the _RPTn, and _RPTFn macros, defined in CRTDBG.H, to replace the use of printf statements for debugging. These macros automatically disappear in your release build when _DEBUG is not defined, so there is no need to enclose them in #ifdefs.

Example...

if (someVar > MAX_SOMEVAR) {
    _RPTF2(_CRT_WARN, "In NameOfThisFunc( )," 
         " someVar= %d, otherVar= %d\n", someVar, otherVar );
}

Or you can use the VC++ runtime functions _CrtDbgReport, _CrtDbgReportW directly.

_CrtDbgReport and _CrtDbgReportW can send the debug report to three different destinations: a debug report file, a debug monitor (the Visual Studio debugger), or a debug message window.

_CrtDbgReport and _CrtDbgReportW create the user message for the debug report by substituting the argument[n] arguments into the format string, using the same rules defined by the printf or wprintf functions. These functions then generate the debug report and determine the destination or destinations, based on the current report modes and file defined for reportType. When the report is sent to a debug message window, the filename, lineNumber, and moduleName are included in the information displayed in the window.

Sandeep Datta
  • 28,607
  • 15
  • 70
  • 90
  • It's worth adding to the answer or noting that `_RPTF0` can be used where no variables are expected to be passed after the format string. The `_RPTFN` macro, on the other hand, **requires** at least one argument following the format string. – Armen Michaeli Apr 24 '18 at 21:46
5

If you need to see the output of an existing program that extensively used printf w/o changing the code (or with minimal changes) you can redefine printf as follows and add it to the common header (stdafx.h).

int print_log(const char* format, ...)
{
    static char s_printf_buf[1024];
    va_list args;
    va_start(args, format);
    _vsnprintf(s_printf_buf, sizeof(s_printf_buf), format, args);
    va_end(args);
    OutputDebugStringA(s_printf_buf);
    return 0;
}

#define printf(format, ...) \
        print_log(format, __VA_ARGS__)
vlad
  • 184
  • 2
  • 5
  • 1
    be-careful because of the static buffer, this function is not reentrant and couldn't be used from different threads. – Nikazo Nov 07 '17 at 19:59
2

Your Win32 project is likely a GUI project, not a console project. This causes a difference in the executable header. As a result, your GUI project will be responsible for opening its own window. That may be a console window, though. Call AllocConsole() to create it, and use the Win32 console functions to write to it.

MSalters
  • 173,980
  • 10
  • 155
  • 350
2

I was looking for a way to do this myself and figured out a simple solution.

I'm assuming that you started a default Win32 Project (Windows application) in Visual Studio, which provides a "WinMain" function. By default, Visual Studio sets the entry point to "SUBSYSTEM:WINDOWS". You need to first change this by going to:

Project -> Properties -> Linker -> System -> Subsystem

And select "Console (/SUBSYSTEM:CONSOLE)" from the drop-down list.

Now, the program will not run, since a "main" function is needed instead of the "WinMain" function.

So now you can add a "main" function like you normally would in C++. After this, to start the GUI program, you can call the "WinMain" function from inside the "main" function.

The starting part of your program should now look something like this:

#include <iostream>

using namespace std;

// Main function for the console
int main(){

    // Calling the wWinMain function to start the GUI program
    // Parameters:
    // GetModuleHandle(NULL) - To get a handle to the current instance
    // NULL - Previous instance is not needed
    // NULL - Command line parameters are not needed
    // 1 - To show the window normally
    wWinMain(GetModuleHandle(NULL), NULL,NULL, 1); 

    system("pause");
    return 0;
}

// Function for entry into GUI program
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPWSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
    // This will display "Hello World" in the console as soon as the GUI begins.
    cout << "Hello World" << endl;
.
.
.

Result of my implementation

Now you can use functions to output to the console in any part of your GUI program for debugging or other purposes.

pops
  • 53
  • 1
  • 4
2

You can also use WriteConsole method to print on console.

AllocConsole();
LPSTR lpBuff = "Hello Win32 API";
DWORD dwSize = 0;
WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), lpBuff, lstrlen(lpBuff), &dwSize, NULL);
Haseeb Mir
  • 928
  • 1
  • 13
  • 22
0

This works for C++ under MSVC, and even for GUI applications when being run via Debugger. It also gets omitted entirely from release builds. It even uses a C++ stringstream for flexible input.

#include <iostream>

#ifdef _MSC_VER
#include "Windows.h"
#endif

#if !defined(NDEBUG) && defined(_MSC_VER)
#define LOG(args) {std::stringstream _ss; _ss << __FILE__ << "@" << __LINE__ << ": " \
    << args << std::endl; OutputDebugString(_ss.str().c_str());}
#else
#define LOG(args)
#endif

Use like:

LOG("some message " << someValue);
user1050755
  • 11,218
  • 4
  • 45
  • 56
  • I believe that strictly speaking, this should include `` as `` is not guaranteed to pull in the necessary libraries (and Microsoft can and does change the organization in areas that are not subject to standard requirements from one version of the library to another). – Craig Sep 02 '22 at 21:35