启动代码中的调试器

64
我需要调试一个从一键安装程序启动的应用程序(VS 2010,与 Office 7 的 Excel VSTO 相关)。根据提供给一键安装程序的登录凭据,用户应该看到两个不同的启动页面中的其中之一。在我的机器上都很正常,但在部署后,从默认页面切换到第二个页面会出现错误。
我实在想不出如何在 VS2010 中调试此进程。我可以附加到输入凭据之前的登录操作,但无法附加到 Excel,因为直到单击“确定”按钮才会启动 Excel。
那么,有没有一种方法让 Excel 或者说我的代码在实例化时调用调试器,以便我能找出部署应用程序中为什么我的图像资源不可用?
谢谢。 兰迪

目标机器是否安装了Visual Studio? - Scott Chamberlain
不行。那是开发服务器,但我认为调试人员必须拥有管理员权限,而这是不可能的。 - EoRaptor013
很高兴你解决了这个问题,但是作为一条提示,你不需要管理员权限,你只需要成为“调试器用户”组的成员即可。 (http://msdn.microsoft.com/en-us/library/aa291232%28v=vs.71%29.aspx) - Scott Chamberlain
4个回答

142
System.Diagnostics.Debugger.Launch();

6
哦,原来如此简单!? :) 我不知道。 - Davide Piras
1
是啊,而且试着在文档中找到那个!也许我的谷歌功夫不够好。 - EoRaptor013
1
我应该自己扣分,因为没有简单地查看类文档。噢,算了。 - EoRaptor013
5
使用 System.Diagnostics.Debugger.Break 在当前位置设置断点。 - smirkingman
1
文档中说“启动并附加调试器到进程”。但是如果我有多个调试器(VS、windbg、cdb...),并且想要其中特定的一个,那么将启动哪个调试器? - KFL
3
我知道这是一篇旧帖子;当它运行到launch()时,会弹出一个对话框询问你想要使用什么进行调试。 - Polosky

10

最简单

要从代码中强制设置断点,请使用:

if (System.Diagnostics.Debugger.IsAttached)
    System.Diagnostics.Debugger.Break();

当应用程序未在Visual Studio中启动时(包括远程调试)

有时候应用程序无法从Visual Studio中启动,但仍然需要进行调试。我使用以下代码来检查是否正在运行Visual Studio,并提供一种将其附加到Visual Studio的方法。

using System.Diagnostics;

....

// get debugger processes
Process[] procName1 = Process.GetProcessesByName("devenv");

// get remote debugging processes
Process[] procName2 = Process.GetProcessesByName("msvsmon"); 

// If Visual Studio or remote debug are running halt the application by showing a MessageBox and give opportunity to attach the debugger
if (procName1.Length > 0 || procName2.Length > 0)
{
    if (MessageBox.Show(Application.Current.MainWindow, "Force breakpoint?", "Wait for debugger attach", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
    {
        // Force a breakpoint when the debugger became attached
        if (System.Diagnostics.Debugger.IsAttached)
            System.Diagnostics.Debugger.Break(); // force a breakpoint
    }
}

今天我需要一个控制台应用程序的解决方案。在这里:
using System.Diagnostics;

....

// Wait for debugger attach and force breakpoint
// for a console app
//
if (!System.Diagnostics.Debugger.IsAttached) // not needed when debugger is already attached
{
    /// for "eternal" wait (~ 68 years) use: 
    ///     int waitTimeout = int.MaxValue 
    int waitTimeout = 60; 

    // get debugger processes
    Process[] procName1 = Process.GetProcessesByName("devenv");

    // get remote debugging processes
    Process[] procName2 = Process.GetProcessesByName("msvsmon");

    // If Visual Studio or remote debug are running halt the application by showing an message and give opportunity to attach the debugger
    if (procName1.Length > 0 || procName2.Length > 0)
    {
        while (true)
        {
            Console.WriteLine("Visual studio is running | Force breakpoint? (Attach the debugger before pressing any key!)");
            Console.WriteLine("[Y]es, [No]");

            DateTime beginWait = DateTime.Now;
            while (!Console.KeyAvailable && DateTime.Now.Subtract(beginWait).TotalSeconds < waitTimeout)
            {
                Thread.Sleep(250); // sleep 1/4 second
            }

            if (!Console.KeyAvailable)
            {
                break; // timeout elapsed without any kepress
                //<----------
            }

            var key = Console.ReadKey(false);
            if (key.Key == ConsoleKey.Y)
            {
                if (System.Diagnostics.Debugger.IsAttached)
                {
                    System.Diagnostics.Debugger.Break(); // force a breakpoint
                    break; // leave the while(true)
                    //<----------
                }
                else
                {
                    Console.WriteLine("No debugger attached");
                    Console.WriteLine("");
                }
            }
            else if (key.Key == ConsoleKey.N)
            {
                break; // leave the while(true)
                //<----------
            }
            Console.WriteLine("");
        }
    }
}

4

Juan的回答是最好的,如果你安装了Visual Studio。但是,如果目标机器没有安装它,你可能需要加入一些暂停(我通常会在main函数中放置一个对话框,让它等待我附加),然后使用远程调试器在你的机器上附加到它。


1
同意。在生产机器上安装VS是一件丑陋的事情 :-D - Juan Ayala
这甚至不是一个生产机器。但我猜他们把它看作是推广到生产环境的测试,这意味着构建管理器是唯一能够部署到开发服务器的人。这就是为什么我无法进行任何远程调试。 - EoRaptor013

0

如果 Excel 运行时间足够长,你可以附加到它,但我认为错误不可能出现在那里。

你可以附加到正在运行的应用程序/进程,如果符号可用(调试版本),你可以真正地进行调试,但应用程序必须存活足够长的时间,以便你选择它进行附加。

从你所说的内容来看,我认为你需要适当的异常和错误日志记录,例如 Log4Net 或 NLog,它们会在每个异常时存储所有内容(堆栈跟踪、异常详细信息...),这样你就可以清楚地确定真正的问题所在。


错误出现在 Excel 的 VSTO 插件中;而且它发生得非常早,以至于在错误已经发生之前没有办法附加到它。再次强调,我可以在我的机器上运行该应用程序而不会出现错误。只有那些从开发服务器使用该应用程序的人才会看到这个错误。 - EoRaptor013

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