Visual Studio 2012 C++标准输出

6

在编译Win32应用程序时,使用fprintf(stdout/stderr)会将输出打印到Visual Studio的哪个位置?我听说它会输出到输出窗口,但我看不到它!

在C++中,没有控制台窗口的情况下,输出日志的标准方法是什么?

1个回答

15

如果您的程序链接了 /SUBSYSTEM:WINDOWS ,则除非您分配一个控制台,否则您将看不到控制台输出。

以下是分配控制台选项的代码。使用此方法,您应该不需要更改链接器设置或创建 WinMain。

static void OpenConsole()
{
    int outHandle, errHandle, inHandle;
    FILE *outFile, *errFile, *inFile;
    AllocConsole();
    CONSOLE_SCREEN_BUFFER_INFO coninfo;
    GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &coninfo);
    coninfo.dwSize.Y = 9999;
    SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coninfo.dwSize);

    outHandle = _open_osfhandle((long)GetStdHandle(STD_OUTPUT_HANDLE), _O_TEXT);
    errHandle = _open_osfhandle((long)GetStdHandle(STD_ERROR_HANDLE),_O_TEXT);
    inHandle = _open_osfhandle((long)GetStdHandle(STD_INPUT_HANDLE),_O_TEXT );

    outFile = _fdopen(outHandle, "w" );
    errFile = _fdopen(errHandle, "w");
    inFile =  _fdopen(inHandle, "r");

    *stdout = *outFile;
    *stderr = *errFile;
    *stdin = *inFile;

    setvbuf( stdout, NULL, _IONBF, 0 );
    setvbuf( stderr, NULL, _IONBF, 0 );
    setvbuf( stdin, NULL, _IONBF, 0 );

    std::ios::sync_with_stdio();

}

如果您不想直接分配控制台,也可以通过更改链接器设置的子系统从 /SUBSYSTEM:WINDOWS 到 /SUBSYSTEM:CONSOLE 来更改。请记住,启用 /SUBSYSTEM:CONSOLE 后,GUI 仍将与以前相同,但 Windows 将为您的应用程序创建一个控制台窗口。

在我的 Qt 代码中,这是所需的全部内容。然而,当我在 VisualStudio 中尝试使用 MFC 并将子系统设置为控制台时,我遇到了以下错误:

1>------ Build started: Project: MFCApplication1, Configuration: Debug Win32 ------
1>  MFCApplication1.cpp
1>msvcrtd.lib(crtexe.obj) : error LNK2019: unresolved external symbol _main referenced in function ___tmainCRTStartup
1>X:\Test\VC.110\MFCTest\MFCApplication1\Debug\MFCApplication1.exe : fatal error LNK1120: 1 unresolved externals

这是由于控制台应用程序默认使用main()作为入口点,而Windows应用程序则使用WinMain。要解决这个问题,我需要在高级链接器设置的“入口点”选项中添加以下内容: "wWinMainCRTStartup"。

在评论中,Ben Voigt提出了另一种方法。使用editbin更改子系统不需要更改入口点。确实如此。我移除了入口点,并将Windows作为子系统构建测试应用程序,然后使用以下命令使用editbin更改子系统:

X:\Test\VC.110\MFCTest\MFCApplication1\Debug>editbin MFCApplication1.exe /SUBSYSTEM:CONSOLE
Microsoft (R) COFF/PE Editor Version 10.00.40219.01
Copyright (C) Microsoft Corporation.  All rights reserved.

在控制台上,我得到了我预期的输出:

X:\Test\VC.110\MFCTest\MFCApplication1\Debug>MFCApplication1.exe
Hello from a windows application!
 

注意:使用editbin方法需要在每次更新可执行文件后重新启用此功能。

最后,无论采用哪种方法,一旦您拥有了控制台printf或std :: cout都将起作用。例如,在我的测试MFC应用程序中,我将以下行添加到CMFCApplication1App类的构造函数中:

std::cout << "Hello from a windows application!" << std::endl;

这是链接器设置的子系统选项卡中的内容。在Qt中,这对我有效,但是在VS2012下使用MFC时,由于使用控制台子系统而导致入口点发生变化,我无法做到这一点。您是否正在使用MFC? - drescherjm
3
你也可以使用 editbin 来更改子系统——这不会影响链接过程,因此也不会改变入口点查找逻辑。 - Ben Voigt
请注意,即使项目目标是另一个控制台应用程序使用的 DLL,更改子系统也可以正常工作。 - leiflundgren
我尝试了那段代码来分配一个控制台,但是窗口里什么也没有显示出来。有什么原因会导致它无法工作? - DarenW
不确定。我明天会看看能否复制这个问题。 - drescherjm
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接