C++ 如何打印到 Win32 应用程序中的调试输出窗口?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1333527/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 19:35:58  来源:igfitidea点击:

How do I print to the debug output window in a Win32 app?

c++visual-studiowinapivisual-studio-2005console

提问by izb

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.

我有一个已加载到 Visual Studio 2005 中的 win32 项目。我希望能够将内容打印到 Visual Studio 输出窗口,但我终生无法弄清楚如何进行。我试过 'printf' 和 'cout <<' 但我的消息顽固地没有打印出来。

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

是否有某种特殊的方式可以打印到 Visual Studio 输出窗口?

回答by Martin Liversage

You can use OutputDebugString. OutputDebugStringis 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 Lprefix:

您可以使用OutputDebugString. OutputDebugString是一个宏,根据您的构建选项映射到OutputDebugStringA(char const*)OutputDebugStringW(wchar_t const*)。在后一种情况下,您必须为该函数提供一个宽字符串。要创建宽字符文字,您可以使用L前缀:

OutputDebugStringW(L"My output string.");

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

通常,您将宏版本与_T宏一起使用,如下所示:

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

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

如果您的项目配置为为 UNICODE 构建,它将扩展为:

OutputDebugStringW(L"My output string.");

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

如果您不是为 UNICODE 构建,它将扩展为:

OutputDebugStringA("My output string.");

回答by Zac

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:

如果项目是 GUI 项目,则不会出现控制台。为了将项目更改为控制台,您需要转到项目属性面板并设置:

  • In "linker->System->SubSystem" the value "Console (/SUBSYSTEM:CONSOLE)"
  • In "C/C++->Preprocessor->Preprocessor Definitions" add the "_CONSOLE" define
  • 在“链接器- >系统->子系统”中的值“控制台(/SUBSYSTEM:CONSOLE)
  • 在“ C/C++->Preprocessor->Preprocessor Definitions”中添加“ _CONSOLE”定义

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

只有当您拥有经典的“ int main()”入口点时,此解决方案才有效。

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

但是如果你像我的例子(一个 openGL 项目),你不需要编辑属性,因为这样效果更好:

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

printf and cout will work as usual.

printf 和 cout 将照常工作。

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.

如果在创建窗口之前调用 AllocConsole,控制台会出现在窗口后面,如果在创建之后调用,它会出现在前面。

Update

更新

freopenis deprecated and may be unsafe. Use freopen_sinstead:

freopen已弃用,可能不安全。使用freopen_s来代替:

FILE* fp;

AllocConsole();
freopen_s(&fp, "CONIN$", "r", stdin);
freopen_s(&fp, "CONOUT$", "w", stdout);
freopen_s(&fp, "CONOUT$", "w", stderr);

回答by Ringding

To print to the realconsole, 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.

要打印到real控制台,您需要使用链接器标志使其可见/SUBSYSTEM:CONSOLE。额外的控制台窗口很烦人,但出于调试目的,它非常有价值。

OutputDebugStringprints to the debugger output when running inside the debugger.

OutputDebugString在调试器内部运行时打印到调试器输出。

回答by Autodidact

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

考虑使用 VC++ 运行时宏进行报告_RPT N() 和 _RPTF N()

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.

您可以使用 CRTDBG.H 中定义的 _RPTn 和 _RPTFn 宏来代替 printf 语句的使用进行调试。当 _DEBUG 未定义时,这些宏会在您的发布版本中自动消失,因此无需将它们包含在 #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, _CrtDbgReportWdirectly.

或者您可以直接使用 VC++ 运行时函数_CrtDbgReport、_CrtDbgReportW

_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.

_CrtDbgReport 和 _CrtDbgReportW 可以将调试报告发送到三个不同的目标:调试报告文件、调试监视器(Visual Studio 调试器)或调试消息窗口。

_CrtDbgReport 和 _CrtDbgReportW 使用 printf 或 wprintf 函数定义的相同规则,通过将参数 [n] 参数替换到格式字符串中,为调试报告创建用户消息。然后,这些函数根据为 reportType 定义的当前报告模式和文件生成调试报告并确定一个或多个目的地。当报告发送到调试消息窗口时,文件名、行号和模块名将包含在窗口中显示的信息中。

回答by svensito

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

回答by vlad

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).

如果您需要查看广泛使用 printf 而不更改代码(或更改最少)的现有程序的输出,您可以按如下方式重新定义 printf 并将其添加到公共头文件 (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__)

回答by pops

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:

我假设您在 Visual Studio 中启动了一个默认的 Win32 项目(Windows 应用程序),它提供了一个“WinMain”函数。默认情况下,Visual Studio 将入口点设置为“SUBSYSTEM:WINDOWS”。您需要先通过以下方式更改此设置:

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

项目 -> 属性 -> 链接器 -> 系统 -> 子系统

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

然后从下拉列表中选择“控制台 (/SUBSYSTEM:CONSOLE)”。

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

现在,程序将不会运行,因为需要“main”函数而不是“WinMain”函数。

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.

所以现在您可以像通常在 C++ 中一样添加“main”函数。在此之后,要启动 GUI 程序,您可以从“main”函数内部调用“WinMain”函数。

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.

现在,您可以使用函数在 GUI 程序的任何部分输出到控制台,以用于调试或其他目的。

回答by HaSeeB MiR

You can also use WriteConsolemethod to print on console.

您还可以使用WriteConsole方法在控制台上打印。

AllocConsole();
LPSTR lpBuff = "Hello Win32 API";
DWORD dwSize = 0;
WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), lpBuff, lstrlen(lpBuff), &dwSize, NULL);

回答by MSalters

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.

您的 Win32 项目可能是 GUI 项目,而不是控制台项目。这会导致可执行文件头的差异。因此,您的 GUI 项目将负责打开自己的窗口。不过,这可能是一个控制台窗口。调用AllocConsole()以创建它,并使用 Win32 控制台函数对其进行写入。