【问题标题】:Visual Studio 2012 C++ Standard OutputVisual Studio 2012 C++ 标准输出
【发布时间】:2012-11-30 05:26:52
【问题描述】:

编译 Win32 应用程序时 fprintf(stdout/stderr) 在 Visual Studio 中打印到哪里?我一直听到它进入输出,但我看不到它!

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

【问题讨论】:

    标签: c++ output


    【解决方案1】:

    如果您的程序与 /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”

    在 cmets 中,Ben Voigt 提出了另一种方法。使用 editbin 更改子系统不需要更改入口点。情况确实如此。当子系统构建测试应用程序时,我删除了入口点并将窗口放回原处,然后使用 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 吗?
    • 您也可以使用editbin 更改子系统——这不会影响链接过程,因此不会更改入口点查找逻辑。
    • 请注意,即使项目目标是另一个控制台应用程序使用的 DLL,也可以更改子系统。
    • 我尝试了那段代码来分配控制台。那个窗口什么都没有显示。什么会阻止它工作?
    • 不确定。我明天看看能不能复制这个问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-24
    • 1970-01-01
    相关资源
    最近更新 更多