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.