Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >dotnet 简单写一个 pdb 符号文件下载器

dotnet 简单写一个 pdb 符号文件下载器

作者头像
林德熙
发布于 2024-11-27 01:24:10
发布于 2024-11-27 01:24:10
9800
代码可运行
举报
文章被收录于专栏:林德熙的博客林德熙的博客
运行总次数:0
代码可运行

本文将告诉大家如何读取 PE 文件头信息,拼接 PDB 符号文件下载地址,从微软公共符号服务器拉取符号文件

本文将以拉取 ntdll.dll 为例子告诉大家如何从 msdl.microsoft.com 下载符号

我先将自己电脑上的 ntdll.dll 拷贝到输出路径,方便我进行访问。读取 C 盘的 Windows 文件夹的 DLL 文件也是有读取权限的,即不拷贝到输出路径也不会有任何的问题的

整体步骤是先读取 dll 的 PE 文件信息,获取到调试信息,即 PDB 名加 Guid 和 Age 参数,由以上三个参数拼接为下载地址

本文使用的 PEReader 等辅助类为 .NET Core 1.0 引入,如需在 .NET Framework 使用,请安装 System.Reflection.Metadata

本文建立的是 dotnet 9 的控制台文件

先使用 File.OpenRead 打开要读取的 DLL 文件,代码如下

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var file = @"ntdll.dll";

using var fileStream = File.OpenRead(file);

接着放入到 PEReader 里面读取,如此即可非常方便完成对 PE 文件的读取,代码如下

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var peReader = new PEReader(fileStream);

尝试读取传入的 PE 文件的调试目录信息,代码如下

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var debugDirectoryEntries = peReader.ReadDebugDirectory();

这里的调试目录可能有很多,咱只需使用 DebugDirectoryEntryType.CodeView 类型的即可

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
foreach (var debugDirectoryEntry in debugDirectoryEntries)
{
    if (debugDirectoryEntry.Type != DebugDirectoryEntryType.CodeView)
    {
        continue;
    }

    ...
}

在 DebugDirectoryEntry 里面存放的只是一些地址偏移和大小的信息,需要进一步调用 ReadCodeViewDebugDirectoryData 方法读取到更多信息,代码如下

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
foreach (var debugDirectoryEntry in debugDirectoryEntries)
{
    if (debugDirectoryEntry.Type != DebugDirectoryEntryType.CodeView)
    {
        continue;
    }

    var readCodeViewDebugDirectoryData = peReader.ReadCodeViewDebugDirectoryData(debugDirectoryEntry);
    var path = readCodeViewDebugDirectoryData.Path;
    var guid = readCodeViewDebugDirectoryData.Guid;
    var age = readCodeViewDebugDirectoryData.Age;

    var pdbName = path;

    ...
}

如此即可获取到下载地址拼接的信息

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    var downloadUrl = $"http://msdl.microsoft.com/download/symbols/{pdbName}/{(guid.ToString("N").ToUpperInvariant() + age.ToString())}/{pdbName}";

继续使用 HttpClient 将其下载下来,代码如下

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    var httpClient = new HttpClient();

    using var httpResponseMessage = await httpClient.GetAsync(downloadUrl, HttpCompletionOption.ResponseHeadersRead);

    var pdbFile = Path.GetFullPath(pdbName);
    await using var downloadFileStream = File.Create(pdbFile);
    await httpResponseMessage.Content.CopyToAsync(downloadFileStream);

下载文件的方法十分简单,先是准备要下载的文件存放的路径,我这里使用的是相对工作路径的方式,即 var pdbFile = Path.GetFullPath(pdbName); 简单的方式拿到绝对路径。这里获取绝对路径仅仅只是为了方便调试而已,无实际逻辑意义

接着使用 File.Create 方法创建文件,且返回 FileStream 对象,方便进行下载内容的 CopyToAsync 写入到文件

以上代码的另一个细节是请求的时候带上了 HttpCompletionOption.ResponseHeadersRead 参数,带上这个参数将告诉 HttpClient 不要等待内容都拉取完了再让 GetAsync 方法返回,而是只要 http 的头信息拿到了,就应该返回了。这一点对下载文件来说,比较有优化,大部分下载的文件的文件长度都不小,全等待下载完成再让 GetAsync 返回,再拷贝到文件,这个逻辑相对来说是比较亏的。只有对 API 调用形的后台访问,才合适使用默认的 HttpCompletionOption.ResponseContentRead 参数,全部完成再返回,如此可以更简化异常处理情况,确保网络通讯完成再返回

通过上文简单的方式即可完成对 DLL 的符号文件下载

以上代码其实还隐藏了另一个功能,那就是自己组建符号服务器,可以自己在构建完成之后,根据如上信息,将 PDB 符号文件存放到合适的路径里面或记录到数据库里面,不依赖 symstore 工具

本文的 Program.cs 代码如下

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
using System.Reflection.PortableExecutable;
using System.Runtime.InteropServices;
using System.Text;

var file = @"ntdll.dll";

using var fileStream = File.OpenRead(file);

var peReader = new PEReader(fileStream);
var httpClient = new HttpClient();

var debugDirectoryEntries = peReader.ReadDebugDirectory();
foreach (var debugDirectoryEntry in debugDirectoryEntries)
{
    if (debugDirectoryEntry.Type != DebugDirectoryEntryType.CodeView)
    {
        continue;
    }

    var readCodeViewDebugDirectoryData = peReader.ReadCodeViewDebugDirectoryData(debugDirectoryEntry);
    var path = readCodeViewDebugDirectoryData.Path;
    var guid = readCodeViewDebugDirectoryData.Guid;
    var age = readCodeViewDebugDirectoryData.Age;

    var pdbName = path;

    var downloadUrl = $"http://msdl.microsoft.com/download/symbols/{pdbName}/{(guid.ToString("N").ToUpperInvariant() + age.ToString())}/{pdbName}";
    using var httpResponseMessage = await httpClient.GetAsync(downloadUrl, HttpCompletionOption.ResponseHeadersRead);

    var pdbFile = Path.GetFullPath(pdbName);
    await using var downloadFileStream = File.Create(pdbFile);
    await httpResponseMessage.Content.CopyToAsync(downloadFileStream);
}

本文代码放在 githubgitee 上,可以使用如下命令行拉取代码。我整个代码仓库比较庞大,使用以下命令行可以进行部分拉取,拉取速度比较快

先创建一个空文件夹,接着使用命令行 cd 命令进入此空文件夹,在命令行里面输入以下代码,即可获取到本文的代码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
git init
git remote add origin https://gitee.com/lindexi/lindexi_gd.git
git pull origin 6bc0a171f53f4da8a968257c621c9df7a6de77a3

以上使用的是国内的 gitee 的源,如果 gitee 不能访问,请替换为 github 的源。请在命令行继续输入以下代码,将 gitee 源换成 github 源进行拉取代码。如果依然拉取不到代码,可以发邮件向我要代码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
git remote remove origin
git remote add origin https://github.com/lindexi/lindexi_gd.git
git pull origin 6bc0a171f53f4da8a968257c621c9df7a6de77a3

获取代码之后,进入 Workbench/WerjiwaijogoNemcuryecho 文件夹,即可获取到源代码

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
win8 metro HttpClient下载文件-带进度条
井九
2024/10/12
830
使用 System.Net.Http.Json 高效处理Json数据
在这篇文章,我将介绍一个名为 System.Net.Http.Json 的扩展库,它最近添加到了 .NET 中,我们看一下这个库能够给我们解决什么问题,今天会介绍下如何在代码中使用。
全球技术精选
2021/01/09
2.2K0
使用 System.Net.Http.Json 高效处理Json数据
dotnet 通过 HttpClient 下载文件同时报告进度的方法
通过 HttpClient 的 ContentLength 很多时候都可以拿到下载的内容的长度,通过 ReadAsync 可以返回当前读到的长度,将读取到的长度加起来就是已经下载的长度
林德熙
2019/03/13
2K0
dotnet 通过 HttpClient 下载文件同时报告进度的方法
通过 HttpClient 的 ContentLength 很多时候都可以拿到下载的内容的长度,通过 ReadAsync 可以返回当前读到的长度,将读取到的长度加起来就是已经下载的长度
林德熙
2022/08/07
1.1K2
Windbg调试----Windbg入门
Windbg简单来说就是一个Windows下对用户态/内核态的程序进行调试,以及对Core Dump文件的分析。对于Crash,资源泄露,死锁等问题的分析,Windbg是一个强有力的利器。
河边一枝柳
2021/08/06
2.7K0
Windbg调试----Windbg入门
abp_vue导入导出excel
后端abp,前端vue导入excel,开始准备用直接用npoi,觉得要写太多的代码,就算从以前的复制粘贴也麻烦,所以偷懒直接用别人的轮子 Magicodes.IE。这样可以节省很多工作,根据实体生成excel模板、支持枚举、导入时自动验证数据是否合法(必填、类型等)
用户6362579
2019/12/11
2.7K1
符号下载器 (dotnet-symbol)
若要安装最新版 dotnet-symbol NuGet 包,请使用 dotnet tool install 命令:
呆呆
2022/01/08
8780
WPF开发-网络请求
使用HttpWebRequest可以让开发者控制请求/响应流程的各个方面,如 timeouts, cookies, headers, protocols。
码客说
2022/09/02
2.5K0
.netcore+vue 实现压缩文件下载
目前接触的项目中,给定的需求是将系统内所有用户的数据整理好,并保存到文件夹内,目的主要是防止用户在实施人员已配置好的基础上由于不熟悉系统,导致的误删或者误操作。减少实施人员的配置工作。我首先想到的就是将数据导入到Excel中,并以各个用户的名称命名文件夹做好分类。
跟着阿笨一起玩NET
2022/05/12
6690
ASP.NET Web API 应用教程(一) ——数据流使用
相信已经有很多文章来介绍ASP.Net Web API 技术,本系列文章主要介绍如何使用数据流,HTTPS,以及可扩展的Web API 方面的技术,系列文章主要有三篇内容。 主要内容如下: I  数据流 II 使用HTTPS III 可扩展的Web API 文档 项目环境要求 VS 2012(SP4)及以上, .Net 框架4.5.1 Nuget包,可在packages.config 文件中查寻 本文涉及的知识点 ActionFilter AuthorizationFilter DelegateHand
葡萄城控件
2018/01/10
2.4K0
ASP.NET  Web API 应用教程(一) ——数据流使用
C#13和 .NET9高级功能解析:.NET高手必备技能
随着 C# 13 和 .NET 9 的发布,现代应用程序的开发变得更加高效和便捷。本文将深入探讨 C# 13 和 .NET 9 的高级功能,并通过复杂代码示例展示如何在大型应用中利用这些特性实现最佳性能。
郑子铭
2024/12/31
1990
C#13和 .NET9高级功能解析:.NET高手必备技能
asp dotnet core 支持客户端上传文件
新建一个 asp dotnet core 程序,创建一个新的类,用于给客户端上传文件的信息
林德熙
2022/08/04
5.3K0
Asp.Net WebApi核心对象解析(二)
彭泽0902
2018/01/04
3.2K0
WinDbg调试.NET程序入门
俗话说:万事开头难! 自从来到新公司遇到性能问题后,需要想办法解决这个问题,但是一直没有合适的性能分析工具,然后找到StevenChennet 大神帮忙,他用WinDbg工具远程帮我分析了一个 dump文件,但是只看到键盘 “啪啪啪”,得到了结果,却不是很清楚WinDbg神奇具体如何使用的。结果,第二天,性能问题又来了,总不能每次劳烦大神驾到,所以不得不自己开始学习WinDbg,这里记录一个入门过程。 1,首先,下载并安装WinDbg程序 从下面的地址打开: https://msdn.microsoft.c
用户1177503
2018/02/26
1.9K0
win10 uwp 使用 asp dotnet core 做图床服务器客户端 服务器端客户端
本文告诉大家如何在 UWP 做客户端和 asp dotnet core 做服务器端来做一个图床工具
林德熙
2019/03/13
2.8K0
win10 uwp 使用 asp dotnet core 做图床服务器客户端
            服务器端客户端
win10 UWP 访问网页
Windows10 UWP 要访问 csdn博客,可以使用Windows.Web.Http.HttpClient,下面尝试访问一下我的博客 http://blog.csdn.net/lindexi_gd/article/details/50392343
林德熙
2022/08/04
5840
dotnet 6 使用 HttpWebRequest 进行 POST 文件将占用大量内存
我有用户给我报告一个内存不足的问题,经过了调查,找到了依然是使用已经被标记过时的 HttpWebRequest 进行文件推送,推送过程中,由于 System.Net.RequestStream 将会完全将推送的文件全部读取到内存,导致了在 x86 应用下,推送超过 500MB 的文件,基本上都会抛出 OutOfMemoryException 异常
林德熙
2022/08/12
1.3K0
dotnet 6 使用 Obfuscar 进行代码混淆
本文来安利大家 Obfuscar 这个好用的基于 MIT 协议开源的混淆工具。这是一个非常老牌的混淆工具,从 2014 年就对外分发,如今已有累计 495.5K 的 nuget 下载量。而且此工具也在不断持续迭代更新,完全支持 dotnet 6 版本,对 WPF 和 WinForms 等等的支持也是非常好,支持多个不同混淆方式和等级的配置,支持混淆之后生成符号文件。本文将来告诉大家如何使用此混淆工具,以及此工具能达成的效果和此工具混淆的原理
林德熙
2022/08/12
2.3K0
dotnet 6 使用 Obfuscar 进行代码混淆
网页解析高手:C#和HtmlAgilityPack教你下载视频
在当今互联网时代,视频内容已成为人们获取信息和娱乐的重要途径之一。而小红书作为一个内容丰富的社交平台,其中的视频资源备受关注。本文将介绍如何利用C#编程语言和HtmlAgilityPack库来解析小红书网页,从而下载小红书视频。
jackcode
2024/03/26
2700
网页解析高手:C#和HtmlAgilityPack教你下载视频
asp dotnet core 支持客户端上传文件
新建一个 asp dotnet core 程序,创建一个新的类,用于给客户端上传文件的信息
林德熙
2019/03/13
6.4K0
相关推荐
win8 metro HttpClient下载文件-带进度条
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验