2018-9-20-断点调试-Windows-源代码

title author date CreateTime categories
断点调试 Windows 源代码
lindexi
2018-09-20 17:37:55 +0800
2018-05-11 20:18:58 +0800
VisualStudio 调试

本文来告诉大家如何使用断点的方式,在 PotPeek 工具的反编译看到报告的异常。 这个方法对于 DUMP 调试比较有用,可以知道是在哪个函数哪一句抛出的异常。

首先先让软件出现一个异常,那么最简单的异常就是跨线程访问主线程

在 页面写一个依赖属性,然后在另一个线程设置这个属性

        public MainWindow()
        {
            InitializeComponent();

            new Thread(() =>
            {
                TowbiboujeJerexakipa = "123";

            }).Start();
        }

        public static readonly DependencyProperty TowbiboujeJerexakipaProperty = DependencyProperty.Register(
            "TowbiboujeJerexakipa", typeof(string), typeof(MainWindow), new PropertyMetadata(default(string)));

        public string TowbiboujeJerexakipa
        {
            get { return (string) GetValue(TowbiboujeJerexakipaProperty); }
            set { SetValue(TowbiboujeJerexakipaProperty, value); }
        }

按一下运行就可以看到下面的异常,但是大家想知道这个异常是在底层哪里抛出的?

2018-9-20-断点调试-Windows-源代码

如果这时在我的设备,可以看到调用堆栈,我双击一下就可以进去代码

2018-9-20-断点调试-Windows-源代码

想知道我是怎么做的就继续看博客,不想知道的就点关闭页面

下载微软代码

打开 https://referencesource.microsoft.com/ 可以看到 Download 点击进入就可以看到这个界面

2018-9-20-断点调试-Windows-源代码

自己需要什么版本就下载什么版本,不过我是把所有的版本都下载,然后创建 git 管理,这样需要哪个版本就可以快速切换

调试文件

但是下载好的文件,VisualStudio 怎么知道他需要从哪里找?虽然 VisualStudio 可以添加人工智能告诉你怎么写代码才有坑,但是他也不知道你下载的文件会放在哪。

通过右击解决方案,点击属性,可以看到可以设置源代码

2018-9-20-断点调试-Windows-源代码

我就把我下载的源代码解压到 God 文件夹的 source 文件夹,也就是图片最后一行,我就这样添加了代码。

这时 VisualStudio 就会尝试去这里寻找源代码。不过不要想着这样就可以像我一样快速调试源代码,还需要另一个工具

DotPeek

打开 DotPeek ,如果还没下载,那么请到官网下载

或者到我上传的 **** 下载 dotPeek 查看源代码-****下载

在我的调试 ms 源代码 已经有告诉大家如何调试 ms 源代码,但是没有告诉大家如何做到断点调试,直接看到微软源代码是哪里异常

符号服务器

打开 dotpeek 符号服务器,打开和使用方法请看调试 ms 源代码

加载代码

如果发现 dotpeek 的加载的代码太少了,如没有找到 WindowsBase 就需要在 GAC 添加代码

2018-9-20-断点调试-Windows-源代码

点击 OpenFromGAC 就可以在 GAC 寻找代码,如果需要调试 WPF 代码,那么 WindowsBase 是必须添加的

2018-9-20-断点调试-Windows-源代码

加载符号

这时很多小伙伴都关闭了符号加载,因为打开符号加载,开始调试需要等很久,如果大家有缓存自己的符号,那么调试加载符号还是很快的。

如果开始没有加载符号,在调试就需要打开点击工具 调试-> 窗口->模块

2018-9-20-断点调试-Windows-源代码

如果看到自己没有加载符号,就需要右击这个模块,点击加载符号

2018-9-20-断点调试-Windows-源代码

这时点击了就可以去喝咖啡,因为需要等待 dotpeek 创建符号,打开 dotpeek 可以看到进度,是非常慢的

除了WindowsBase还需要添加 PresentationCore ,如果自己的 PotPeek 没有,请自己添加

下面是需要检查的代码

  • mscorlib

  • System

  • System.Core

  • System.Xml

  • System.Xaml

  • WindowsBase

  • PresentationCore

  • PresentationFramework

找到符号

有时候发现虽然已经按照我说的做了,还是无法进入堆栈代码,而且弹出了这个选项,让你去找文件

2018-9-20-断点调试-Windows-源代码

这时就需要使用 dotpeek 找到对应的代码,然后导出工程

在对应的代码右击,选择导出工程

如果自己有导出,那么把这个工程添加到设置源代码

2018-9-20-断点调试-Windows-源代码

断点调试

如果已经看到了这里,请不要说我写了这么久还没说到主题,刚才只是准备,现在开始就是断点调试

点击调试->新建断点,例如下面需要调试 PenContext.InitStylusPointDescription 函数,就需要在断点写入 类名.函数名

2018-9-20-断点调试-Windows-源代码

这个函数在第一次触摸时触发,所以使用这个断点就可以在第一次触摸进去

运行程序,如果在断点可以看到一个红色的点,表示这个断点是可以进去

2018-9-20-断点调试-Windows-源代码

如果看到一个黑点,表示这个断点无法进入,这时尝试加载符号,需要注意,必须要使用 dotPeek 符号服务器才可以加载,这时需要开着 dotpeek 只要加载第一次符号,之后加载还是很快

这时试试触摸一下,就可以看到跳转到这个函数

2018-9-20-断点调试-Windows-源代码

下面就可以高兴对这个类的函数进行断点,但是不是全部语句都可以添加断点,因为调试的源代码是 Release 会优化很多代码。

简单的调试

如果这时为了调试简单的代码,还可以使用 dnspy 调试,使用这个调试十分快。

首先下载 dnSpy,这个软件需要区分 x86 和 x64 选择自己需要调试的程序的平台,运行。

首先拖入已经编译好的 exe 到 dnspy

2018-9-20-断点调试-Windows-源代码

然后点击拖入的 exe 点击运行就可以调试这个 exe 了,但是这里是告诉大家如何调试源代码,首先寻找到需要调试的代码

2018-9-20-断点调试-Windows-源代码

还是告诉大家如何调试 PenContext.InitStylusPointDescription ,因为我知道 PenContext 在哪,于是我就一级级展开,找到 InitStylusPointDescription 函数,在这个函数按下 F9 没错,他的快捷键和 VisualStudio 差不多,这时按下 F5 调试程序

2018-9-20-断点调试-Windows-源代码

在使用这个软件还可以在自己的代码断点,然后按 F11 进入微软框架代码查看他是怎么做的。

虽然我告诉了大家这些方法用来断点调试,但是我无法说大家一定可以使用我的方法看到源代码,有一些源代码是无法拿到的,有一些是没有符号。

看到这里大家是否好奇为什么我在调试 InitStylusPointDescription ? 因为我的 WPF 在一个特殊的屏幕点击就会崩溃,我拿到了 Dump ,看到了托管异常

2018-9-20-断点调试-Windows-源代码

我使用了 dnspy 定位了堆栈,然后远程调试,加载了符号,进入源代码查看了这个函数

2018-9-20-断点调试-Windows-源代码

我发现是在这一行代码崩溃的

      StylusPointPropertyInfo pointPropertyInfo = new StylusPointPropertyInfo(new StylusPointProperty(guid, false), iMin, iMax, (StylusPointPropertyUnit) iUnits, flResolution);

我进入了 StylusPointPropertyInfo 构造函数

2018-9-20-断点调试-Windows-源代码

很快就看到抛异常的代码

      if (maximum < minimum)
        throw new ArgumentException(MS.Internal.PresentationCore.SR.Get("Stylus_InvalidMax"), nameof (maximum));

这里 maximum 是 0xFFFFFFFF 因为这里是 int 判断,最大值 -1 所以返回 false ,在 usb 论坛找到工具

发现是插入屏幕描述符是错的,所以就让硬件去修改。