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

时间:2009-08-26 09:45:13

标签: c++ visual-studio winapi visual-studio-2005 console

我有一个win32项目,我已经加载到Visual Studio 2005中。我希望能够将内容打印到Visual Studio输出窗口,但我不能为我的生活找出方法。我试过'printf'和'cout<<'但是我的信息一直没有印刷。

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

10 个答案:

答案 0 :(得分:123)

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

OutputDebugStringW(L"My output string.");

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

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

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

OutputDebugStringW(L"My output string.");

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

OutputDebugStringA("My output string.");

答案 1 :(得分:27)

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

  • 在“ linker-> System-> SubSystem ”中,值“控制台(/ SUBSYSTEM:CONSOLE)
  • 在“ C / C ++ - >预处理器 - >预处理器定义”中添加“ _CONSOLE ”定义

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

但如果你喜欢我的情况(一个openGL项目),你不需要编辑属性,因为这样做效果更好:

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

printf和cout将照常工作。

如果您在创建窗口之前调用AllocConsole,控制台将显示在窗口后面,如果您之后调用它,它将显示在前面。

答案 2 :(得分:12)

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

在调试器内部运行时,

OutputDebugString将打印到调试器输出。

答案 3 :(得分:4)

如果您需要查看广泛使用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__)

答案 4 :(得分:3)

考虑使用VC ++运行时宏进行报告_RPTN() and _RPTFN()

  

您可以使用CRTDBG.H中定义的_RPTn和_RPTFn宏来   替换使用printf语句进行调试。这些宏   当_DEBUG没有时,会自动消失在您的发布版本中   已定义,因此无需将它们括在#ifdefs中。

示例...

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

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

  

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

     

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

答案 5 :(得分:3)

如果要打印十进制变量:

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

答案 6 :(得分:2)

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

答案 7 :(得分:2)

我一直在寻找一种方法来做到这一点并想出一个简单的解决方案。

我假设您在Visual Studio中启动了默认的Win32项目(Windows应用程序),它提供了一个" WinMain"功能。默认情况下,Visual Studio将入口点设置为" SUBSYSTEM:WINDOWS"。您需要先转到:

进行更改

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

并选择"控制台(/ SUBSYSTEM:CONSOLE)"从下拉列表中。

现在,程序将无法运行,因为" main"需要函数而不是" WinMain"功能

所以现在你可以添加" main"像往常一样在C ++中运行。在此之后,要启动GUI程序,您可以调用" WinMain"功能来自" main"功能

你的程序的起始部分应该看起来像这样:

#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

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

答案 8 :(得分:1)

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

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

答案 9 :(得分:0)

这适用于 MSVC 下的 C++,甚至适用于通过调试器运行时的 GUI 应用程序。它也从发布版本中完全省略。它甚至使用 C++ 字符串流来实现灵活的输入。

#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

像这样使用:

LOG("some message " << someValue);