【问题标题】:How do I make Visual Studio pause after executing a console application in debug mode?在调试模式下执行控制台应用程序后,如何让 Visual Studio 暂停?
【发布时间】:2010-09-16 15:31:40
【问题描述】:

我有一组 Boost 单元测试,我想将其作为控制台应用程序运行。

当我处理项目并运行测试时,我希望能够调试测试,并且希望在测试运行后控制台保持打开状态。

我看到如果我在发布模式下运行,程序退出后控制台窗口会保持打开状态,但在调试模式下情况并非如此。

我不想添加 'system("pause");'或任何其他技巧,例如将字符读取到我的程序中。我只想让 Visual Studio 在运行带有调试的测试后暂停,就像我在发布模式下运行一样。如果测试的输出是在 Visual Studio 的输出窗口之一中捕获的,我也希望这样做,但这似乎也比应有的更难。

我该怎么做?

【问题讨论】:

标签: c++ visual-studio unit-testing boost console


【解决方案1】:

提示用户输入。

https://www.youtube.com/watch?v=NIGhjrWLWBo

展示了如何为 C++ 做到这一点。对于 Node.js,这是直接从文档中获取的(并且有效):

'use strict';

console.log('Hello world');

const readline = require('readline');
const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

rl.question('Press enter to continue...', (answer) => {
    rl.close(); /* discard the answer */
});

【讨论】:

    【解决方案2】:

    你说你不想使用system("pause") hack。为什么不呢?

    如果是因为您不希望程序在 没有 被调试时提示,那么有一种解决方法。这对我有用:

    void pause () {
        system ("pause");
    }
    
    int main (int argc, char ** argv) {
        // If "launched", then don't let the console close at the end until
        // the user has seen the report.
        // (See the MSDN ConGUI sample code)
        //
        do {
            HANDLE hConsoleOutput = ::GetStdHandle (STD_OUTPUT_HANDLE);
            if (INVALID_HANDLE_VALUE == hConsoleOutput)
                break;
            CONSOLE_SCREEN_BUFFER_INFO csbi;
            if (0 == ::GetConsoleScreenBufferInfo (hConsoleOutput, &csbi))
                break;
            if (0 != csbi.dwCursorPosition.X)
                break;
            if (0 != csbi.dwCursorPosition.Y)
                break;
            if (csbi.dwSize.X <= 0)
                break;
            if (csbi.dwSize.Y <= 0)
                break;
            atexit (pause);
        } while (0);
    

    我只是将此代码粘贴到我正在编写的每个新控制台应用程序中。如果程序从命令窗口运行,光标位置不会是,也不会调用atexit()。如果它已从您的调试器(任何调试器)启动,则控制台光标位置将为 并且将执行 atexit() 调用。

    我从以前在 MSDN 库中的示例程序中得到这个想法,但我认为它已被删除。

    注意:system() 例程的 Microsoft Visual Studio 实现需要 COMSPEC 环境变量来识别命令行解释器。如果这个环境变量搞砸了——例如,如果你在 Visual Studio 项目的调试属性中遇到问题,以至于在程序启动时环境变量没有正确传递——那么它就会默默地失败.

    【讨论】:

      【解决方案3】:

      尝试使用 Ctrl + F5 组合运行应用程序。

      【讨论】:

      • Ctrl+F5不调试不就运行了吗?
      • 这个 OP 想要在调试模式下运行 - 这在发布模式下运行。
      • @Lloyd:这不准确 - 它在调试器外部运行当前配置(可能是也可能不是调试)。 VisualStudio 中没有“发布模式”之类的东西
      • 如果您试图找出应用程序崩溃的原因(未捕获的异常)并且您想查看错误,这仍然是一个有用的答案。有更好的方法,但这又快又容易。 +1
      • 如果您在 Mac 上的 VM 中运行 Windows,则需要禁用默认的 Ctrl+F5 绑定(Mac 设置 > 键盘 > 快捷方式 > 键盘)
      【解决方案4】:

      我刚刚从http://social.msdn.microsoft.com/forums/en-US/Vsexpressvc/thread/1555ce45-8313-4669-a31e-b95b5d28c787/?prof=required复制过来的:

      以下对我有用:-)

      /////////////////////////////////////// ////////////////////////////////

      这是控制台可能消失的另一个原因。以及解决方案:

      使用新的 Visual Studio 2010,即使您使用 Ctrl + F5 也就是“不调试就开始”,您可能会看到这种行为。这很可能是因为您创建了一个“空项目”而不是“Win32 控制台应用程序”。如果您将项目创建为“Win32 控制台应用程序”,则可以忽略它,因为它不适用。

      在旧版本中,即使您选择了“空项目”,它也会默认使用控制台子系统,但在 Visual Studio 2010 中则不会,因此您必须手动设置它。为此,请在右侧或左侧的解决方案资源管理器中选择项目(可能已被选中,因此您不必担心)。

      然后从菜单栏下拉菜单中选择“项目”,然后选择“项目名称属性”→“配置属性”→“链接器”→“系统”并设置第一个属性,下拉将“子系统”属性向下移动到“控制台 (/SUBSYSTEM:CONSOLE)”。控制台窗口现在应该像往常一样在执行后保持打开状态。

      /////////////////////////////////////// ////////////////////////////////

      【讨论】:

      • 我的设置“未设置”。将其更改为“控制台(/SUBSYSTEM:CONSOLE)”有效!
      【解决方案5】:

      我会在您自己选择的特定时间(毫秒)内使用“等待”命令。应用程序一直执行到您要检查的行,然后在时间到期后继续。

      包含&lt;time.h&gt; 标头:

      clock_t wait;
      
      wait = clock();
      while (clock() <= (wait + 5000)) // Wait for 5 seconds and then continue
          ;
      wait = 0;
      

      【讨论】:

        【解决方案6】:

        如果是控制台应用,使用Ctrl + F5

        【讨论】:

          【解决方案7】:

          在最后做一个 readline(它是“forma cochina”,就像我们在哥伦比亚所说的那样,但它有效):

          static void Main(string[] args)
          {
              .
              .
              .
              String temp = Console.ReadLine();
          }
          

          【讨论】:

          • 问题明确表示“我不想添加 'system("pause");'或任何其他技巧,例如将字符读取到我的程序中。"
          • 这也不是 C++ 解决方案...?
          【解决方案8】:

          在 Boost.Test 中有 --auto_start_dbg 参数,用于在测试失败(异常或断言失败)时进入调试器。由于某种原因,它对我不起作用。

          http://www.boost.org/doc/libs/1_40_0/libs/test/doc/html/utf/usage-recommendations/dot-net-specific.html

          出于这个原因,我创建了我的自定义 test_observer,它会在出现断言失败或异常时进入调试器。当我们在调试器下运行时,它会在调试版本中启用。

          在我的单元测试 EXE 文件的源文件之一中,我添加了以下代码:

          #ifdef _DEBUG
          
          #include <boost/test/framework.hpp>
          #include <boost/test/test_observer.hpp>
          
          struct BoostUnitTestCrtBreakpointInDebug: boost::unit_test::test_observer
          {
              BoostUnitTestCrtBreakpointInDebug()
              {
                  boost::unit_test::framework::register_observer(*this);
              }
          
              virtual ~BoostUnitTestCrtBreakpointInDebug()
              {
                  boost::unit_test::framework::deregister_observer(*this);
              }
          
              virtual void assertion_result( bool passed /* passed */ )
              {
                  if (!passed)
                      BreakIfInDebugger();
              }
          
              virtual void exception_caught( boost::execution_exception const& )
              {
                  BreakIfInDebugger();
              }
          
              void BreakIfInDebugger()
              {
                  if (IsDebuggerPresent())
                  {
                      /**
                       * Hello, I know you are here staring at the debugger :)
                       *
                       * If you got here then there is an exception in your unit
                       * test code. Walk the call stack to find the actual cause.
                       */
                      _CrtDbgBreak();
                  }
              }
          };
          
          BOOST_GLOBAL_FIXTURE(BoostUnitTestCrtBreakpointInDebug);
          
          #endif
          

          【讨论】:

            【解决方案9】:

            只需使用 log4net 之类的日志库,并将其记录到文件追加器。

            【讨论】:

            • 嗯,这是 C++,但我明白你的意思。我正在使用 BOOST 单元测试的东西。我可以用这种方式在测试中记录东西,但我不知道如何让 boost 测试框架记录到特殊的地方。
            【解决方案10】:

            Boost 测试提供以下usage recommendations for Visual Studio,使您能够在编译结束时自动运行单元测试并将输出捕获到构建窗口中。

            这个技巧的好处是它使您能够将测试失败视为编译错误。 “...您可以使用用于编译错误分析的常用键盘快捷键/鼠标单击来跳过这些错误...”

            【讨论】:

            • 更新:这仍然适用于 VS2012 和 Boost 1.52 - 不是最新版本,但我想 1.54 也可以。
            【解决方案11】:

            添加以下行将执行一个简单的 MS-DOS pause 不显示任何消息。

            system("pause >nul | set /p \"=\"");
            

            并且不需要Ctrl+F5(这将使您的应用程序在发布模式下运行)

            【讨论】:

              【解决方案12】:

              http://connect.microsoft.com/VisualStudio/feedback/details/540969/missing-press-any-key-to-continue-when-lauching-with-ctrl-f5

              在旧版本中,即使您选择了“空项目”,它也会默认使用控制台子系统,但在 2010 中不会,因此您必须手动设置它。为此,请在右侧或左侧的解决方案资源管理器中选择项目(可能已被选中,因此您不必担心这一点)。然后从菜单栏下拉菜单中选择“项目”,然后选择“项目名称属性”>“配置属性”>“链接器”>“系统”并设置第一个属性,下拉“子系统” ” 属性到“控制台 (/SUBSYSTEM:CONSOLE)”。控制台窗口现在应该像往常一样在执行后保持打开状态。

              【讨论】:

              • THIS 是正确的答案,但它没有得分,另一个问题的答案得到了所有的分数,而接受的答案是一个过于复杂的问题在一种情况下(使用升压测试)。有时向下滚动是值得的……
              • 看起来这是一个仅限 C++ 的答案。 C# 项目有同样的问题,但一组不同的属性不包含这些选项。
              【解决方案13】:

              或者您可以使用 boost_test "测试日志输出"。

              http://www.boost.org/doc/libs/1_47_0/libs/test/doc/html/utf/user-guide/test-output/test-log.html

              那么控制台窗口是否显示都无关紧要,并且您的构建日志可以将单元测试输出保存为用于检查失败构建的工件...

              【讨论】:

                【解决方案14】:

                我用 F11 启动应用程序并在 unit_test_main.ipp 中的某处获得一个断点(可以是汇编代码)。我使用 shift-f11 (Step out) 来运行单元测试并在 CRT 中获取下一条汇编指令(通常在 mainCRTStartup() 中)。我使用 F9 在该指令处设置断点。

                在下一次调用时,我可以按 F5 启动应用程序,运行测试后应用程序将中断,因此我有机会查看控制台窗口

                【讨论】:

                  【解决方案15】:

                  在代码的最后一行设置断点。

                  【讨论】:

                  • 不错,打断点后有热键继续吗?
                  • 好的,断点后按F5继续! (也很方便:F10、F11、Shift+F11)
                  • 而且你也可以按F9在最后一行代码设置断点。另请注意,控制台窗口可能会最小化启动,因此您需要在调试后选择它(F5)。
                  • 如果提前抛出异常或该代码有多个返回路径并且可能无法到达该断点怎么办?
                  【解决方案16】:

                  您还可以将可执行文件设置为外部工具,并将该工具标记为使用输出窗口。这样,工具的输出将在 Visual Studio 本身中可见,而不是单独的窗口。

                  【讨论】:

                    【解决方案17】:

                    实际上会更费力,但您可以在 VS.Net 中构建,从常规命令行 (cmd.exe) 运行它,然后在它开始运行后附加到进程。然而,这可能不是您正在寻找的解决方案。

                    【讨论】:

                    • 我不寻找这个解决方案的原因是它有点笨拙。我希望我的测试在启用调试断言的情况下运行,所以我确实想在调试模式下运行,但我也想查看测试套件输出。
                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2012-09-18
                    • 2016-08-15
                    • 2013-03-09
                    • 1970-01-01
                    相关资源
                    最近更新 更多