Command Line Debugging Revisited - Part 4: Attaching to Processes
Being able to attach to a running process is a very powerful debugger feature. It is especially handy when the application is in the field. With the CorDbg debugger, formal attach to process support was not available when debugging .NET Compact Framework applications. Using the .NET Compact Framework MDbg debugger extension (in version 2 service pack 1), support for attaching the debugger to running applications is now available from the command line.
Note: Before we can attach MDbg to our application (the Visual Studio 2005 WebCrawler sample), we must first enable attach to process support on the device. This step can be performed at any time prior to starting the application we wish to debug. |
When debugging a .NET Compact Framework application, the first step in using MDbg is to load the .NET Compact Framework extension (mdbgnetcf.dll). Once the extension is loaded, we can then make a connection to our target device. These steps are documented in the Getting Started part of this series.
The next step is to start the application we wish to debug. The application can be started on the device by clicking on it's icon, or from MDbg by using the cp[roc]
(create process) command. Since we are already in the debugger, I will use the cp[roc]
command. For more information about cp[roc]
and other process control commands, please see Command Line Debugging Revisited - Part 3: Process Control.
mdbg> cp "\program files\webcrawler.exe"
Our application should now be running on the device. To attach, we need to know the application's process identifier.
mdbg> pro Active processes on current machine: << additional processes removed for clarity >>(PID: 0x6de24e9a) webcrawler.exe
From the output above, we can see that the process identifier for the WebCrawler is 0x6de24e9a
. We will use this value to attach to our application.
mdbg> a 0x6de24e9a
After attaching, we do not return to the mdbg>
prompt. In order to begin debugging our application, we need to break into the debugger using Ctrl+C
.
<Ctrl+C>STOP AsyncStop[p#:0, t#:no active thread] mdbg>
We are now debugging the WebCrawler! For fun, let's set a breakpoint in the Crawl method of the Crawler class.
Setting breakpoints using CorDbg was challenging; the exact name (case-sensitive) had to be entered to be able to successfully set breakpoints on methods. With MDbg this has gotten much easier. Using the x
command, we can search for methods of interest within the WebCrawler module.
[p#:0, t#:no active thread] mdbg> x WebCrawler~0. Microsoft.Samples.NetCF.Crawler.add_CurrentPageEvent(value)~1. Microsoft.Samples.NetCF.Crawler.remove_CurrentPageEvent(value)~2. Microsoft.Samples.NetCF.Crawler.add_PageFoundEvent(value)~3. Microsoft.Samples.NetCF.Crawler.remove_PageFoundEvent(value)~4. Microsoft.Samples.NetCF.Crawler.add_CrawlFinishedEvent(value)~5. Microsoft.Samples.NetCF.Crawler.remove_CrawlFinishedEvent(value)~6. Microsoft.Samples.NetCF.Crawler..ctor(startingPage,noProxy)~7. Microsoft.Samples.NetCF.Crawler.Start()~8. Microsoft.Samples.NetCF.Crawler.Stop()~9. Microsoft.Samples.NetCF.Crawler.PageIsHtml(pageAddress,status)~10. Microsoft.Samples.NetCF.Crawler.GetPageData(pageUri,pageData)~11. Microsoft.Samples.NetCF.Crawler.GetPageLinks(pageUri,pageBody,tag,attribute,links)~12. Microsoft.Samples.NetCF.Crawler.Crawl()~13. Microsoft.Samples.NetCF.Crawler.CurrentPageEventHandler..ctor(object,method)~14. Microsoft.Samples.NetCF.Crawler.CurrentPageEventHandler.Invoke(sender,e)~15. Microsoft.Samples.NetCF.Crawler.CurrentPageEventHandler.BeginInvoke(sender,e,callback,object)~16. Microsoft.Samples.NetCF.Crawler.CurrentPageEventHandler.EndInvoke(result)~17. Microsoft.Samples.NetCF.CurrentPageEventArgs.get_PageAddress()~18. Microsoft.Samples.NetCF.CurrentPageEventArgs..ctor(page)~19. Microsoft.Samples.NetCF.LinkInfo.get_LinkPath()~20. Microsoft.Samples.NetCF.LinkInfo.get_StatusCode()~21. Microsoft.Samples.NetCF.LinkInfo.set_StatusCode(value)~22. Microsoft.Samples.NetCF.LinkInfo..ctor(path,status)~23. Microsoft.Samples.NetCF.MainForm..ctor()~24. Microsoft.Samples.NetCF.MainForm.Dispose(disposing)~25. Microsoft.Samples.NetCF.MainForm.InitializeComponent()~26. Microsoft.Samples.NetCF.MainForm.Main()~27. Microsoft.Samples.NetCF.MainForm.startButton_Click(sender,e)~28. Microsoft.Samples.NetCF.MainForm.HandleCurrentPageEvent(sender,e)~29. Microsoft.Samples.NetCF.MainForm.HandlePageFoundEvent(sender,e)~30. Microsoft.Samples.NetCF.MainForm.HandleCrawlFinishedEvent(sender,e)~31. Microsoft.Samples.NetCF.MainForm.HandleActivityLightsEvent(unused,notused)~32. Microsoft.Samples.NetCF.MainForm.CustomInvokeRequired()
From this list, we see that entry 12 is our desired method. To set a breakpoint on the Crawl method, we can reference the entry number.
[p#:0, t#:no active thread] mdbg> b ~12Breakpoint #1 bound (:1!Microsoft.Samples.NetCF.Crawler::Crawl(+0))
When we continue the application (and click Start in the WebCrawler application), we stop at the beginning of the Crawl method.
[p#:0, t#:no active thread] mdbg> gSTOP: Breakpoint 1 Hitlocated at line 380 in Crawler.cs[p#:0, t#:no active thread] mdbg>
Enjoy!
-- DK
Disclaimer(s): This posting is provided "AS IS" with no warranties, and confers no rights.
Comments
Anonymous
August 25, 2006
Being able to attach to a running process is a very powerful debugger feature.&nbsp; It is especially...Anonymous
September 13, 2006
In the previous installment, I talked about attaching to running processes using MDbg.&nbsp; As part...Anonymous
December 28, 2006
I started this series last year and thought I would continue the tradition with my best of 2006 collection.Anonymous
May 31, 2007
老狼的话:David Kline是.NET CF团队一位非常优秀的开发者,看到他这个系列文章已经很久了,一直没空翻译。今天用下班后的时间翻译出来,也是希望有个督促,能让这个系列文章让更多朋友认识。原文地址: http://blogs.msdn.com/davidklinems/archive/2006/08/25/724718.aspx