无法在C#控制台应用程序中捕获Ctrl+C

4

我有以下的代码,试图在控制台应用程序中捕获Ctrl+C:

    /// <summary>
    /// A driver program for testing 
    /// </summary>
    /// <param name="args">Arguments to the program</param>
    static void Main(string[] args)
    {
        var program = new Program();

        Console.Clear();
        Console.TreatControlCAsInput = false;
        Console.CancelKeyPress += program.OnCancelKeyPress;

        program.Run(args.FirstOrDefault() ?? "3.26.200.125");

        Console.WriteLine("Press any key to continue ...");
        Console.ReadKey();
    }

    /// <summary>
    /// Called when [cancel key press].
    /// </summary>
    /// <param name="sender">The sender.</param>
    /// <param name="e">The <see cref="System.ConsoleCancelEventArgs"/> instance containing the event data.</param>
    internal void OnCancelKeyPress(object sender, ConsoleCancelEventArgs e)
    {
        this.Continue = false;
        e.Cancel = true;
    }

我已经查看了这里这里的问题,但出现了一个问题,当我按下Control+C时,Visual Studio 2010不会进入我的处理程序,在调试器中只会显示“源代码不可用”的屏幕,并有继续调试的机会,仅此而已。有人知道为什么我没有进入处理程序吗?我确信我只是错过了一些简单的东西。


这也是我调试程序时遇到的情况,当我在发布模式下运行程序时,它可以正常工作。这只是我遇到的 Visual Studio 问题吗? - Alex Marshall
你尝试在控制处理程序中设置断点了吗?可能有一些东西会导致 Visual Studio 在运行处理程序之前中断执行。然后你可以看看是否继续执行后进入了控制处理程序。 - Guvante
是的,我已经在处理程序中设置了断点,但它从未被触发。当我在上述点按F5继续(希望进入我的处理程序)时,程序就像什么都没有发生过一样继续运行,没有任何中断键被按下。 - Alex Marshall
1
由于调试器的更改,VS2010的设计使Ctrl+C现在类似于Debug + Break All。一种解决方法是启用非托管代码调试,单击消息框上的“继续”按钮,然后就可以触发断点了。 - Hans Passant
3个回答

4

显然存在一个bug,来自Connect页面的解决方法如下:

与此同时,为了解决这个问题,您可以启用混合模式调试。然后,当您按下Ctrl-C并弹出对话框通知您第一次机会Ctrl-C异常时,请单击“继续”。然后,您应该在处理程序中触发断点。


你说得对。我启用了混合模式调试,现在它进入了处理程序。非常感谢你。 - Alex Marshall

2

以下代码对我来说非常有效

using System;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.Clear();
            Console.WriteLine("Press X to quit");
            Console.TreatControlCAsInput = false;
            Console.CancelKeyPress += (s, ev) =>
                                          {
                                              Console.WriteLine("Ctrl+C pressed");
                                              ev.Cancel = true;
                                          };

            while (true)
                if (Console.ReadKey().Key == ConsoleKey.X)
                    break;
        }
    }
}

希望这可以帮到你!

是的,但重点不在于证明它。只需捕获Ctrl+C。另外:你试过吗?作为一个简单的例子,它按预期工作。 - Ani
是的,我正在做非常类似的事情,并且正在测试它。然而,我的更复杂,因为我添加了异步内容,使其非阻塞并具有取消等功能。 - Latency

0
当主函数退出时,你已经注册的事件处理程序会被垃圾回收。然后,当操作系统尝试访问委托时,就没有代码可以运行。
你必须声明一个静态委托,以在Main之外运行,并在Main中分配它,以便在操作系统尝试回调它时保持在范围内。

1
这显然不是问题所在,因为当我没有在 Visual Studio 中进行调试时,处理程序运行良好。 - Alex Marshall
你是正确的。我提供的答案是在我通过Windows API调用注册Ctrl-C处理程序时起作用的,而不是上面你展示的方法。看起来你已经将其弄清楚了,这是个好消息。 - Buddy

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