新闻  |   论坛  |   博客  |   在线研讨会
.NET CF命令行调试器MDbg入门
tongxin | 2009-04-28 16:33:29    阅读:1174   发布文章

   认识MDbg和.NET Compact Framework 2.0 SP1    老狼的话:David Kline是.NET CF团队一位非常优秀的开发者,看到他这个系列文章已经很久了,一直没空翻译。今天用下班后的时间翻译出来,也是希望有个督促,能让这个系列文章让更多朋友认识。原文地址:http://blogs.msdn.com/davidklinems/archive/2006/07/13/665023.aspx

     现在距离我写如何在.NET Compact Framework中使用命令行调试器(cordbg)的文章,已经有一段时间了。在这段时间里.NET CF的命令行调试已经发生了很大的变化。

    去年发布的.NET Framewrok SDK 2.0中,出现了一个新的命令行调试器(MDbg)。MDbg是使用托管代码编写的,并且可以通过扩展程序集(DLLs)来添加新功能。在我们发布2.0版本的时候,这个扩展功能还没有被.NET CF所支持。不过当.NET CF 2.0 SP1发布的时候,我们的扩展程序集(mdbgnetcf.dll)已经可用了。

如果您读过我最初的命令行调试器系列文章,您也许会回忆起在.NET CF 1.0中得到命令行调试环境的几个步骤。我高兴地宣布,我们通过MDbg扩展开始的步骤要简单很多。我会在今天的文章里介绍如何为设备添加mdbgnetcf扩展,并运行命令。

预备步骤
在我们开始使用MDbg调试一个.NET CF应用程序之前,有一些准备工作是我们必须完成的。
1.    下载并安装.NET Compact Framework 2.0 SP1
2.    更新你的设备到.NET CF SP1
3.    拷贝下列文件到设备的\Windows目录中
a)    从 <drive>:\Program Files\Common Files\Microsoft Shared\CoreCon\1.0\Target\wce400\<cpu>
i.    edbgtl.dll
ii.    tcpconnectiona.dll
b)    从SP1的安装目录 (比如 <drive>:\Program Files\Microsoft.NET\SDK\CompactFramework\v2.0\WindowsCE\<version>\<cpu>
i.    netcfrtl.dll
ii.    netcflaunch.exe
4.    将你的应用程序文件部署到设备上
对于一台设备,步骤2和3只需要准备一次。步骤1每台开发、调试PC只需要准备一次。步骤4在每次应用程序更新后需要进行。

开始
一旦准备任务完成,我们可以使用MDbg开始调试我们的程序了。
1.    运行mdbg.exe
我推荐从Visual Studio 2005 Command Prompt中运行MDbg(Start Menu\All Programs\Microsoft Visual Studio 2005\Visual Studio Tools)或者SDK Command Prompt(Start Menu\All Programs\Microsoft .NET Framework SDK v2.0).这将保证MDbg.exe在搜索路径中。
2.    加载mdbgnetcf扩展
mdbg>load <path>\mdbgnetcf
请注意在使用load命令时,文件扩展名(.dll)是不用写的。
当扩展被加载后,会显示出下面的信息:
.NET Compact Framework extension loaded successfully.
3.    在设备中运行NetCFLaunch.exe
当NetCFLaunch启动,将会显示连接到设备所必须的传送参数(例如:169.254.2.1 6510)。我们将在下一步用到这个传送参数。 
4.    使用device命令连接到设备
device 169.254.2.1 6510
当device命令成功完成,我们将与NetCFLaunch程序建立一个连接。NetCFLaunch窗口将显示“Connection SUCCEEDED”。
5.    使用run命令运行你的应用程序
我将使用Visual Studio 2005中的WebCrawler示例程序
run "\program files\webcrawler.exe"
当run命令完成,MDbg将显示当前的source位置(应用程序的入口点)。
STOP: Breakpoint Hit
288: {
[p#:0, t#:0] mdbg>
注意:Mdbug涉及的初始或临时断点被调试器管理,当MDbg连接到应用程序时,断点被插入或清除。
现在你可以使用其他的MDbg命令来调试你的应用程序了。你可以使用h[elp] 或者 ? 命令来列出目前可用的命令。

在接下来的一周,我计划继续这个系列并讨论被mdbgnetcf扩展添加的其他命令,并且演示一些例子来告诉你们应该如何去做。 Visual Studio 2005设备模拟器是一个非常酷的工具,用于开发、测试和调试Windows Mobile应用程序。你可以在模拟器上设计并运行多种Windows Mobile设备。另外,你可以安装并使用本地化映像文件,使你的程序在多种语言版本的Windows Mobile操作系统上运行。

在默认情况下,设备模拟器使用DMA方式传输设备与桌面PC之间的通讯。MDbg命令行调试器支持TCP/IP通讯方法。为了允许MDbg使用设备模拟器,在连接被建立前,我们需要进行一些额外的步骤。

Abhi Khune有一篇很好的文章《使用设备模拟器建立一个Internet连接》。在那篇文章里,有一个章节是谈论关于DMA和TCP/IP传输,其中谈到,将设备模拟器的传输方式从DMA转换为TCP/IP是不被推荐的。除了一种情况外,我完全同意这个建议。这个情况就是通过.NET CF 2.0 SP1调试器扩展(mdbgnetcf)将MDbg连接到设备模拟器。

注意:在改变了设备模拟器的传输方式后,你需要重启设备。

建议:我强烈建议在使用MDbg调试完成后,将设备模拟器的传输方式改回DMA。

一旦设备模拟器被配置为TCP/IP传输方式,会有两种连接选择:

   1,ActiveSync
对于我来说,用设备模拟器建立TCP/IP连接最简单的办法就是使用Visual Studio 2005的Device Emulator Manager的“cradle”命令和ActiveSync进行连接。
Abhi的文章中有对于如何使用Device Emulator Manager的完整描述,并且有很多配图。

    2,Virtual Machine Network Driver
另一种方法是安装Virtual Machine Network Driver,你可以在微软下载中心下载并且阅读安装说明。
当使用Virtual Machine Network Driver时,我们就不需要再使用Device Emulator Manager 来连接ActiveSync和设备模拟器了。

请注意你需要在每次使用MDbg前完成上述步骤。

完成上述步骤之后,你可以使用第一章的办法来连接并使用MDbg调试。

在这个系列的前两篇文章中,我讨论了MDbg的入门和使用设备模拟器。这次,我们来讨论如何使用MDbg在调试过程中来控制设备上的进程。Commands
cp[roc]
kp[roc]
pro[cessenum]cp[roc]命令:运行一个进程,不将调试器attach到进程中在我的第一篇文章中,我谈到了如何连接NetCFLaunch应用程序,和开始调试一个应用程序。那时我想调试所运行的进程,如果我想启动一个进程,但不进行调试。我会使用cp[roc]命令,示例如下:

mdbg> cp "\program files\webcrawler.exe"

如果命令能够启动一个进程,mdbg>的提示符将会出现。如果不能启动一个进程(例如:应用程序不存在),将会有一个错误提示出现。

pro[cessenum] 命令:列出当前设备中运行的进程

如果你经常需要了解哪些进程运行在你的设备上。例如,你的应用程序需要依赖于其他进程所提供的数据或者执行特别的人物。使用pro[cessenum]命令允许你检查所依赖的进程是否在运行。下面的例子是显示运行在你的Windows Mobile 5.0 Pocket PC上的进程:

mdbg> pro
Active processes on current machine:
(PID: 0x0dcb4002) NK.EXE
(PID: 0xedca5752) filesys.exe
(PID: 0x8dadc526) device.exe
(PID: 0xcd7f62ea) shell32.exe
(PID: 0xcd97c7a6) gwes.exe
(PID: 0xcd7f6732) services.exe
(PID: 0x2d4b6da6) CommLoader.exe
(PID: 0xcd517ac2) BatteryIndicator.exe
(PID: 0x2d5219ea) connmgr.exe
(PID: 0xad517b8a) srvtrust.exe
(PID: 0xed810392) repllog.exe
(PID: 0x2d4b6c76) poutlook.exe
(PID: 0xed3affce) cprog.exe
(PID: 0x2d99977a) rapiclnt
(PID: 0xeced62b2) webcrawler.exe
(PID: 0x2d0ed5be) tmail.exe
(PID: 0x8d30f68a) netcflaunch.exe

查看这个进程列表,我们可以看到早先调用cp[roc]命令时成功地运行了webcrawler.exe。

Kp[roc]命令:终止一个运行的进程

有一些情况下,我们需要终止一个进程的运行。当我的应用程序与其他进程通讯时,我需要研究失败代码路径,这将是非常有用的。下面的例子中,我使用kp[roc]命令来终止webcrawler.exe进程,这个进程是我用cp[roc]命令启动的。

mdbg> kp 0xeced62b2

传递给kp[roc]命令的值是被pro[cessenum]命令列出的进程ID(PID)。

(PID: 0xeced62b2) webcrawler.exe

注意:在终止设备上的进程时请务必小心,强制终止了错误的应用程序可能会让设备产生不稳定情况,或者相应迟缓。(译者注:NK.EXE、filesys.exe、device.exe、shell32.exe、gwes.exe和services.exe是系统运行相关的进程,所以不能强制终止。)

提示:使用命令行提示窗体中的QuickEdit模式或Mark and Paste功能可以让MDbg使用剪切和拷贝功能。


能够attach到一个运行中的进程中是调试器非常强大的一个功能。这项功能对于调试运行中的应用程序特别便利。对于CorDbg来说,当调试.NET CF程序时,并不支持正式的attach process。使用.NET CF MDbg调试器扩展(2.0版本SP1),支持在命令行中附加调试器到一个运行中的程序中。

注意:在我们附加MDbg到我们的应用程序(Visual Studio 2005 WebCrawler sample)之前,我们必须让设备支持attach to process。这个步骤要在我们想调试的应用程序启动之前完成。

当调试一个.NET CF应用程序时,第一步是使用MDbg加载.NET Compact Framework 扩展(mdbgnetcf.dll)。一旦扩展被加载,我们可以创建一个连接到我们的目标设备。这些在本系列的第一部分有描述。

下一步是启动我们希望调试的应用程序。应用程序可以通过在设备中点击它们的图标来启动,或者可以通过MDbg的cp[roc]命令(创建进程)。因为我们已经设置了调试器环境,所以我通过cp[roc]命令来启动进程。关于cp[roc]和其他进程控制命令的更多信息可以查看本系列的第三部分。

mdbg> cp "\program files\webcrawler.exe"

我们的应用程序现在已经在设备中启动了。为了attach,我们需要知道应用程序的进程ID。

mdbg> pro
Active processes on current machine:
<< additional processes removed for clarity >>
(PID: 0x6de24e9a) webcrawler.exe

通过输入,我们可以看到WebCrawler的进程ID是0x6de24e9a,我们将使用这个值来attach我们的应用程序。

mdbg> a 0x6de24e9a

在attach之后,我们将不会返回到mdbg>的提示符,为了能够开始调试我们的应用程序,我们需要使用Ctrl+C来打断调试器。

<Ctrl+C>
STOP AsyncStop
[p#:0, t#:no active thread] mdbg>

现在我们可以调试WebCrawler了。现在让我们在Crawler类的Crawl方法里设置一个断点。

在CorDbg中设置断点是具有挑战性的事情,为了能够成功的设置断点,我们必须输入精确的方法名称(区分大小写)。在MDbg中这将变得简单。使用x命令,我们可以在WebCrawler模块中搜索我们感兴趣的方法。

[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()

在这个列表中,我们看到条目12是我们要找的方法。为了给Crawl方法设置一个断点,我们可以引用条目数。

[p#:0, t#:no active thread] mdbg> b ~12
Breakpoint #1 bound (:1!Microsoft.Samples.NetCF.Crawler::Crawl(+0))

当我们继续执行应用程序(并在WebCrawler应用程序中点击Start),我们将停止在Crawl方法开始的地方。

[p#:0, t#:no active thread] mdbg> g
STOP: Breakpoint 1 Hit
located at line 380 in Crawler.cs
[p#:0, t#:no active thread] mdbg>

Enjoy!
-- DK

*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。

参与讨论
登录后参与讨论
最近文章
寂寞如雪
2009-05-19 19:01:18
夜色花
2009-05-19 18:56:22
没有爱可以重来
2009-05-19 18:54:59
推荐文章
最近访客