it-swarm.dev

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

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

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

80
izb

你可以使用 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.");
123
Martin Liversage

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

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

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

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

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

printf和cout将照常工作。

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

27
Zac

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

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

12
Ringding

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

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

您可以使用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]参数替换为格式字符串,使用printf或wprintf函数定义的相同规则,为调试报告创建用户消息。然后,这些函数将生成调试报告,并根据为reportType定义的当前报告模式和文件确定目标或目标。将报告发送到调试消息窗口时,文件名,lineNumber和moduleName将包含在窗口中显示的信息中。

3
Autodidact

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

2
MSalters

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

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

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

从下拉列表中选择“Console(/ SUBSYSTEM:CONSOLE)”。

现在,程序将无法运行,因为需要“主”功能而不是“WinMain”功能。

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

现在,程序的起始部分应如下所示:

#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;
.
.
.

我的实施结果

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

2
pops

如果要打印十进制变量:

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

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

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