<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>David Kline : Debugging</title><link>http://blogs.msdn.com/davidklinems/archive/tags/Debugging/default.aspx</link><description>Tags: Debugging</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>Quick Tip: Debugging Smart Device Unit Tests</title><link>http://blogs.msdn.com/davidklinems/archive/2007/11/12/quick-tip-debugging-smart-device-unit-tests.aspx</link><pubDate>Mon, 12 Nov 2007 21:54:08 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:6147256</guid><dc:creator>DavidKlineMS</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/davidklinems/comments/6147256.aspx</comments><wfw:commentRss>http://blogs.msdn.com/davidklinems/commentrss.aspx?PostID=6147256</wfw:commentRss><description>&lt;p&gt;While browsing &lt;a href="http://msdn2.microsoft.com"&gt;MSDN&lt;/a&gt; today, I came upon a handy article that I wanted to share.&amp;#160;&amp;#160; Titled &lt;a href="http://msdn2.microsoft.com/en-us/library/bb513875(VS.90).aspx"&gt;'How to: Debug while Running a Smart Device Unit Test&lt;/a&gt;', it provides step by step instructions on debugging your test projects.     &lt;br /&gt;    &lt;br /&gt;There is one additional step I would like to add to those listed in the article.     &lt;br /&gt;    &lt;br /&gt;&lt;/p&gt;  &lt;table bordercolor="#800080" cellspacing="0" cellpadding="2" width="60%" border="1"&gt;&lt;tbody&gt;     &lt;tr&gt;       &lt;td valign="top" width="398"&gt;&lt;strong&gt;WARNING&lt;/strong&gt;: Using Remote Registry Editor incorrectly can cause serious problems that may require you to hard reset your device. Microsoft cannot guarantee that problems resulting from the incorrect use of Remote Registry Editor can be solved. Use Remote Registry Editor at your own risk.&lt;/td&gt;     &lt;/tr&gt;   &lt;/tbody&gt;&lt;/table&gt;  &lt;p&gt;   &lt;br /&gt;7. Disable support for attaching to managed processes     &lt;br /&gt;To do this, use the Visual Studio Remote Registry Editor:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;a. Navigate to HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETCompactFramework      &lt;br /&gt;b. Set the value of Managed Debugger\AttachEnabled to 0       &lt;br /&gt;-or-       &lt;br /&gt;Delete the Managed Debugger node&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Take care!    &lt;br /&gt;-- DK     &lt;br /&gt;    &lt;br /&gt;&lt;font face="Arial" size="1"&gt;Disclaimer(s):      &lt;br /&gt;This posting is provided &amp;quot;AS IS&amp;quot; with no warranties, and confers no rights.       &lt;br /&gt;The information contained within this post is in relation to beta software.&amp;#160; Any and all details are subject to change.&lt;/font&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=6147256" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/davidklinems/archive/tags/Debugging/default.aspx">Debugging</category><category domain="http://blogs.msdn.com/davidklinems/archive/tags/Tips+and+Tricks/default.aspx">Tips and Tricks</category><category domain="http://blogs.msdn.com/davidklinems/archive/tags/Quick+Tips/default.aspx">Quick Tips</category></item><item><title>What is a Side Effect?</title><link>http://blogs.msdn.com/davidklinems/archive/2006/10/06/What-is-a-Side-Effect_3F00_.aspx</link><pubDate>Fri, 06 Oct 2006 21:54:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:797027</guid><dc:creator>DavidKlineMS</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/davidklinems/comments/797027.aspx</comments><wfw:commentRss>http://blogs.msdn.com/davidklinems/commentrss.aspx?PostID=797027</wfw:commentRss><description>We've all heard the commercials or read the prescription information sheets describing the possible side effects of medications.&amp;nbsp; The side effects described are typically negative (ex: upset stomach).&amp;nbsp; There are other side effects of a more positive nature; a medication helping treat an illness that it was not designed for, etc.&amp;nbsp; In software, side effects are very similar.&amp;nbsp; Software side effects are any 'unexpected' change in application behavior or data / object state that occur due to execution of some code.&amp;nbsp; &lt;BR&gt;&lt;BR&gt;Side effects in software are quite often encountered when debugging.&amp;nbsp; Evaluating a function in the Visual Studio immediate window or changing which statement to be executed next (set next statement / set instruction pointer) can (and likely will) create side effects.&amp;nbsp; A prime example of side effects while debugging is setting the next statement to either skip or re-execute a portion of code.&amp;nbsp; If any of the code that is skipped or re-executed alters state (global, class or local), the behavior of the application will be altered, often unexpectedly.&lt;BR&gt;&lt;BR&gt;Software side effects are not limited to debugging -- they can manifest anywhere application state is referenced.&amp;nbsp; Debugging is often the easiest way to recognize a side effect (ex: a value unexpectedly changes in the Autos, Locals or Watch window).&amp;nbsp; Be on the lookout for side effects during your debugging session, they can point the way towards otherwise hard to track down bugs.&lt;BR&gt;&lt;BR&gt;Take care,&lt;BR&gt;DK&lt;BR&gt;&lt;BR&gt;&lt;FONT size=1&gt;Disclaimers:&lt;BR&gt;This posting is provided "AS IS" with no warranties, and confers no rights.&lt;BR&gt;&amp;nbsp;&lt;/FONT&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=797027" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/davidklinems/archive/tags/Debugging/default.aspx">Debugging</category></item><item><title>Command Line Debugging Revisited - Part 6: IL Debugging Commands</title><link>http://blogs.msdn.com/davidklinems/archive/2006/09/27/774433.aspx</link><pubDate>Thu, 28 Sep 2006 00:16:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:774433</guid><dc:creator>DavidKlineMS</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/davidklinems/comments/774433.aspx</comments><wfw:commentRss>http://blogs.msdn.com/davidklinems/commentrss.aspx?PostID=774433</wfw:commentRss><description>&lt;A href="http://blogs.msdn.com/bluecollar/"&gt;Dan Elliott&lt;/A&gt; recently posted about the &lt;A href="http://blogs.msdn.com/bluecollar/archive/2006/09/27/773065.aspx"&gt;IL OpCodes supported by the .NET Compact Framework&lt;/A&gt;.&amp;nbsp; This got me inspired to talk about the IL debugging commands in the .NET Compact Framework MDbg extension (mdbgnetcf.dll).&lt;BR&gt;&lt;BR&gt;&lt;B&gt;Commands&lt;/B&gt;&lt;BR&gt;dis[assemble]&lt;BR&gt;in[ext]&lt;BR&gt;is[tep]&lt;BR&gt;o[ut]&lt;BR&gt;&lt;BR&gt;As with the previous installments of this series, I will be using the Visual Studio 2005 WebCrawler sample application as the debuggee.&amp;nbsp; You can download the sample from &lt;A href="http://msdn2.microsoft.com/en-us/library/t7w4afa2.aspx"&gt;here&lt;/A&gt;.&amp;nbsp; To debug at the IL level, we first need to &lt;A href="http://blogs.msdn.com/davidklinems/archive/2006/07/13/665023.aspx"&gt;get connected&lt;/A&gt; to the debuggee (Device Emulator users should refer to &lt;A href="http://blogs.msdn.com/davidklinems/archive/2006/07/14/666050.aspx"&gt;this addendum&lt;/A&gt;).&lt;BR&gt;&lt;BR&gt;Once connected, we can set a breakpoint on an interesting method, I will use Crawler.Crawl().&lt;BR&gt;&lt;BR&gt;&lt;CODE&gt;[p#:0, t#:0] mdbg&amp;gt; x webcrawler!*Crawl*&lt;BR&gt;~0. Microsoft.Samples.NetCF.Crawler.add_CurrentPageEvent(value)&lt;BR&gt;~1. Microsoft.Samples.NetCF.Crawler.remove_CurrentPageEvent(value)&lt;BR&gt;~2. Microsoft.Samples.NetCF.Crawler.add_PageFoundEvent(value)&lt;BR&gt;~3. Microsoft.Samples.NetCF.Crawler.remove_PageFoundEvent(value)&lt;BR&gt;~4. Microsoft.Samples.NetCF.Crawler.add_CrawlFinishedEvent(value)&lt;BR&gt;~5. Microsoft.Samples.NetCF.Crawler.remove_CrawlFinishedEvent(value)&lt;BR&gt;~6. Microsoft.Samples.NetCF.Crawler..ctor(startingPage,noProxy)&lt;BR&gt;~7. Microsoft.Samples.NetCF.Crawler.Start()&lt;BR&gt;~8. Microsoft.Samples.NetCF.Crawler.Stop()&lt;BR&gt;~9. Microsoft.Samples.NetCF.Crawler.PageIsHtml(pageAddress,status)&lt;BR&gt;~10. Microsoft.Samples.NetCF.Crawler.GetPageData(pageUri,pageData)&lt;BR&gt;~11. Microsoft.Samples.NetCF.Crawler.GetPageLinks(pageUri,pageBody,tag,attribute,links)&lt;BR&gt;~12. Microsoft.Samples.NetCF.Crawler.Crawl()&lt;BR&gt;~13. Microsoft.Samples.NetCF.Crawler.CurrentPageEventHandler..ctor(object,method)&lt;BR&gt;~14. Microsoft.Samples.NetCF.Crawler.CurrentPageEventHandler.Invoke(sender,e)&lt;BR&gt;~15. Microsoft.Samples.NetCF.Crawler.CurrentPageEventHandler.BeginInvoke(sender,e,callback,object)&lt;BR&gt;~16. Microsoft.Samples.NetCF.Crawler.CurrentPageEventHandler.EndInvoke(result)&lt;BR&gt;~17. Microsoft.Samples.NetCF.MainForm.HandleCrawlFinishedEvent(sender,e)&lt;BR&gt;[p#:0, t#:0] mdbg&amp;gt; b ~12&lt;BR&gt;Breakpoint #1 bound (:1!Microsoft.Samples.NetCF.Crawler::Crawl(+0))&lt;BR&gt;[p#:0, t#:0] mdbg&amp;gt; g &lt;/CODE&gt;&lt;BR&gt;&lt;BR&gt;After hitting the breakpoint, we can look at the disassembly using the dis[assemble] command.&lt;BR&gt;&lt;BR&gt;&lt;CODE&gt;STOP: Breakpoint 1 Hit&lt;BR&gt;located at line 380 in Crawler.cs&lt;BR&gt;[p#:0, t#:1] mdbg&amp;gt; dis 5&lt;BR&gt;IL at 0x49e0172c&lt;BR&gt;*[IL:0000] 00: nop&lt;BR&gt;&amp;nbsp;[IL:0001] 14: ldnull&lt;BR&gt;&amp;nbsp;[IL:0002] 0a: stloc.0&lt;BR&gt;&amp;nbsp;[IL:0003] 00: nop&lt;BR&gt;&amp;nbsp;[IL:0004] 28:4100000a call System.StringComparer::get_InvariantCultureIgnoreCase&lt;BR&gt;&lt;/CODE&gt;&lt;BR&gt;Stepping through IL code is as easy as stepping through high level languages (C#, VB.Net) using the in[ext] command.&lt;BR&gt;&lt;BR&gt;&lt;CODE&gt;p#:0, t#:1] mdbg&amp;gt; in&lt;BR&gt;L at 0x49e0172c&lt;BR&gt;&amp;nbsp;[IL:0000] 00: nop&lt;BR&gt;*[IL:0001] 14: ldnull&lt;BR&gt;&amp;nbsp;[IL:0002] 0a: stloc.0&lt;BR&gt;&amp;nbsp;[IL:0003] 00: nop&lt;BR&gt;&amp;nbsp;[IL:0004] 28:4100000a call System.StringComparer::get_InvariantCultureIgnoreCase&lt;BR&gt;&lt;/CODE&gt;&lt;BR&gt;This is a pretty long method and single stepping can be time consuming.&amp;nbsp; To save me some time, I am going to set an additional breakpoint on the call to Crawler.GetPageData().&lt;BR&gt;&lt;BR&gt;&lt;CODE&gt;[p#:0, t#:1] mdbg&amp;gt; sh 100&lt;BR&gt;&amp;lt; additional lines removed for space / clarity &amp;gt;&lt;BR&gt;425 LinkInfo li = (LinkInfo)links[page];&lt;BR&gt;426 // check that the page contains html text&lt;BR&gt;427 try&lt;BR&gt;428 {&lt;BR&gt;429 // get the currently stored HttpStatusCode&lt;BR&gt;430 // for the target page&lt;BR&gt;431 HttpStatusCode currentStatus = li.StatusCode;&lt;BR&gt;432&lt;BR&gt;433 // check to see if we have tried to connect&lt;BR&gt;434 // and if the page is HTML&lt;BR&gt;435 if (((HttpStatusCode)0 == currentStatus) &amp;amp;&amp;amp;&lt;BR&gt;436 PageIsHtml(page, out currentStatus))&lt;BR&gt;437 {&lt;BR&gt;438 // read the page&lt;BR&gt;439 Uri pageUri = new Uri(page);&lt;BR&gt;440 string pageData = "";&lt;BR&gt;441 currentStatus = GetPageData(ref pageUri,&lt;BR&gt;442 out pageData);&lt;BR&gt;&amp;lt; additional lines removed for space / clarity &amp;gt;&lt;BR&gt;[p#:0, t#:1] mdbg&amp;gt; b 441&lt;BR&gt;Breakpoint #2 bound (line 441 in Crawler.cs)&lt;BR&gt;[p#:0, t#:1] mdbg&amp;gt; g&lt;BR&gt;&lt;/CODE&gt;&lt;BR&gt;Now that I am at the second breakpoint, I would like to step into the call to Crawler.GetPageData().&amp;nbsp; As with in[ext], there is a corresponding step into command for IL: is[tep].&lt;BR&gt;&lt;BR&gt;&lt;CODE&gt;STOP: Breakpoint 2 Hit&lt;BR&gt;441: currentStatus = GetPageData(ref pageUri,&lt;BR&gt;[p#:0, t#:1] mdbg&amp;gt; is&lt;BR&gt;IL at 0x49e01388&lt;BR&gt;*[IL:0000] 00: nop&lt;BR&gt;&amp;nbsp;[IL:0001] 16: ldc.i4.0&lt;BR&gt;&amp;nbsp;[IL:0002] 0a: stloc.0&lt;BR&gt;&amp;nbsp;[IL:0003] 14: ldnull&lt;BR&gt;&amp;nbsp;[IL:0004] 0b: stloc.1&lt;BR&gt;&lt;/CODE&gt;&lt;BR&gt;The stack shows that we are at the start of the Crawler.GetPageData method.&lt;BR&gt;&lt;BR&gt;&lt;CODE&gt;[p#:0, t#:1] mdbg&amp;gt; w&lt;BR&gt;Thread [#:1]&lt;BR&gt;*0. Microsoft.Samples.NetCF.Crawler.GetPageData (Crawler.cs:216)&lt;BR&gt;&amp;nbsp;1. Microsoft.Samples.NetCF.Crawler.Crawl (Crawler.cs:441)&lt;BR&gt;&lt;/CODE&gt;&lt;BR&gt;I can now step through Crawler.GetPageData in IL as desired.&amp;nbsp; &lt;BR&gt;&lt;BR&gt;&lt;CODE&gt;[p#:0, t#:1] mdbg&amp;gt; in&lt;BR&gt;IL at 0x49e01388&lt;BR&gt;&amp;nbsp;[IL:0000] 00: nop&lt;BR&gt;*[IL:0001] 16: ldc.i4.0&lt;BR&gt;&amp;nbsp;[IL:0002] 0a: stloc.0&lt;BR&gt;&amp;nbsp;[IL:0003] 14: ldnull&lt;BR&gt;&amp;nbsp;[IL:0004] 0b: stloc.1&lt;BR&gt;&lt;/CODE&gt;&lt;BR&gt;When I am no longer interested in debugging the method, I can return to the caller using the o[ut] command.&amp;nbsp; This returns me to where I left off in the Crawler.Crawl method.&lt;BR&gt;&lt;BR&gt;&lt;CODE&gt;[p#:0, t#:1] mdbg&amp;gt; o&lt;BR&gt;441: currentStatus = GetPageData(ref pageUri,&lt;BR&gt;&lt;/CODE&gt;&lt;BR&gt;The stack and source confirm that we have returned to the Crawler.Crawl() method at the call to Crawler.GetPageData().&lt;BR&gt;&lt;BR&gt;&lt;CODE&gt;[p#:0, t#:1] mdbg&amp;gt; w&lt;BR&gt;Thread [#:1]&lt;BR&gt;*0. Microsoft.Samples.NetCF.Crawler.Crawl (Crawler.cs:441)&lt;BR&gt;[p#:0, t#:1] mdbg&amp;gt; sh 5&lt;BR&gt;436 PageIsHtml(page, out currentStatus))&lt;BR&gt;437 {&lt;BR&gt;438 // read the page&lt;BR&gt;439 Uri pageUri = new Uri(page);&lt;BR&gt;440 string pageData = "";&lt;BR&gt;441:* currentStatus = GetPageData(ref pageUri,&lt;BR&gt;442 out pageData);&lt;BR&gt;443&lt;BR&gt;444 // if we successfully retrieved the page data&lt;BR&gt;445 if (HttpStatusCode.OK == currentStatus)&lt;BR&gt;&lt;/CODE&gt;&lt;BR&gt;For more information on the commands I have used here, please refer to the MDbg h[elp] command.&lt;BR&gt;&lt;BR&gt;Take care,&lt;BR&gt;-- DK&lt;BR&gt;&lt;BR&gt;&lt;FONT size=1&gt;Disclaimers:&lt;BR&gt;This posting is provided "AS IS" with no warranties, and confers no rights.&lt;BR&gt;&lt;/FONT&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=774433" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/davidklinems/archive/tags/Debugging/default.aspx">Debugging</category></item><item><title>Command Line Debugging Revisited - Part 5: The X Command</title><link>http://blogs.msdn.com/davidklinems/archive/2006/09/13/752632.aspx</link><pubDate>Wed, 13 Sep 2006 22:53:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:752632</guid><dc:creator>DavidKlineMS</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/davidklinems/comments/752632.aspx</comments><wfw:commentRss>http://blogs.msdn.com/davidklinems/commentrss.aspx?PostID=752632</wfw:commentRss><description>In the previous installment, I talked about &lt;A href="http://blogs.msdn.com/davidklinems/archive/2006/08/25/724718.aspx"&gt;attaching to running processes using MDbg&lt;/A&gt;.&amp;nbsp; As part of that discussion, I used the &lt;CODE&gt;X&lt;/CODE&gt; command.&amp;nbsp; Today, I'd like to spend a little time on &lt;CODE&gt;X&lt;/CODE&gt;.&amp;nbsp; The &lt;CODE&gt;X command&lt;/CODE&gt; is one of those great features of MDbg that I think is worth the price of admission by itself.&lt;BR&gt;&lt;BR&gt;From MDbg's online help:&lt;BR&gt;&lt;BR&gt;&lt;CODE&gt;mdbg&amp;gt; ? x&lt;BR&gt;abbrev: x&lt;BR&gt;Usage: x [-c numSymbols] [module[!pattern]]&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Displays functions matching [pattern] for a module. If numSymbols is&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; provided, the output is limited to the given number. If !regex is not&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; provided, all functions are displayed. If module is not provided either,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; all loaded modules are displayed. Symbols (~#) may be used to set&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; breakpoints using the "break" command.&lt;BR&gt;Example: x mscorlib!*String*&lt;BR&gt;See Also:&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; break&lt;/CODE&gt;&lt;BR&gt;&lt;BR&gt;I won't be going into all of the features of &lt;CODE&gt;X&lt;/CODE&gt; here, rather I will demonstrate the ways that I most often use the command.&lt;BR&gt;&lt;BR&gt;I'll use the Visual Studio 2005 WebCrawler sample application to show some of the cool features of &lt;CODE&gt;X&lt;/CODE&gt; in action.&amp;nbsp; Once connected to the debuggee (via &lt;CODE&gt;&lt;A href="http://blogs.msdn.com/davidklinems/archive/2006/07/13/665023.aspx"&gt;Run&lt;/A&gt;&lt;/CODE&gt; or &lt;CODE&gt;&lt;A href="http://blogs.msdn.com/davidklinems/archive/2006/08/25/724718.aspx"&gt;Attach&lt;/A&gt;&lt;/CODE&gt;), we are ready to go.&lt;BR&gt;&lt;BR&gt;When debugging using command line tools, one of the most challenging tasks is getting the fully qualified names of functions correct when setting breakpoints.&amp;nbsp; Namespaces can get long (as you will see in my examples) and the casing of names must be 100% accurate.&amp;nbsp; &lt;CODE&gt;X&lt;/CODE&gt; makes this much much easier, as we will see.&lt;BR&gt;&lt;BR&gt;&lt;B&gt;Getting the list of loaded modules&lt;BR&gt;&lt;/B&gt;In it's simplest form, &lt;CODE&gt;X&lt;/CODE&gt; will display the modules loaded in your application.&lt;BR&gt;&lt;BR&gt;&lt;CODE&gt;[p#:0, t#:0] mdbg&amp;gt; x&lt;BR&gt;Please specify module.&lt;BR&gt;Loaded Modules:&lt;BR&gt;:0 mscorlib.dll#0 (no symbols loaded)&lt;BR&gt;:1 webcrawler.exe#0&lt;BR&gt;:2 System.Windows.Forms.dll#0 (no symbols loaded)&lt;BR&gt;:3 System.dll#0 (no symbols loaded)&lt;BR&gt;:4 System.Drawing.dll#0 (no symbols loaded)&lt;/CODE&gt;&lt;BR&gt;&lt;BR&gt;If you are a user of the Modules window in the Visual Studio 2005 debugger, as I am, this usage will be very familiar and handy.&amp;nbsp; The one useful thing missing from this display is the path from where the symbols were loaded, which the Visual Studio 2005 Modules window provides.
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;B&gt;Setting a breakpoint on a function&lt;BR&gt;&lt;/B&gt;My favorite way to use &lt;CODE&gt;X&lt;/CODE&gt; is to help me set breakpoints on functions.&amp;nbsp; As I mentioned earlier, entering fully qualified names exactly right can be challenging, especially when they get long.&amp;nbsp; &lt;CODE&gt;X&lt;/CODE&gt; really helps here by allowing us to search for functions by name fragments.&amp;nbsp; In the example below, I am looking for anything (methods, classes, etc) with "Crawl" as part of the name.&lt;BR&gt;&lt;BR&gt;&lt;CODE&gt;[p#:0, t#:0] mdbg&amp;gt; x webcrawler.exe!*Crawl*&lt;BR&gt;~0. Microsoft.Samples.NetCF.Crawler.add_CurrentPageEvent(value)&lt;BR&gt;~1. Microsoft.Samples.NetCF.Crawler.remove_CurrentPageEvent(value)&lt;BR&gt;~2. Microsoft.Samples.NetCF.Crawler.add_PageFoundEvent(value)&lt;BR&gt;~3. Microsoft.Samples.NetCF.Crawler.remove_PageFoundEvent(value)&lt;BR&gt;~4. Microsoft.Samples.NetCF.Crawler.add_CrawlFinishedEvent(value)&lt;BR&gt;~5. Microsoft.Samples.NetCF.Crawler.remove_CrawlFinishedEvent(value)&lt;BR&gt;~6. Microsoft.Samples.NetCF.Crawler..ctor(startingPage,noProxy)&lt;BR&gt;~7. Microsoft.Samples.NetCF.Crawler.Start()&lt;BR&gt;~8. Microsoft.Samples.NetCF.Crawler.Stop()&lt;BR&gt;~9. Microsoft.Samples.NetCF.Crawler.PageIsHtml(pageAddress,status)&lt;BR&gt;~10. Microsoft.Samples.NetCF.Crawler.GetPageData(pageUri,pageData)&lt;BR&gt;~11. Microsoft.Samples.NetCF.Crawler.GetPageLinks(pageUri,pageBody,tag,attribute,links)&lt;BR&gt;~12. Microsoft.Samples.NetCF.Crawler.Crawl()&lt;BR&gt;~13. Microsoft.Samples.NetCF.Crawler.CurrentPageEventHandler..ctor(object,method)&lt;BR&gt;~14. Microsoft.Samples.NetCF.Crawler.CurrentPageEventHandler.Invoke(sender,e)&lt;BR&gt;~15. Microsoft.Samples.NetCF.Crawler.CurrentPageEventHandler.BeginInvoke(sender,e,callback,object)&lt;BR&gt;~16. Microsoft.Samples.NetCF.Crawler.CurrentPageEventHandler.EndInvoke(result)&lt;BR&gt;~17. Microsoft.Samples.NetCF.MainForm.HandleCrawlFinishedEvent(sender,e)&lt;/CODE&gt;&lt;BR&gt;&lt;BR&gt;When we search by a part of the name, we get a numbered list of symbols that match our fragment.&amp;nbsp; If the list contains our desired function, we can set a breakpoint very easily by specifying the index of the function within the list.&amp;nbsp; The results above returned all methods from the Crawler class as well as the event handler for the CrawlFinishedEvent within the MainForm class.&amp;nbsp; I am interested in debugging the event handler, so I'll set a breakpoint there.&lt;BR&gt;&lt;BR&gt;&lt;CODE&gt;[p#:0, t#:0] mdbg&amp;gt; b ~17&lt;BR&gt;Breakpoint #1 bound (:1!Microsoft.Samples.NetCF.MainForm::HandleCrawlFinishedEvent(+0))&lt;/CODE&gt;&lt;BR&gt;&lt;BR&gt;This is much more convenient than retyping the name (&lt;CODE&gt;Microsoft.Samples.NetCF.MainForm.HandleCrawlFinishedEvent&lt;/CODE&gt;), or using the Mark - Copy - Paste feature of the Windows Command Prompt.&amp;nbsp; It is important to be sure to use the tilde (~) when specifying the list index.&amp;nbsp; Forgetting to do so will attempt to set a breakpoint by line number within the current source file as shown in the example below.&lt;BR&gt;&lt;BR&gt;&lt;CODE&gt;[p#:0, t#:0] mdbg&amp;gt; b 17&lt;BR&gt;Breakpoint #2 bound (line 17 in MainForm.cs)&lt;/CODE&gt;&lt;BR&gt;&lt;BR&gt;Enjoy!&lt;BR&gt;-- DK&lt;BR&gt;&lt;BR&gt;&lt;FONT size=1&gt;Disclaimer(s): This posting is provided "AS IS" with no warranties, and confers no rights.&lt;/FONT&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=752632" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/davidklinems/archive/tags/Debugging/default.aspx">Debugging</category><category domain="http://blogs.msdn.com/davidklinems/archive/tags/Tips+and+Tricks/default.aspx">Tips and Tricks</category></item><item><title>Using the .NET Compact Framework Remote Performance Monitor to Configure Diagnostic Options</title><link>http://blogs.msdn.com/davidklinems/archive/2006/08/31/734123.aspx</link><pubDate>Thu, 31 Aug 2006 23:26:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:734123</guid><dc:creator>DavidKlineMS</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/davidklinems/comments/734123.aspx</comments><wfw:commentRss>http://blogs.msdn.com/davidklinems/commentrss.aspx?PostID=734123</wfw:commentRss><description>Diagnostic, performance and debugging tools are very cool.&amp;nbsp; The more tools available, the easier it tends to be to find and fix application issues.&amp;nbsp; With Visual Studio 2005, several handy tools were added.&amp;nbsp; I use the Remote Registry Editor and Remote File Viewer just about every day.&amp;nbsp; Version 2 of the .NET Compact Framework added diagnostic logs (enabled via the device registry) to help identify application problems in places where it was very difficult, or not possible to find them with other tools.&amp;nbsp; &lt;BR&gt;&lt;BR&gt;One difficulty with using the diagnostic logs is setting the registry options.&amp;nbsp; Modifying the registry can be intimidating and, if done incorrectly, a risky proposition.&amp;nbsp; Readers familiar with my writings on using the diagnostic logs will recall that every time I mention the Remote Registry Editor, I include a warning to use the tool with great care.&amp;nbsp; &lt;BR&gt;&lt;BR&gt;A few months ago, &lt;A href="http://blogs.msdn.com/stevenpr"&gt;Steven&lt;/A&gt; posted a tour of the &lt;A href="http://blogs.msdn.com/stevenpr/archive/2006/04/17/577636.aspx"&gt;.NET Compact Framework Remote Performance Monitor&lt;/A&gt;.&amp;nbsp; He talked about installation, getting connected, publishing the statistics to the Windows Performance Monitor and touched upon what I am going to talk about today.&lt;BR&gt;&lt;BR&gt;Did you know that you can use the .NET Compact Framework Remote Performance Monitor to configure diagnostic options on a device?&lt;BR&gt;&lt;BR&gt;The other day, I was writing about &lt;A href="http://blogs.msdn.com/davidklinems/archive/2006/08/25/724718.aspx"&gt;using the MDbg command line debugger to attach to a .NET Compact Framework application&lt;/A&gt; and I needed to enable attach to process support.&amp;nbsp; On my way to the Start menu to run the Remote Registry Editor, I noticed that I had the .NET Compact Framework Remote Performance Monitor running and remembered that it could configure the device registry for me.&amp;nbsp; Having had the experience of&lt;A href="http://blogs.msdn.com/davidklinems/archive/2006/06/16/634503.aspx"&gt; incorrectly modifying this very registry flag while presenting at MEDC&lt;/A&gt;, I decided to save myself the embarrassment of making the same mistake again.&lt;BR&gt;&lt;BR&gt;On the Device menu of the .NET Compact Framework Remote Performance Monitor,&amp;nbsp;select&amp;nbsp;Logging Options.&amp;nbsp; &lt;BR&gt;&lt;BR&gt;&lt;A href="http://blogs.msdn.com/photos/davidklinems/picture734104.aspx" target=_blank&gt;&lt;IMG src="http://blogs.msdn.com/photos/davidklinems/images/734104/464x358.aspx" border=0&gt;&lt;/A&gt;&lt;BR&gt;&lt;BR&gt;The first step that is required is to connect to your device.&amp;nbsp; The steps to connect here are the same as those &lt;A href="http://blogs.msdn.com/stevenpr/archive/2006/04/17/577636.aspx"&gt;Steven describes to connect to the performance statistics&lt;/A&gt;.&amp;nbsp; Once connected, you can configure your desired diagnostic settings.&lt;BR&gt;&lt;BR&gt;Once connected, you can 
&lt;P&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Enable the &lt;A href="http://blogs.msdn.com/stevenpr/archive/2005/02/28/381744.aspx"&gt;Loader&lt;/A&gt;, &lt;A href="http://blogs.msdn.com/stevenpr/archive/2005/06/22/431612.aspx"&gt;Native Interop&lt;/A&gt; and Network logs&lt;/LI&gt;
&lt;LI&gt;Configure log file naming options&lt;/LI&gt;
&lt;LI&gt;Enable &lt;A href="http://blogs.msdn.com/davidklinems/archive/2005/12/09/502125.aspx"&gt;performance statistics&lt;/A&gt; (.stat) file creation&lt;/LI&gt;
&lt;LI&gt;Enable &lt;A href="http://blogs.msdn.com/davidklinems/archive/2005/05/24/421566.aspx"&gt;attach to process support in the debugger&lt;/A&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Enjoy!&lt;BR&gt;-- DK&lt;BR&gt;&lt;BR&gt;&lt;FONT size=1&gt;Disclaimer(s): This posting is provided "AS IS" with no warranties, and confers no rights.&lt;/FONT&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=734123" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/davidklinems/archive/tags/Debugging/default.aspx">Debugging</category><category domain="http://blogs.msdn.com/davidklinems/archive/tags/Tips+and+Tricks/default.aspx">Tips and Tricks</category><category domain="http://blogs.msdn.com/davidklinems/archive/tags/Performance/default.aspx">Performance</category><category domain="http://blogs.msdn.com/davidklinems/archive/tags/Diagnostics/default.aspx">Diagnostics</category></item><item><title>Command Line Debugging Revisited - Part 4: Attaching to Processes</title><link>http://blogs.msdn.com/davidklinems/archive/2006/08/25/724718.aspx</link><pubDate>Sat, 26 Aug 2006 02:58:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:724718</guid><dc:creator>DavidKlineMS</dc:creator><slash:comments>4</slash:comments><comments>http://blogs.msdn.com/davidklinems/comments/724718.aspx</comments><wfw:commentRss>http://blogs.msdn.com/davidklinems/commentrss.aspx?PostID=724718</wfw:commentRss><description>Being able to attach to a running process is a very powerful debugger feature.&amp;nbsp; It is especially handy when the application is in the field.&amp;nbsp; With the CorDbg debugger, formal attach to process support was not available when debugging .NET Compact Framework applications.&amp;nbsp; 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. 
&lt;P&gt;&lt;/P&gt;
&lt;TABLE cellSpacing=0 borderColorDark=#800080 width="50%" borderColorLight=#800080 border=1&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD&gt;&lt;B&gt;Note:&lt;/B&gt; Before we can attach MDbg to our application (the Visual Studio 2005 WebCrawler sample), we must first &lt;A href="http://blogs.msdn.com/davidklinems/archive/2005/05/24/421566.aspx"&gt;enable attach to process support&lt;/A&gt; on the device.&amp;nbsp; This step can be performed at any time prior to starting the application we wish to debug.&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;P&gt;When debugging a .NET Compact Framework application, the first step in using MDbg is to load the .NET Compact Framework extension (mdbgnetcf.dll).&amp;nbsp; Once the extension is loaded, we can then make a connection to our target device.&amp;nbsp; These steps are documented in the &lt;A href="http://blogs.msdn.com/davidklinems/archive/2006/07/13/665023.aspx"&gt;Getting Started&lt;/A&gt; part of this series.&lt;BR&gt;&lt;BR&gt;The next step is to start the application we wish to debug.&amp;nbsp; The application can be started on the device by clicking on it's icon, or from MDbg by using the &lt;CODE&gt;cp[roc]&lt;/CODE&gt; (create process) command. Since we are already in the debugger, I will use the &lt;CODE&gt;cp[roc]&lt;/CODE&gt; command.&amp;nbsp; For more information about &lt;CODE&gt;cp[roc]&lt;/CODE&gt; and other process control commands, please see &lt;A id=_ctl0____ctl0___Month___postlist___EntryItems__ctl1_PostTitle href="http://blogs.msdn.com/davidklinems/archive/2006/08/11/695975.aspx"&gt;Command Line Debugging Revisited - Part 3: Process Control&lt;/A&gt;.&lt;BR&gt;&lt;BR&gt;&lt;CODE&gt;mdbg&amp;gt; cp "\program files\webcrawler.exe"&lt;/CODE&gt;&lt;BR&gt;&lt;BR&gt;Our application should now be running on the device.&amp;nbsp; To attach, we need to know the application's process identifier.&lt;BR&gt;&lt;BR&gt;&lt;CODE&gt;mdbg&amp;gt; pro &lt;BR&gt;Active processes on current machine: &lt;BR&gt;&amp;lt;&amp;lt; additional processes removed for clarity &amp;gt;&amp;gt;&lt;BR&gt;(PID: 0x6de24e9a) webcrawler.exe&lt;/CODE&gt;&lt;BR&gt;&lt;BR&gt;From the output above, we can see that the process identifier for the WebCrawler is &lt;CODE&gt;0x6de24e9a&lt;/CODE&gt;.&amp;nbsp; We will use this value to attach to our application.&lt;BR&gt;&lt;BR&gt;&lt;CODE&gt;mdbg&amp;gt; a 0x6de24e9a&lt;/CODE&gt;&lt;BR&gt;&lt;BR&gt;After attaching, we do not return to the &lt;CODE&gt;mdbg&amp;gt;&lt;/CODE&gt; prompt.&amp;nbsp; In order to begin debugging our application, we need to break into the debugger using &lt;CODE&gt;Ctrl+C&lt;/CODE&gt;.&lt;BR&gt;&lt;BR&gt;&lt;CODE&gt;&amp;lt;Ctrl+C&amp;gt;&lt;BR&gt;STOP AsyncStop&lt;BR&gt;[p#:0, t#:no active thread] mdbg&amp;gt;&lt;/CODE&gt;&lt;BR&gt;&lt;BR&gt;We are now debugging the WebCrawler!&amp;nbsp; For fun, let's set a breakpoint in the Crawl method of the Crawler class.&lt;BR&gt;&lt;BR&gt;Setting breakpoints using CorDbg was challenging; the exact name (case-sensitive) had to be entered to be able to successfully set breakpoints on methods.&amp;nbsp; With MDbg this has gotten much easier.&amp;nbsp; Using the &lt;CODE&gt;x&lt;/CODE&gt; command, we can search for methods of interest within the WebCrawler module.&lt;BR&gt;&lt;BR&gt;&lt;CODE&gt;[p#:0, t#:no active thread] mdbg&amp;gt; x WebCrawler&lt;BR&gt;~0. Microsoft.Samples.NetCF.Crawler.add_CurrentPageEvent(value)&lt;BR&gt;~1. Microsoft.Samples.NetCF.Crawler.remove_CurrentPageEvent(value)&lt;BR&gt;~2. Microsoft.Samples.NetCF.Crawler.add_PageFoundEvent(value)&lt;BR&gt;~3. Microsoft.Samples.NetCF.Crawler.remove_PageFoundEvent(value)&lt;BR&gt;~4. Microsoft.Samples.NetCF.Crawler.add_CrawlFinishedEvent(value)&lt;BR&gt;~5. Microsoft.Samples.NetCF.Crawler.remove_CrawlFinishedEvent(value)&lt;BR&gt;~6. Microsoft.Samples.NetCF.Crawler..ctor(startingPage,noProxy)&lt;BR&gt;~7. Microsoft.Samples.NetCF.Crawler.Start()&lt;BR&gt;~8. Microsoft.Samples.NetCF.Crawler.Stop()&lt;BR&gt;~9. Microsoft.Samples.NetCF.Crawler.PageIsHtml(pageAddress,status)&lt;BR&gt;~10. Microsoft.Samples.NetCF.Crawler.GetPageData(pageUri,pageData)&lt;BR&gt;~11. Microsoft.Samples.NetCF.Crawler.GetPageLinks(pageUri,pageBody,tag,attribute,links)&lt;BR&gt;~12. Microsoft.Samples.NetCF.Crawler.Crawl()&lt;BR&gt;~13. Microsoft.Samples.NetCF.Crawler.CurrentPageEventHandler..ctor(object,method)&lt;BR&gt;~14. Microsoft.Samples.NetCF.Crawler.CurrentPageEventHandler.Invoke(sender,e)&lt;BR&gt;~15. Microsoft.Samples.NetCF.Crawler.CurrentPageEventHandler.BeginInvoke(sender,e,callback,object)&lt;BR&gt;~16. Microsoft.Samples.NetCF.Crawler.CurrentPageEventHandler.EndInvoke(result)&lt;BR&gt;~17. Microsoft.Samples.NetCF.CurrentPageEventArgs.get_PageAddress()&lt;BR&gt;~18. Microsoft.Samples.NetCF.CurrentPageEventArgs..ctor(page)&lt;BR&gt;~19. Microsoft.Samples.NetCF.LinkInfo.get_LinkPath()&lt;BR&gt;~20. Microsoft.Samples.NetCF.LinkInfo.get_StatusCode()&lt;BR&gt;~21. Microsoft.Samples.NetCF.LinkInfo.set_StatusCode(value)&lt;BR&gt;~22. Microsoft.Samples.NetCF.LinkInfo..ctor(path,status)&lt;BR&gt;~23. Microsoft.Samples.NetCF.MainForm..ctor()&lt;BR&gt;~24. Microsoft.Samples.NetCF.MainForm.Dispose(disposing)&lt;BR&gt;~25. Microsoft.Samples.NetCF.MainForm.InitializeComponent()&lt;BR&gt;~26. Microsoft.Samples.NetCF.MainForm.Main()&lt;BR&gt;~27. Microsoft.Samples.NetCF.MainForm.startButton_Click(sender,e)&lt;BR&gt;~28. Microsoft.Samples.NetCF.MainForm.HandleCurrentPageEvent(sender,e)&lt;BR&gt;~29. Microsoft.Samples.NetCF.MainForm.HandlePageFoundEvent(sender,e)&lt;BR&gt;~30. Microsoft.Samples.NetCF.MainForm.HandleCrawlFinishedEvent(sender,e)&lt;BR&gt;~31. Microsoft.Samples.NetCF.MainForm.HandleActivityLightsEvent(unused,notused)&lt;BR&gt;~32. Microsoft.Samples.NetCF.MainForm.CustomInvokeRequired()&lt;/CODE&gt;&lt;BR&gt;&lt;BR&gt;From this list, we see that entry 12 is our desired method.&amp;nbsp; To set a breakpoint on the Crawl method, we can reference the entry number.&lt;BR&gt;&lt;BR&gt;&lt;CODE&gt;[p#:0, t#:no active thread] mdbg&amp;gt; b ~12&lt;BR&gt;Breakpoint #1 bound (:1!Microsoft.Samples.NetCF.Crawler::Crawl(+0))&lt;/CODE&gt;&lt;BR&gt;&lt;BR&gt;When we continue the application (and click Start in the WebCrawler application), we stop at the beginning of the Crawl method.&lt;BR&gt;&lt;BR&gt;&lt;CODE&gt;[p#:0, t#:no active thread] mdbg&amp;gt; g&lt;BR&gt;STOP: Breakpoint 1 Hit&lt;BR&gt;located at line 380 in Crawler.cs&lt;BR&gt;[p#:0, t#:no active thread] mdbg&amp;gt;&lt;BR&gt;&lt;/CODE&gt;&lt;BR&gt;Enjoy!&lt;BR&gt;-- DK&lt;BR&gt;&lt;BR&gt;&lt;FONT size=1&gt;Disclaimer(s): This posting is provided "AS IS" with no warranties, and confers no rights.&lt;/FONT&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=724718" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/davidklinems/archive/tags/Debugging/default.aspx">Debugging</category></item><item><title>The Error Log: A New Diagnostic in .NET Compact Framework v2 Service Pack 1</title><link>http://blogs.msdn.com/davidklinems/archive/2006/08/17/704662.aspx</link><pubDate>Thu, 17 Aug 2006 22:36:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:704662</guid><dc:creator>DavidKlineMS</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/davidklinems/comments/704662.aspx</comments><wfw:commentRss>http://blogs.msdn.com/davidklinems/commentrss.aspx?PostID=704662</wfw:commentRss><description>The &lt;A href="http://blogs.msdn.com/netcfteam/archive/2006/08/04/688766.aspx"&gt;recent release of Service Pack 1 for the .NET Compact Framework version 2&lt;/A&gt; has added some very useful diagnostic tools.&amp;nbsp; You may have already read about the &lt;A href="http://blogs.msdn.com/stevenpr/archive/2006/04/17/577636.aspx"&gt;.NET Compact Framework Remote Performance Monitor&lt;/A&gt;, and have hopefully used it to analyze the performance characteristics of your applications.&amp;nbsp; Today, I would like to talk about another new diagnostic tool: the error log.&lt;BR&gt;&lt;BR&gt;With the addition of support for headless devices, it became apparent that we needed a means for capturing details about unexpected errors.&amp;nbsp; It is not always feasible to run applications under a debugger, and not all error conditions occur with the consistency that makes them easy to diagnose.&amp;nbsp; To help address this, the error log was created.&amp;nbsp; While the error log is typically most useful for headless devices, it is available for all devices running .NET Compact Framework version 2 service pack 1.&lt;BR&gt;&lt;BR&gt;&lt;B&gt;Enabling Error Logging&lt;/B&gt;&lt;BR&gt;The Error Log is enabled via the device's registry. In my steps, below, I will be using the Remote Registry Editor that is included with Visual Studio 2005.&amp;nbsp; 
&lt;P&gt;&lt;/P&gt;
&lt;TABLE borderColor=#800080 cellSpacing=0 width="50%" border=1&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD&gt;&lt;B&gt;WARNING&lt;/B&gt;: Using Remote Registry Editor incorrectly can cause serious problems that may require you to hard reset your device. Microsoft cannot guarantee that problems resulting from the incorrect use of Remote Registry Editor can be solved. Use Remote Registry Editor at your own risk.&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;OL&gt;
&lt;LI&gt;Start the Remote Registry Editor 
&lt;UL&gt;
&lt;LI&gt;Open the Start Menu&lt;/LI&gt;
&lt;LI&gt;Select All Programs&lt;/LI&gt;
&lt;LI&gt;Select Microsoft Visual Studio 2005&lt;/LI&gt;
&lt;LI&gt;Select Visual Studio Remote Tools&lt;/LI&gt;
&lt;LI&gt;Select Remote Registry Editor&lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;
&lt;LI&gt;Connect to your device
&lt;UL&gt;
&lt;LI&gt;On the Target menu, select Connect&lt;/LI&gt;
&lt;LI&gt;Select your device and click OK&lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;
&lt;LI&gt;Enable diagnostic logging
&lt;UL&gt;
&lt;LI&gt;In the left hand pane, expand the device&lt;/LI&gt;
&lt;LI&gt;Expand HKEY_LOCAL_MACHINE&lt;/LI&gt;
&lt;LI&gt;Expand SOFTWARE&lt;/LI&gt;
&lt;LI&gt;Expand Microsoft&lt;/LI&gt;
&lt;LI&gt;Expand .NETCompactFramework&lt;/LI&gt;
&lt;LI&gt;Expand Diagnostics&lt;BR&gt;If this key does not exist, you will need to create it 
&lt;UL&gt;
&lt;LI&gt;Right click on .NETCompactFramework&lt;/LI&gt;
&lt;LI&gt;Select New &amp;gt; Key Type "Diagnostics" (without quotes)&lt;/LI&gt;
&lt;LI&gt;Click OK&lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;
&lt;LI&gt;Expand Logging&lt;BR&gt;If this key does not exist, you will need to create it 
&lt;UL&gt;
&lt;LI&gt;Right click on Diagnostics&lt;/LI&gt;
&lt;LI&gt;Select New &amp;gt; Key&lt;/LI&gt;
&lt;LI&gt;Type "Logging" (without quotes)&lt;/LI&gt;
&lt;LI&gt;Click OK&lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;
&lt;LI&gt;Set the value of Enabled to 1 &lt;BR&gt;If this value does not exist, you will need to create it
&lt;UL&gt;
&lt;LI&gt;Right click on Logging&lt;/LI&gt;
&lt;LI&gt;Select New &amp;gt; DWORD Value&lt;/LI&gt;
&lt;LI&gt;Set the Name to "Enabled" (without quotes)&lt;/LI&gt;
&lt;LI&gt;Set the value to 1&lt;/LI&gt;
&lt;LI&gt;Click OK &lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;
&lt;LI&gt;Enable error logging 
&lt;UL&gt;
&lt;LI&gt;In the Logging key (from step 3) expand Error&lt;BR&gt;If this key does not exist, you will need to create it 
&lt;UL&gt;
&lt;LI&gt;Right click on Logging&lt;/LI&gt;
&lt;LI&gt;Select New &amp;gt; Key&lt;/LI&gt;
&lt;LI&gt;Type "Error" (without quotes)&lt;/LI&gt;
&lt;LI&gt;Click OK&lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;
&lt;LI&gt;Set the value of Enabled to 1 &lt;BR&gt;If this value does not exist, you will need to create it 
&lt;UL&gt;
&lt;LI&gt;Right click on Error&lt;/LI&gt;
&lt;LI&gt;Select New &amp;gt; DWORD Value&lt;/LI&gt;
&lt;LI&gt;Set the Name to "Enabled" (without quotes) &lt;/LI&gt;
&lt;LI&gt;Set the value to 1 &lt;/LI&gt;
&lt;LI&gt;Click OK&lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;To disable the Error Log, follow the above steps and set the value of Enabled to 0. To disable all logging, follow only steps 1-3, and set the value of Enabled to 0. &lt;/P&gt;
&lt;TABLE borderColor=#800080 cellSpacing=0 width="50%" border=1&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD&gt;&lt;B&gt;TIP&lt;/B&gt;: Set the value of UseApp (under Logging) to 1 to enable application specific log files.&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;P&gt;&lt;BR&gt;&lt;B&gt;Using the Error Log&lt;/B&gt;&lt;BR&gt;To demonstrate the error log, I created a very simple application that encounters an unhandled exception.&amp;nbsp; After the application exits (is terminated by clicking the Quit button), the error log file will be created.&lt;/P&gt;
&lt;TABLE borderColor=#800080 cellSpacing=0 width="50%" border=1&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD&gt;&lt;B&gt;NOTE&lt;/B&gt;: On headless devices, error dialogs are dismissed automatically using the default button.&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;P&gt;After opening the log file, we can see the unhandled exception.&lt;BR&gt;&lt;BR&gt;&lt;CODE&gt;Caption: UnhandledException.exe&lt;BR&gt;Title : Error&lt;BR&gt;Text : An unexpected error has occurred in UnhandledException.exe.&lt;BR&gt;Select Quit and then restart this program, or select Details for more information.&lt;BR&gt;&lt;BR&gt;Cannot perform requested task at this time&lt;BR&gt;Details: (null)&lt;/CODE&gt;&lt;BR&gt;&lt;BR&gt;On devices with display capabilities, clicking the Details button will result in the following additional data being present in the error log file.&lt;BR&gt;&lt;BR&gt;&lt;CODE&gt;Caption: UnhandledException.exe&lt;BR&gt;Title : Error&lt;BR&gt;Text : UnhandledException.exe&lt;BR&gt;ApplicationException&lt;BR&gt;Cannot perform requested task at this time&lt;BR&gt;&lt;BR&gt;at UnhandledException.Program.PerformTask()&lt;BR&gt;at UnhandledException.Program.Main()&lt;BR&gt;&lt;BR&gt;Details: (null)&lt;/CODE&gt;&lt;BR&gt;&lt;BR&gt;As we can see, the new error log feature allows unexpected errors can now be captured in the field, without requiring users to copy large amounts of data manually from the device.&amp;nbsp; &lt;BR&gt;&lt;BR&gt;Enjoy!&lt;BR&gt;-- DK&lt;BR&gt;&lt;BR&gt;&lt;FONT size=1&gt;Disclaimer(s): This posting is provided "AS IS" with no warranties, and confers no rights.&lt;/FONT&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=704662" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/davidklinems/archive/tags/Debugging/default.aspx">Debugging</category><category domain="http://blogs.msdn.com/davidklinems/archive/tags/Tips+and+Tricks/default.aspx">Tips and Tricks</category><category domain="http://blogs.msdn.com/davidklinems/archive/tags/Diagnostics/default.aspx">Diagnostics</category></item><item><title>Command Line Debugging Revisited - Part 3: Process Control</title><link>http://blogs.msdn.com/davidklinems/archive/2006/08/11/695975.aspx</link><pubDate>Sat, 12 Aug 2006 01:19:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:695975</guid><dc:creator>DavidKlineMS</dc:creator><slash:comments>4</slash:comments><comments>http://blogs.msdn.com/davidklinems/comments/695975.aspx</comments><wfw:commentRss>http://blogs.msdn.com/davidklinems/commentrss.aspx?PostID=695975</wfw:commentRss><description>In the previous parts of this series, I talked about &lt;A href="http://blogs.msdn.com/davidklinems/archive/2006/07/13/665023.aspx"&gt;getting started with MDbg&lt;/A&gt; and &lt;A href="http://blogs.msdn.com/davidklinems/archive/2006/07/14/666050.aspx"&gt;using the Device Emulator&lt;/A&gt;.&amp;nbsp; Today, I would like to talk about how to use MDbg to control processes on the device being debugged.&lt;BR&gt;&lt;BR&gt;&lt;B&gt;Commands&lt;/B&gt;&lt;BR&gt;cp[roc]&lt;BR&gt;kp[roc]&lt;BR&gt;pro[cessenum]&lt;BR&gt;&lt;BR&gt;&lt;B&gt;The cp[roc] command - Running a process without attaching the debugger&lt;/B&gt;&lt;BR&gt;In my &lt;A href="http://blogs.msdn.com/davidklinems/archive/2006/07/13/665023.aspx"&gt;getting started&lt;/A&gt; post, I talked about how to connect to the NetCFLaunch application and start an application for debugging.&amp;nbsp; While I typically want to debug the process that I launch, there are instances where I wish to start a process without debugging.&amp;nbsp; To do so, I use the &lt;CODE&gt;cp[roc]&lt;/CODE&gt; command as shown in the example below.&lt;BR&gt;&lt;BR&gt;&lt;CODE&gt;mdbg&amp;gt; cp "\program files\webcrawler.exe"&lt;/CODE&gt;&lt;BR&gt;&lt;BR&gt;If the command is able to start the process, the mdbg&amp;gt; prompt will be displayed.&amp;nbsp; If it is unable to start the process (ex: the application could not be found) an error message will be displayed.&lt;BR&gt;&lt;BR&gt;&lt;B&gt;The pro[cessenum] command - Listing the processes running on the device&lt;/B&gt;&lt;BR&gt;It is often interesting to know exactly what processes are running on your device.&amp;nbsp; Perhaps your application relies upon another process for some data or to perform a particular task.&amp;nbsp; Using the &lt;CODE&gt;pro[cessenum]&lt;/CODE&gt; command allows you to verify whether or not the partner process is running.&amp;nbsp; The example, below, shows the processes running on my Windows Mobile 5.0 Pocket PC device.&lt;BR&gt;&lt;BR&gt;&lt;CODE&gt;mdbg&amp;gt; pro&lt;BR&gt;Active processes on current machine:&lt;BR&gt;(PID: 0x0dcb4002) NK.EXE&lt;BR&gt;(PID: 0xedca5752) filesys.exe&lt;BR&gt;(PID: 0x8dadc526) device.exe&lt;BR&gt;(PID: 0xcd7f62ea) shell32.exe&lt;BR&gt;(PID: 0xcd97c7a6) gwes.exe&lt;BR&gt;(PID: 0xcd7f6732) services.exe&lt;BR&gt;(PID: 0x2d4b6da6) CommLoader.exe&lt;BR&gt;(PID: 0xcd517ac2) BatteryIndicator.exe&lt;BR&gt;(PID: 0x2d5219ea) connmgr.exe&lt;BR&gt;(PID: 0xad517b8a) srvtrust.exe&lt;BR&gt;(PID: 0xed810392) repllog.exe&lt;BR&gt;(PID: 0x2d4b6c76) poutlook.exe&lt;BR&gt;(PID: 0xed3affce) cprog.exe&lt;BR&gt;(PID: 0x2d99977a) rapiclnt&lt;BR&gt;(PID: 0xeced62b2) webcrawler.exe&lt;BR&gt;(PID: 0x2d0ed5be) tmail.exe&lt;BR&gt;(PID: 0x8d30f68a) netcflaunch.exe&lt;BR&gt;&lt;/CODE&gt;&lt;BR&gt;In looking at the process list, we can see that my earlier call to the &lt;CODE&gt;cp[roc]&lt;/CODE&gt; command successfully loaded webcrawler.exe.&lt;BR&gt;&lt;BR&gt;&lt;B&gt;The kp[roc] command - Terminating a running process&lt;/B&gt;&lt;BR&gt;There are a number of situations where being able to terminate a running process can be desirable.&amp;nbsp; I find this most useful when I wish to explore failure code paths when my applications leverage another process.&amp;nbsp; The following example shows using the &lt;CODE&gt;kp[roc]&lt;/CODE&gt; command to terminate the webcrawler.exe process that I started with the &lt;CODE&gt;cp[roc]&lt;/CODE&gt; command..&lt;BR&gt;&lt;BR&gt;&lt;CODE&gt;mdbg&amp;gt; kp 0xeced62b2&lt;/CODE&gt;&lt;BR&gt;&lt;BR&gt;The value passed to the &lt;CODE&gt;kp[roc]&lt;/CODE&gt; command is the process identifier (PID) listed by the &lt;CODE&gt;pro[cessenum]&lt;/CODE&gt; command.&lt;BR&gt;&lt;BR&gt;&lt;CODE&gt;(PID: 0xeced62b2) webcrawler.exe&lt;/CODE&gt;&lt;BR&gt;&amp;nbsp; 
&lt;P&gt;&lt;/P&gt;
&lt;TABLE cellSpacing=0 borderColorDark=#800080 cellPadding=2 width="50%" borderColorLight=#800080 border=1&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD&gt;&lt;I&gt;&lt;B&gt;Note&lt;/B&gt;&lt;/I&gt;: Please take care when terminating a process on your device.&amp;nbsp; Forcibly exiting the wrong application can lead to instability or an unresponsive device.&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;TABLE cellSpacing=0 borderColorDark=#800080 cellPadding=2 width="50%" borderColorLight=#800080 border=1&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD&gt;&lt;I&gt;&lt;B&gt;Tip&lt;/B&gt;&lt;/I&gt;: Use QuickEdit Mode or the Mark and Paste features of the Command Prompt to enable cut and paste within MDbg.&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;P&gt;&lt;BR&gt;Enjoy!&lt;BR&gt;-- DK&lt;BR&gt;&lt;BR&gt;&lt;FONT size=1&gt;[Edit: fix formatting]&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=1&gt;Disclaimer(s): This posting is provided "AS IS" with no warranties, and confers no rights.&lt;/FONT&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=695975" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/davidklinems/archive/tags/Debugging/default.aspx">Debugging</category></item><item><title>Command Line Debugging Revisited - Part 2: The Device Emulator</title><link>http://blogs.msdn.com/davidklinems/archive/2006/07/14/666050.aspx</link><pubDate>Fri, 14 Jul 2006 23:09:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:666050</guid><dc:creator>DavidKlineMS</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/davidklinems/comments/666050.aspx</comments><wfw:commentRss>http://blogs.msdn.com/davidklinems/commentrss.aspx?PostID=666050</wfw:commentRss><description>The Visual Studio 2005 Device Emulator is a very cool tool for developing, testing and debugging Windows Mobile applications.&amp;nbsp; You can design for and run on the wide variety of Windows Mobile devices.&amp;nbsp; In addition, you can install and use the &lt;A href="http://msdn.microsoft.com/mobility/downloads/Emulator/default.aspx"&gt;localized images&lt;/A&gt;, to run your applications on international versions of the Windows Mobile operating system.&lt;BR&gt;&lt;BR&gt;By default, the Device Emulator uses DMA as it's transport for device to desktop communications.&amp;nbsp; The MDbg command line debugger supports TCP/IP for device to desktop communications.&amp;nbsp; To allow MDbg to be used with the Device Emulator, there are some additional steps that are required before a connection can be established.&lt;BR&gt;&lt;BR&gt;&lt;A href="http://blogs.msdn.com/akhune"&gt;Abhi Khune&lt;/A&gt; has an excellent post on &lt;A href="http://blogs.msdn.com/akhune/archive/2005/11/16/493329.aspx"&gt;establishing a connection to the Internet using the Device Emulator&lt;/A&gt;.&amp;nbsp; In that post, there is a paragraph talking about the DMA and TCP/IP transports where it is noted that changing the Device Emulator transport from DMA to TCP/IP is &lt;B&gt;not recommended&lt;/B&gt;.&amp;nbsp; I fully agree with the recommendation with one notable exception: it is the only means to connect MDbg to the device emulator using the .NET Compact Framework version 2 service pack 1 debugger extension (mdbgnetcf).&lt;BR&gt;&lt;BR&gt;Note: After changing the Device Emulator's transport, you will need to reset the device.&lt;BR&gt;&lt;BR&gt;&lt;B&gt;Recommendation:&lt;/B&gt; I highly recommend switching the Device Emulator transport back to DMA once you are finished debugging with MDbg.&lt;BR&gt;&lt;BR&gt;Once the Device Emulator is configured for the TCP/IP transport, there are two options for connectivity. 
&lt;P&gt;&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;ActiveSync&lt;BR&gt;For me, the easiest way to establish a TCP/IP connection using the Device Emulator is to use Visual Studio 2005's Device Emulator Manager and ActiveSync to "cradle" the device.&lt;BR&gt;&lt;BR&gt;Abhi's post provides a walk-through on using the Device Emulator Manager, with many screen shots.&lt;BR&gt;&amp;nbsp; 
&lt;LI&gt;Virtual Machine Network Driver&lt;BR&gt;Another alternative is installing the Virtual Machine Network Driver.&amp;nbsp; You can download and read installation instructions in the &lt;A href="http://www.microsoft.com/downloads/details.aspx?FamilyID=dc8332d6-565f-4a57-be8c-1d4718d3af65&amp;amp;displaylang=en"&gt;Microsoft Download Center&lt;/A&gt;.&lt;BR&gt;&lt;BR&gt;When using the Virtual Machine Network Driver, there is no need to cradle the Device Emulator using ActiveSync and the Device Emulator Manager.&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;Please note you will need to perform Abhi's steps once per Device Emulator image (ex: Windows Mobile 5.0 Pocket PC) you wish to use with MDbg.&lt;BR&gt;&lt;BR&gt;With the above steps completed, you can connect and debug with MDbg as described in &lt;A href="http://blogs.msdn.com/davidklinems/archive/2006/07/13/665023.aspx"&gt;part 1&lt;/A&gt;.&lt;BR&gt;&lt;BR&gt;Enjoy!&lt;BR&gt;-- DK&lt;BR&gt;&lt;BR&gt;&lt;FONT size=1&gt;[Edit: fix spelling error]&lt;BR&gt;&lt;BR&gt;Disclaimer(s): This posting is provided "AS IS" with no warranties, and confers no rights.&lt;/FONT&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=666050" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/davidklinems/archive/tags/Debugging/default.aspx">Debugging</category></item><item><title>Command Line Debugging Revisited - Part 1: Getting started with MDbg and .NET Compact Framework Version 2 Service Pack 1</title><link>http://blogs.msdn.com/davidklinems/archive/2006/07/13/665023.aspx</link><pubDate>Fri, 14 Jul 2006 01:44:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:665023</guid><dc:creator>DavidKlineMS</dc:creator><slash:comments>16</slash:comments><comments>http://blogs.msdn.com/davidklinems/comments/665023.aspx</comments><wfw:commentRss>http://blogs.msdn.com/davidklinems/commentrss.aspx?PostID=665023</wfw:commentRss><description>It's been a while since I last wrote about using the command line debugger (cordbg) with the .NET Compact Framework.&amp;nbsp; Quite a bit has changed in the world of .NET Compact Framework command line debugging since that time.&lt;BR&gt;&lt;BR&gt;With the release, last year, of version 2 of the .NET Framework SDK, a new command line debugger (MDbg) became available.&amp;nbsp; MDbg is written in managed code and supports adding functionality via extension assemblies (DLLs).&amp;nbsp; At the time we released version 2, the extension which adds .NET Compact Framework support was not ready.&amp;nbsp; With the release of .NET Compact Framework version 2 service pack 1, our extension assembly (&lt;CODE&gt;mdbgnetcf.dll&lt;/CODE&gt;) is now available.&lt;BR&gt;&lt;BR&gt;If you followed my original command line debugger series, you may recall that there were several steps to getting a command line debugging session established with a .NET Compact Framework application in version 1.&amp;nbsp; I'm happy to say that we have made the process of getting started quite a bit easier with our MDbg extension.&amp;nbsp; I'm going to spend today's post talking about the &lt;CODE&gt;device&lt;/CODE&gt; and &lt;CODE&gt;run&lt;/CODE&gt; commands that are added by the mdbgnetcf extension.&lt;BR&gt;&lt;BR&gt;&lt;B&gt;Preliminary steps&lt;BR&gt;&lt;/B&gt;Before we can get started using MDbg to debug a .NET Compact Framework application, there are a few preliminary tasks we must perform. 
&lt;P&gt;&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Download and install .NET Compact Framework version 2 service pack 1&lt;/LI&gt;
&lt;LI&gt;Update your device to the service pack 1 release&lt;/LI&gt;
&lt;LI&gt;Copy the following files to the &lt;CODE&gt;\Windows&lt;/CODE&gt; folder on the device 
&lt;UL&gt;
&lt;LI&gt;from &lt;CODE&gt;&amp;lt;drive&amp;gt;:\Program Files\Common Files\Microsoft Shared\CoreCon\1.0\Target\wce400\&amp;lt;cpu&amp;gt;&lt;/CODE&gt; 
&lt;UL&gt;
&lt;LI&gt;&lt;CODE&gt;edbgtl.dll&lt;/CODE&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;CODE&gt;tcpconnectiona.dll&lt;/CODE&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;
&lt;LI&gt;from the service pack 1 installation folder (typically &lt;CODE&gt;&amp;lt;drive&amp;gt;:\Program Files\Microsoft.NET\SDK\CompactFramework\v2.0\WindowsCE\&amp;lt;version&amp;gt;\&amp;lt;cpu&amp;gt;&lt;/CODE&gt; 
&lt;UL&gt;
&lt;LI&gt;&lt;CODE&gt;netcfrtl.dll&lt;/CODE&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;CODE&gt;netcflaunch.exe&lt;/CODE&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;
&lt;LI&gt;Deploy your application file(s) to the device.&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;Steps 2 &amp;amp; 3 typically need to be performed only once per device.&amp;nbsp; Step 1 once per development / debugging PC.&amp;nbsp; Step 4 needs to be performed whenever the application file(s) have changed.&lt;BR&gt;&lt;BR&gt;&lt;B&gt;Getting started&lt;BR&gt;&lt;/B&gt;Once the preliminary tasks have been performed, we can get started debugging our application using MDbg.&amp;nbsp; &lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Run &lt;CODE&gt;mdbg.exe&lt;/CODE&gt;&lt;BR&gt;I recommend running MDbg from either a Visual Studio 2005 Command Prompt (Start Menu\All Programs\Microsoft Visual Studio 2005\Visual Studio Tools) or a SDK Command Prompt (Start Menu\All Programs\Microsoft .NET Framework SDK v2.0).&amp;nbsp; This will ensure that MDbg.exe is on the search path.&lt;BR&gt;&lt;BR&gt;I also recommend running MDbg from within the folder containing both your target executable and the symbol (.pdb) file.&amp;nbsp; This allows MDbg to match the symbols to the exe and display the correct source code without any additional steps.&lt;BR&gt;&amp;nbsp;&lt;/LI&gt;
&lt;LI&gt;Load the mdbgnetcf extension&lt;BR&gt;&lt;BR&gt;&lt;CODE&gt;mdbg&amp;gt;load &amp;lt;path&amp;gt;\mdbgnetcf&lt;/CODE&gt;&lt;BR&gt;&lt;BR&gt;It is important to note that the file extension (.dll) is left off when using the load command.&lt;BR&gt;&lt;BR&gt;When the extension is loaded, the following message will be displayed.&lt;BR&gt;&lt;BR&gt;&lt;CODE&gt;.NET Compact Framework extension loaded successfully.&lt;/CODE&gt;&lt;BR&gt;&amp;nbsp;&lt;/LI&gt;
&lt;LI&gt;On your device, run &lt;CODE&gt;NetCFLaunch.exe&lt;/CODE&gt;&lt;BR&gt;&lt;BR&gt;When NetCFLaunch starts, it will display the transport parameters (ex: 169.254.2.1 6510) required to connect to the device.&amp;nbsp; We will use the transport parameters in the next step.&lt;BR&gt;&amp;nbsp;&lt;/LI&gt;
&lt;LI&gt;Connect to the device using the device command&lt;BR&gt;&lt;BR&gt;&lt;CODE&gt;device 169.254.2.1 6510&lt;/CODE&gt;&lt;BR&gt;&lt;BR&gt;When the device command successfully completes, we will have a connection to the NetCFLaunch application.&amp;nbsp; The NetCFLaunch window will display "&lt;CODE&gt;Connection SUCCEEDED&lt;/CODE&gt;".&lt;BR&gt;&amp;nbsp;&lt;/LI&gt;
&lt;LI&gt;Run your application using the run command&lt;BR&gt;&lt;BR&gt;I will use the WebCrawler sample from Visual Studio 2005.&lt;BR&gt;&lt;BR&gt;&lt;CODE&gt;run "\program files\webcrawler.exe"&lt;/CODE&gt;&lt;BR&gt;&lt;BR&gt;When the run command completes, MDbg will display the current source location (the application entry point).&lt;BR&gt;&lt;BR&gt;&lt;CODE&gt;STOP: Breakpoint Hit&lt;BR&gt;288: {&lt;BR&gt;[p#:0, t#:0] mdbg&amp;gt;&lt;/CODE&gt;&lt;BR&gt;&lt;BR&gt;Note: The breakpoint to which MDbg refers is the initial, temporary breakpoint managed by the debugger.&amp;nbsp; This breakpoint is inserted and cleared when MDbg connects to the application.&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;You can now debug your application using the other MDbg commands.&amp;nbsp; For a list of available commands, use the h[elp] or ? commands.&lt;BR&gt;&lt;BR&gt;In the coming weeks, I plan on continuing this series and talking about the other commands added by the mdbgnetcf extension and show some examples of how they can be used.&lt;BR&gt;&lt;BR&gt;Enjoy!&lt;BR&gt;-- DK&lt;BR&gt;&lt;BR&gt;&lt;FONT size=1&gt;Disclaimer(s): This posting is provided "AS IS" with no warranties, and confers no rights.&lt;/FONT&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=665023" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/davidklinems/archive/tags/Debugging/default.aspx">Debugging</category><category domain="http://blogs.msdn.com/davidklinems/archive/tags/Tips+and+Tricks/default.aspx">Tips and Tricks</category></item><item><title>MEDC 2006 Update: What went wrong in the debugging demo during APP326?</title><link>http://blogs.msdn.com/davidklinems/archive/2006/06/16/634503.aspx</link><pubDate>Fri, 16 Jun 2006 23:17:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:634503</guid><dc:creator>DavidKlineMS</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/davidklinems/comments/634503.aspx</comments><wfw:commentRss>http://blogs.msdn.com/davidklinems/commentrss.aspx?PostID=634503</wfw:commentRss><description>Ever since I finished my MEDC 2006 presentation (APP326 - Essential Tips and Tricks for .NET Compact Framework Application Developers), I have been bothered by the fact that one of my demos did not work 100% as I had designed and practiced.&amp;nbsp; During the demo of debugging a P/Invoke call (based on &lt;A href="http://blogs.msdn.com/davidklinems/archive/2005/06/02/424595.aspx"&gt;this post&lt;/A&gt;),&amp;nbsp; I was unable to re-attach to the managed application.&amp;nbsp; This demo worked correctly at MEDC 2005, so why didn't it work this year?&lt;BR&gt;&lt;BR&gt;After thinking about this for awhile, I realized that there was one major difference between 2005 and 2006...&amp;nbsp; This year, I decided to show setting the AttachEnabled registry key as part of the presentation.&amp;nbsp; Last year, I had pre-configured the device to &lt;A href="http://blogs.msdn.com/davidklinems/archive/2005/05/24/421566.aspx"&gt;support attach to process&lt;/A&gt;.&amp;nbsp; This is was the cause of my problem.&amp;nbsp; &lt;BR&gt;&lt;BR&gt;While practicing my session, I had used the demo system (my laptop) to walk through each and every demo until I knew them backwards, forwards and inside-out.&amp;nbsp; I was very careful to always leave the device and emulator images in a known state (the beta of .NET Compact Framework v2 sp1 installed, the shared folder configured, etc) so that I would not run into any problems or deployment related delays.&amp;nbsp; My practices went flawlessly and the time came to do them "for real".&lt;BR&gt;&lt;BR&gt;Those who attended the session may recall that there were actually two things that did not go smoothly for this particular demo.&amp;nbsp; First, while I was careful to leave the device and emulators in a known state, I forgot to make sure that I had reset the source code before starting the debugging demo and left the Debug.Assert statements that the demo required commented and, therefore, they did not execute.&lt;BR&gt;&lt;BR&gt;The second (actually it was the first mistake that I made) was misspelling "AttachEnabled" when editing the device's registry.&amp;nbsp; &lt;A href="http://blogs.msdn.com/ryanms"&gt;Ryan Chapman&lt;/A&gt; later pointed out that he remembered seeing me type "AttachEnable" (missing the &lt;B&gt;d&lt;/B&gt;).&amp;nbsp; After he mentioned that, all I could think was "oh no, how could I have made that mistake".&amp;nbsp; I will confirm this once I receive and watch the session recording, but I think Ryan is correct.&amp;nbsp; Fortunately, the slides have the correct registry data listed.&lt;BR&gt;&lt;BR&gt;To make a long story short, when you watch the session recording, please be aware of this error and use the registry key (AttachEnable&lt;B&gt;d&lt;/B&gt;) that is shown in my slides and &lt;A href="http://blogs.msdn.com/davidklinems/archive/2005/05/24/421566.aspx"&gt;here&lt;/A&gt;.&amp;nbsp; Sorry for the confusion that this may have caused at the show.&lt;BR&gt;&lt;BR&gt;Take care,&lt;BR&gt;-- DK&lt;BR&gt;&lt;BR&gt;&lt;FONT size=1&gt;Disclaimer(s):&lt;BR&gt;This posting is provided "AS IS" with no warranties, and confers no rights. &lt;BR&gt;Some of the information contained within this post may be in relation to beta software. Any and all details are subject to change. &lt;BR&gt;&amp;nbsp;&lt;/FONT&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=634503" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/davidklinems/archive/tags/Debugging/default.aspx">Debugging</category><category domain="http://blogs.msdn.com/davidklinems/archive/tags/Events/default.aspx">Events</category></item><item><title>The Importance of Debugger Symbols: or Reloading Symbols while Debugging</title><link>http://blogs.msdn.com/davidklinems/archive/2006/03/15/552347.aspx</link><pubDate>Thu, 16 Mar 2006 02:01:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:552347</guid><dc:creator>DavidKlineMS</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/davidklinems/comments/552347.aspx</comments><wfw:commentRss>http://blogs.msdn.com/davidklinems/commentrss.aspx?PostID=552347</wfw:commentRss><description>Have you ever &lt;A HREF="/davidklinems/archive/2005/05/26/422338.aspx"&gt;attached to a managed application&lt;/A&gt; and been greeted with the following message ...&lt;BR&gt;&lt;BR&gt;&lt;CODE&gt;No symbols are loaded for any call stack frame.&amp;nbsp; The source code cannot be displayed.&lt;/CODE&gt;&lt;BR&gt;&lt;BR&gt;... and found that breakpoints could not be set, or that single step attempts cause the application to run to completion)?&lt;BR&gt;&lt;BR&gt;While preparing one of the demos for my MEDC 2006 presentation, I found myself in this state and was reminded of the importance of making sure the correct debugger symbols can be found by the Visual Studio 2005 debugger.&lt;BR&gt;&lt;BR&gt;Often when attaching a debugger to a running application, you are not using the system on which the application was originally compiled, or the source code may have been moved since the application was built.&amp;nbsp; In these cases, the Visual Studio 2005 debugger is unable to resolve the location of the debugging symbols automatically.&amp;nbsp; To be able to successfully debug your application, you will need to instruct Visual Studio 2005 as to where to find the application's symbols (.pdb file) and to attempt to reload them.&lt;BR&gt;&lt;BR&gt;To load symbols after you have attached to an application:
&lt;P&gt;&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;On the &lt;STRONG&gt;Debug&lt;/STRONG&gt; menu, select &lt;STRONG&gt;Windows&lt;/STRONG&gt; and then &lt;STRONG&gt;Modules&lt;/STRONG&gt;&lt;BR&gt;This will open the Modules window and show the binaries loaded as part of your application, including the .NET Compact Framework runtime.&lt;/LI&gt;
&lt;LI&gt;Right click anywhere within the &lt;STRONG&gt;Modules&lt;/STRONG&gt; window and select &lt;STRONG&gt;Symbol Settings&lt;/STRONG&gt;&lt;/LI&gt;
&lt;LI&gt;In the &lt;STRONG&gt;Options&lt;/STRONG&gt; dialog, click on the folder icon (to the upper right)&lt;/LI&gt;
&lt;LI&gt;Type the location to the application's .pdb file (ex: &lt;CODE&gt;c:\projects\TestApplication\bin\debug&lt;/CODE&gt;) and click &lt;STRONG&gt;OK&lt;/STRONG&gt;&lt;BR&gt;If you have the &lt;B&gt;Load symbols using the updated settings when this dialog is closed &lt;/B&gt;option selected (it is selected by default), the Visual Studio debugger will attempt to reload the symbols for all loaded modules.&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;With the correct symbols loaded, you will be able to set breakpoints and step through your code as if you had built and deployed the application from the current system.&lt;BR&gt;&lt;BR&gt;Take care,&lt;BR&gt;-- DK&lt;BR&gt;&lt;BR&gt;&lt;FONT size=1&gt;Disclaimer(s):&lt;BR&gt;This posting is provided "AS IS" with no warranties, and confers no rights.&lt;/FONT&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=552347" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/davidklinems/archive/tags/Debugging/default.aspx">Debugging</category><category domain="http://blogs.msdn.com/davidklinems/archive/tags/Tips+and+Tricks/default.aspx">Tips and Tricks</category></item><item><title>Using the Interop Log to Diagnose P/Invoke Call Issues</title><link>http://blogs.msdn.com/davidklinems/archive/2006/02/03/524471.aspx</link><pubDate>Sat, 04 Feb 2006 01:33:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:524471</guid><dc:creator>DavidKlineMS</dc:creator><slash:comments>6</slash:comments><comments>http://blogs.msdn.com/davidklinems/comments/524471.aspx</comments><wfw:commentRss>http://blogs.msdn.com/davidklinems/commentrss.aspx?PostID=524471</wfw:commentRss><description>&lt;P dir=ltr style="MARGIN-RIGHT: 0px"&gt;Sometimes, determining why an unmanaged function call (P/Invoke) has failed can be challenging.&amp;nbsp; Fortunately, version 2 of the .NET Compact Framework has a new diagnostic log for this data -- the Interop Log.&amp;nbsp; In June 2005, &lt;A href="http://blogs.msdn.com/stevenpr"&gt;Steven Pratschner&lt;/A&gt; wrote a great post detailing the Inteop Log and it's contents: &lt;A href="http://blogs.msdn.com/stevenpr/archive/2005/06/22/431612.aspx"&gt;Diagnosing Marshalling Errors using Interop Logging&lt;/A&gt;. &lt;BR&gt;&lt;BR&gt;I would like to take some time to explore a specific example where the Interop Log can save time and make P/Invoke call debugging quick and easy.&lt;BR&gt;&lt;BR&gt;&lt;B&gt;Enabling the Interop Log&lt;BR&gt;&lt;/B&gt;The Interop Log is enabled via the device's registry. In my steps, below, I will be using the Remote Registry Editor that is included with Visual Studio 2005. &lt;/P&gt;
&lt;P dir=ltr style="MARGIN-RIGHT: 0px"&gt;&lt;/P&gt;
&lt;P dir=ltr style="MARGIN-RIGHT: 0px"&gt;&lt;B&gt;WARNING&lt;/B&gt;: Using Remote Registry Editor incorrectly can cause serious problems that may require you to hard reset your device. Microsoft cannot guarantee that problems resulting from the incorrect use of Remote Registry Editor can be solved. Use Remote Registry Editor at your own risk. &lt;/P&gt;
&lt;P dir=ltr style="MARGIN-RIGHT: 0px"&gt;
&lt;OL&gt;
&lt;LI&gt;Start the Remote Registry Editor 
&lt;UL&gt;
&lt;LI&gt;Open the Start Menu 
&lt;LI&gt;Select All Programs 
&lt;LI&gt;Select Microsoft Visual Studio 2005 
&lt;LI&gt;Select Visual Studio Remote Tools 
&lt;LI&gt;Select Remote Registry Editor &lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;Connect to your device 
&lt;UL&gt;
&lt;LI&gt;On the Target menu, select Connect 
&lt;LI&gt;Select your device and click OK &lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;Enable diagnostic logging 
&lt;UL&gt;
&lt;LI&gt;In the left hand pane, expand the device 
&lt;LI&gt;Expand HKEY_LOCAL_MACHINE 
&lt;LI&gt;Expand SOFTWARE 
&lt;LI&gt;Expand Microsoft 
&lt;LI&gt;Expand .NETCompactFramework 
&lt;LI&gt;Expand Diagnostics&lt;BR&gt;If this key does not exist, you will need to create it 
&lt;UL&gt;
&lt;LI&gt;Right click on .NETCompactFramework 
&lt;LI&gt;Select New &amp;gt; Key 
&lt;LI&gt;Type "Diagnostics" (without quotes) 
&lt;LI&gt;Click OK&lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;Expand Logging&lt;BR&gt;If this key does not exist, you will need to create it 
&lt;UL&gt;
&lt;LI&gt;Right click on Diagnostics 
&lt;LI&gt;Select New &amp;gt; Key 
&lt;LI&gt;Type "Logging" (without quotes) 
&lt;LI&gt;Click OK &lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;Set the value of Enabled to 1 &lt;BR&gt;If this value does not exist, you will need to create it 
&lt;UL&gt;
&lt;LI&gt;Right click on Logging 
&lt;LI&gt;Select New &amp;gt; DWORD Value 
&lt;LI&gt;Set the Name to "Enabled" (without quotes) 
&lt;LI&gt;Set the value to 1 
&lt;LI&gt;Click OK &lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;Enable interop logging 
&lt;UL&gt;
&lt;LI&gt;In the Logging key (from step 3) expand Interop&lt;BR&gt;If this key does not exist, you will need to create it 
&lt;UL&gt;
&lt;LI&gt;Right click on&amp;nbsp;Logging 
&lt;LI&gt;Select New &amp;gt; Key 
&lt;LI&gt;Type "Interop" (without quotes) 
&lt;LI&gt;Click OK&lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;Set the value of Enabled to 1&lt;BR&gt;If this value does not exist, you will need to create it 
&lt;UL&gt;
&lt;LI&gt;Right click on Interop 
&lt;LI&gt;Select New &amp;gt; DWORD Value 
&lt;LI&gt;Set the Name to "Enabled" (without quotes) 
&lt;LI&gt;Set the value to 1 
&lt;LI&gt;Click OK&lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;&lt;/OL&gt;&lt;/P&gt;
&lt;P&gt;To disable the Interop Log, follow the above steps and set the value of Enabled to 0.&lt;BR&gt;To disable all logging, follow only steps 1-3, and set the value of Enabled to 0. &lt;/P&gt;
&lt;P&gt;There are a few optional settings that can be set to configure how the Interop Log is created. For details, please refer to &lt;A href="http://blogs.msdn.com/stevenpr/archive/2005/06/22/431612.aspx"&gt;Steven's post&lt;/A&gt;. &lt;/P&gt;
&lt;P&gt;One optional setting I highly recommend is to create application specific log files. This causes the .NET Compact Framework to name the log file based on your application name. For example, if I enable logging with the UseApp option, the log file created for an application called DkTest.exe will be netcf_DkTest_interop.log. &lt;/P&gt;
&lt;P&gt;To enable application specific log files please make the following addition to the above steps. &lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Enable application specific log files &lt;/LI&gt;
&lt;UL&gt;
&lt;LI&gt;In the Logging key set the value of UseApp to 1&lt;BR&gt;If this value does not exist, you will need to create it&lt;/LI&gt;
&lt;UL&gt;
&lt;LI&gt;Right click on Logging 
&lt;LI&gt;Select New &amp;gt; DWORD Value 
&lt;LI&gt;Set the Name to "UseApp" (without quotes) 
&lt;LI&gt;Set the value to 1 &lt;/LI&gt;&lt;/UL&gt;
&lt;UL&gt;
&lt;LI&gt;Click OK&lt;/LI&gt;&lt;/UL&gt;&lt;/UL&gt;&lt;/OL&gt;
&lt;P&gt;&lt;B&gt;Diagnosing a P/Invoke call issue&lt;BR&gt;&lt;/B&gt;One of the things that I sometimes forget is that .NET types are not necessarily the same as Win32 types.&amp;nbsp; One type, in particular, where this is true is &lt;I&gt;&lt;B&gt;long&lt;/B&gt;&lt;/I&gt;.&amp;nbsp; On Win32, a long (or LONG) takes up 4 bytes (32 bits).&amp;nbsp; In the .NET world, a long is 8 bytes (64 bits) in size.&lt;BR&gt;&lt;BR&gt;Let's look at an example where this type size difference can cause application issues.&lt;BR&gt;&lt;BR&gt;First, a simple function written in C/C++&lt;BR&gt;&lt;CODE&gt;int SampleFunction(long lData)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // int == long on Win32 systems&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return lData;&lt;BR&gt;}&lt;BR&gt;&lt;BR&gt;&lt;/CODE&gt;To be able to call this function, our managed application must define the signature for the P/Invoke.&lt;BR&gt;&lt;CODE&gt;[DllImport("InteropLogExampleNative.dll", SetLastError=true)]&lt;BR&gt;public static extern int SampleFunction(long lData);&lt;BR&gt;&lt;/CODE&gt;&lt;BR&gt;Now we can call our function.&lt;BR&gt;&lt;CODE&gt;int result = SampleFunction(long.MaxValue);&lt;BR&gt;&lt;/CODE&gt;&lt;BR&gt;If you add the above code to a simple project and attempt to call the P/Invoke method, depending on the data passed to the function, you may encounter "calculation errors" related to the wrong data type being sent to the unmanaged function.&lt;BR&gt;&lt;BR&gt;If the Interop logging is enabled, we can see that the application tried to call the method with an 8 byte value when the method was expecting only 4 bytes.&amp;nbsp; &lt;BR&gt;&lt;BR&gt;&lt;CODE&gt;[pinvokeimpl][preservesig]&lt;BR&gt;int InteropLogPInvokeExample.Program::SampleFunction(long );&lt;BR&gt;int (I4_VAL) SampleFunction(INT64 (I8_VAL) );&lt;BR&gt;&lt;/CODE&gt;&lt;BR&gt;To quote &lt;A href="http://blogs.msdn.com/stevenpr/archive/2005/06/22/431612.aspx"&gt;Steven&lt;/A&gt;: "The Compact Framework does not have intrinsic knowledge of the native function you are calling – it simply takes the managed definition you’ve provided and creates an equivalent native signature. If this signature doesn’t match the actual signature of the targeted native function, a marshaling error will occur."&lt;BR&gt;&lt;BR&gt;By changing the P/Invoke signature to specify a 4 byte integer, the call succeeds.&lt;BR&gt;&lt;BR&gt;&lt;CODE&gt;// managed code&lt;BR&gt;// p/invoke method signature.&amp;nbsp; &lt;BR&gt;//&lt;BR&gt;// note: a Win32 long is the same size as a .NET int&lt;BR&gt;[DllImport("InteropLogExampleNative.dll", SetLastError=true)]&lt;BR&gt;public static extern int SampleFunction(int lData);&lt;/CODE&gt;&lt;BR&gt;&lt;BR&gt;These types of issues can sometimes be difficult to notice.&amp;nbsp; For example, in our simple unmanaged (native) function, we are simply returning the value passed as the argument.&amp;nbsp; If the value happens to be one that can fit within a 32 bit integer, the failure may go unnoticed.&amp;nbsp; If the value exceeds that which will fit in a 32 bit integer and the code does not validate the data returned from the call, the failure may also go unnoticed.&lt;BR&gt;&lt;BR&gt;The moral of this story is that it is very important to validate the behavior of all P/Invoke calls by examining the returned data or any other means appropriate.&amp;nbsp; I also highly recommend enabling Interop logging and examining the P/Invoke signature data in the log file as a standard part pre-checkin unit testing and release criteria if your application makes calls to unmanaged functions.&lt;BR&gt;&lt;BR&gt;Take care,&lt;BR&gt;-- DK&lt;BR&gt;&lt;BR&gt;&lt;FONT size=1&gt;Edit: Fix error in registry steps.&lt;BR&gt;Edit: Fix UseApp steps&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=1&gt;Disclaimer(s):&lt;BR&gt;This posting is provided "AS IS" with no warranties, and confers no rights.&lt;/FONT&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=524471" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/davidklinems/archive/tags/Debugging/default.aspx">Debugging</category><category domain="http://blogs.msdn.com/davidklinems/archive/tags/Tips+and+Tricks/default.aspx">Tips and Tricks</category><category domain="http://blogs.msdn.com/davidklinems/archive/tags/Diagnostics/default.aspx">Diagnostics</category></item><item><title>Diagnosing MissingMethodExceptions and TypeLoadExceptions using the Loader Log</title><link>http://blogs.msdn.com/davidklinems/archive/2006/01/31/520899.aspx</link><pubDate>Tue, 31 Jan 2006 21:59:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:520899</guid><dc:creator>DavidKlineMS</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/davidklinems/comments/520899.aspx</comments><wfw:commentRss>http://blogs.msdn.com/davidklinems/commentrss.aspx?PostID=520899</wfw:commentRss><description>Have you ever encountered a MissingMethodException or TypeLoadException when starting a .NET Compact Framework application?&amp;nbsp; If you are running version 2 of the .NET Compact Framework, the Loader Log can help identify the source of the exception.&lt;BR&gt;&lt;BR&gt;For detailed information regarding the Loader Log, please read &lt;A href="http://blogs.msdn.com/stevenpr"&gt;Steven Pratschner&lt;/A&gt;'s excellent &lt;A href="http://blogs.msdn.com/stevenpr/archive/2005/02/28/381744.aspx"&gt;Better Diagnostics in Whidbey: Loader Logging&lt;/A&gt; post.&lt;BR&gt;&lt;BR&gt;&lt;B&gt;Enabling the Loader Log&lt;/B&gt;&lt;BR&gt;The Loader Log is enabled via the device's registry.&amp;nbsp; In my steps, below, I will be using the Remote Registry Editor that is included with Visual Studio 2005. 
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;B&gt;WARNING&lt;/B&gt;: Using Remote Registry Editor incorrectly can cause serious problems that may require you to hard reset your device. Microsoft cannot guarantee that problems resulting from the incorrect use of Remote Registry Editor can be solved. Use Remote Registry Editor at your own risk. &lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Start the Remote Registry Editor 
&lt;UL&gt;
&lt;LI&gt;Open the Start Menu 
&lt;LI&gt;Select All Programs 
&lt;LI&gt;Select Microsoft Visual Studio 2005 
&lt;LI&gt;Select Visual Studio Remote Tools 
&lt;LI&gt;Select Remote Registry Editor &lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;Connect to your device 
&lt;UL&gt;
&lt;LI&gt;On the Target menu, select Connect 
&lt;LI&gt;Select your device and click OK &lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;Enable diagnostic logging 
&lt;UL&gt;
&lt;LI&gt;In the left hand pane, expand the device 
&lt;LI&gt;Expand HKEY_LOCAL_MACHINE 
&lt;LI&gt;Expand SOFTWARE 
&lt;LI&gt;Expand Microsoft 
&lt;LI&gt;Expand .NETCompactFramework 
&lt;LI&gt;Expand Diagnostics&lt;BR&gt;If this key does not exist, you will need to create it 
&lt;UL&gt;
&lt;LI&gt;Right click on .NETCompactFramework 
&lt;LI&gt;Select New &amp;gt; Key 
&lt;LI&gt;Type "Diagnostics" (without quotes) 
&lt;LI&gt;Click OK&lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;Expand Logging&lt;BR&gt;If this key does not exist, you will need to create it 
&lt;UL&gt;
&lt;LI&gt;Right click on Diagnostics 
&lt;LI&gt;Select New &amp;gt; Key 
&lt;LI&gt;Type "Logging" (without quotes) 
&lt;LI&gt;Click OK &lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;Set the value of Enabled to 1 &lt;BR&gt;If this value does not exist, you will need to create it 
&lt;UL&gt;
&lt;LI&gt;Right click on Logging 
&lt;LI&gt;Select New &amp;gt; DWORD Value 
&lt;LI&gt;Set the Name to "Enabled" (without quotes) 
&lt;LI&gt;Set the value to 1 
&lt;LI&gt;Click OK &lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;Enable loader logging 
&lt;UL&gt;
&lt;LI&gt;In the Logging key (from step 3) expand Loader&lt;BR&gt;If this key does not exist, you will need to create it 
&lt;UL&gt;
&lt;LI&gt;Right click on Logging 
&lt;LI&gt;Select New &amp;gt; Key 
&lt;LI&gt;Type "Loader" (without quotes) 
&lt;LI&gt;Click OK&lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;Set the value of Enabled to 1&lt;BR&gt;If this value does not exist, you will need to create it 
&lt;UL&gt;
&lt;LI&gt;Right click on Loader 
&lt;LI&gt;Select New &amp;gt; DWORD Value 
&lt;LI&gt;Set the Name to "Enabled" (without quotes) 
&lt;LI&gt;Set the value to 1 
&lt;LI&gt;Click OK&lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;To disable the Loader Log, follow the above steps and set the value of Enabled to 0.&lt;BR&gt;To disable &lt;B&gt;&lt;I&gt;all &lt;/I&gt;&lt;/B&gt;logging, follow only steps 1-3, and set the value of Enabled to 0.&lt;/P&gt;
&lt;P&gt;There are a few optional settings that can be set to configure how the Loader Log is created.&amp;nbsp; For details, please refer to &lt;A href="http://blogs.msdn.com/stevenpr/archive/2005/02/28/381744.aspx"&gt;Steven's post&lt;/A&gt;.&amp;nbsp; &lt;BR&gt;&lt;BR&gt;One optional setting I &lt;I&gt;&lt;B&gt;highly&lt;/B&gt;&lt;/I&gt; recommend is to create application specific log files.&amp;nbsp; This causes the .NET Compact Framework to name the log file based on your application name.&amp;nbsp; For example, if I enable logging with the UseApp option, the log file created for an application called &lt;CODE&gt;DkTest.exe&lt;/CODE&gt; will be &lt;CODE&gt;netcf_DkTest_loader.log&lt;/CODE&gt;.&lt;BR&gt;&lt;BR&gt;To enable application specific log files please make the following addition to the above steps.&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Enable application specific log files 
&lt;UL&gt;
&lt;LI&gt;In the Logging key et the value of UseApp to 1&lt;BR&gt;If this value does not exist, you will need to create it 
&lt;UL&gt;
&lt;LI&gt;Right click on Logging
&lt;LI&gt;Select New &amp;gt; DWORD Value 
&lt;LI&gt;Set the Name to "UseApp" (without quotes) 
&lt;LI&gt;Set the value to 1 
&lt;LI&gt;Click OK&lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;&lt;B&gt;Diagnosing the exception&lt;/B&gt;&lt;BR&gt;To illustrate how the Loader Log can help identify the cause of these exceptions, I created a custom control that was built to incorrectly reference the full .NET Framework version of the System.Windows.Forms assembly.&amp;nbsp; I then built a simple application that used this control.&amp;nbsp; After running the application, the Loader Log contained the following data.&lt;BR&gt;&lt;BR&gt;&lt;CODE&gt;MissingType. Class [myControl.CustomButton], Assembly [myControl, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null].&lt;BR&gt;&lt;/CODE&gt;&lt;BR&gt;Scrolling back up the log file, we find this entry.&lt;BR&gt;&lt;BR&gt;&lt;CODE&gt;Failed to load [System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=B77A5C561934E089]&lt;BR&gt;&lt;/CODE&gt;&lt;BR&gt;In examining this entry, we see that the &lt;CODE&gt;myControl.CustomButton&lt;/CODE&gt; assembly failed to load the &lt;CODE&gt;System.Windows.Forms&lt;/CODE&gt; assembly.&amp;nbsp; The reason was that the strong name of the &lt;CODE&gt;System.Windows.Forms&lt;/CODE&gt; assembly (Name, Version, Culture, PublicKeyToken) was not present on my device.&amp;nbsp; Take note of the value of PublicKeyToken.&amp;nbsp; By comparing the PublicKeyToken value of successfully loaded assemblies (ex: System.Xml), we find that, in this instance, they do not match.&lt;BR&gt;&lt;BR&gt;The PublicKeyToken specified in the strong name for the System.Windows.Forms assembly is that of the full .NET Framework.&amp;nbsp; &lt;BR&gt;&lt;BR&gt;To date (versions 1 and 2), the .NET Compact Framework uses the &lt;CODE&gt;969DB8053D3322AC&lt;/CODE&gt; as it's PublicKeyToken in system assembly strong names.&lt;BR&gt;&lt;BR&gt;Enjoy!&lt;BR&gt;-- DK&lt;BR&gt;&lt;BR&gt;&lt;FONT size=1&gt;Edit: Fix UseApp steps&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=1&gt;Disclaimer(s):&lt;BR&gt;This posting is provided "AS IS" with no warranties, and confers no rights.&lt;/FONT&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=520899" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/davidklinems/archive/tags/Debugging/default.aspx">Debugging</category><category domain="http://blogs.msdn.com/davidklinems/archive/tags/Tips+and+Tricks/default.aspx">Tips and Tricks</category><category domain="http://blogs.msdn.com/davidklinems/archive/tags/Diagnostics/default.aspx">Diagnostics</category></item><item><title>What is a Race Condition?</title><link>http://blogs.msdn.com/davidklinems/archive/2005/10/24/484275.aspx</link><pubDate>Mon, 24 Oct 2005 22:39:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:484275</guid><dc:creator>DavidKlineMS</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/davidklinems/comments/484275.aspx</comments><wfw:commentRss>http://blogs.msdn.com/davidklinems/commentrss.aspx?PostID=484275</wfw:commentRss><description>I've been posting a bit, lately, on debugging multi-threaded applications.&amp;nbsp; When talking about &lt;a href="http://blogs.msdn.com/davidklinems/archive/2005/09/15/467827.aspx"&gt;deadlocks&lt;/A&gt;, I mentioned that I was adding a Sleep statement to ensure that I hit the deadlock issue.&amp;nbsp; The reason that I needed to force the deadlock was that, depending on timing, the code could either work, or hang the application.&amp;nbsp; The example I was using was a classic "race condition".&amp;nbsp; If Thread 2 completed before Thread 1 started, there would appear to be no bug.&amp;nbsp; However, if Thread 1 entered the lock statement first, the application would hang.&lt;BR&gt;&lt;BR&gt;&lt;B&gt;What is a race condition?&lt;/B&gt;&lt;BR&gt;I mentioned earlier that the situation in my example was called a "race condition".&amp;nbsp; What exactly does that mean?&amp;nbsp; Multi-threaded applications are very similar to sporting events such as sprints, marathons and stock car races.&amp;nbsp; As with these more traditional races, for any given event, any entrant can win.&amp;nbsp; In a marathon, if an unexpected entrant wins, it's exciting.&amp;nbsp; In software, if an unexpected thread wins the race the results are typically unpleasant (application hangs, data corruption, etc) for users.&lt;BR&gt;&lt;BR&gt;It has been my experience that running multi-threaded applications on multiple processor machines tends to encounter race conditions more frequently.&amp;nbsp; On these systems multiple simultaneous application threads are not only possible, they are likely and in such an environment, race condition bugs have been, for me, much more likely to surface.&lt;BR&gt;&lt;BR&gt;&lt;B&gt;Debugging race conditions&lt;/B&gt;&lt;BR&gt;How do you debug a race condition?&amp;nbsp; This is a difficult question to answer.&amp;nbsp; Whenever you make any change to the system such as: running on a different system, instrumenting the binary with diagnostic logging or running under the debugger, the timing characteristics of your application can be changed.&amp;nbsp; This change in the application's timing can cause a different thread to win the race.&amp;nbsp; If we are lucky, this causes the bug to surface.&amp;nbsp; If we are not, this timing change can mask the problem.&lt;BR&gt;&lt;BR&gt;What has worked for me has been to instrument my code (in debug builds) and run the debug build of my application (or component) under the debugger at all times while writing the code.&amp;nbsp; Whenever possible, I also recommend running on a debug build of the target platform.&amp;nbsp; Using the debugger to step through your code and setting breakpoints on the methods where thread safety is a requirement, you may be able to find the issue during development.&lt;BR&gt;&lt;BR&gt;I have also found that reviewing my threading code with another developer to be a very useful strategy to find race conditions.&amp;nbsp; By walking through the code and explaining how it works, I have found that many issues, not just those related to threading, can be resolved before the code gets run.&lt;BR&gt;&lt;BR&gt;&lt;B&gt;Avoiding race conditions&lt;/B&gt;&lt;BR&gt;By far, the best approach to handling race conditions is to code proactively.&amp;nbsp; If your library code could possibly be used in a multi-threaded application, use synchronization objects (&lt;A href="http://msdn2.microsoft.com/en-us/library/c5kehkcz"&gt;locks&lt;/A&gt;, &lt;A href="http://msdn2.microsoft.com/en-us/library/system.threading.mutex"&gt;mutexes&lt;/A&gt;, &lt;A href="http://msdn2.microsoft.com/en-us/library/system.threading.manualresetevent"&gt;ManualResetEvents&lt;/A&gt;, etc) to make the code thread safe.&amp;nbsp;&amp;nbsp; Be sure to take care and perform only thread safety critical operations within these synchronization events to avoid deadlocks such as the example shown in my &lt;a href="http://blogs.msdn.com/davidklinems/archive/2005/09/15/467827.aspx"&gt;earlier post&lt;/A&gt; (where I used a ManualResetEvent within a lock statement).&lt;BR&gt;&lt;BR&gt;Take care,&lt;BR&gt;-- DK&lt;BR&gt;&lt;BR&gt;&lt;FONT size=1&gt;Disclaimer(s):&lt;BR&gt;This posting is provided "AS IS" with no warranties, and confers no rights.&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=484275" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/davidklinems/archive/tags/Debugging/default.aspx">Debugging</category></item></channel></rss>