.NET Core分析程序集最优美的方法,不用Assembly.LoadFile(),超越ReflectionOnlyLoad

在编写.NET程序的时候,如果需要对一个程序集文件进行分析,我们可以使用Assembly.LoadFile()来加载这个程序集,然后对LoadFile()方法返回的Assembly对象进行进一步的分析。但是Assembly.LoadFile()方法会以执行为目的把程序集加载到程序中,因此它对于被加载的程序集文件有严格的要求,比如,如果被程序集所依赖的程序集不存在,那么LoadFile()会抛出异常,再比如,在.NET Core中加载.NET Framework的程序集,LoadFile()也会抛出异常。如果我们只想分析程序集,但是并不需要执行程序集,那么我们就需要一种单纯地分析程序集文件的方式。

.NET Framework提供了Assembly.ReflectionOnlyLoad()来实现类似的效果,但是这个方法由于依赖于AppDomain,因此在.NET Core中不被支持。微软曾经在实验室项目中提出过一个在.NET Core中实现这个功能的System.Reflection.TypeLoader,但不知道什么原因,没有在.NET Core的正式版中提供这个类。

我们知道,.NET程序集是PE格式的文件,.NET中提供了用来分析PE文件的类PEReader(位于System.Reflection.Metadata这个NuGet包中),因此我们可以用PEReader来分析程序集文件。

在PEReader中,我们可以通过TypeDefinitions获取到程序集中的所有类,我们可以用GetMethods()获取某个类中定义的所有方法。为了提升效率,TypeDefinitions、GetMethods()等成员获得到的对象都是TypeDefinitionHandle、MethodDefinitionHandle等句柄类型的,这些对象只包含地址信息,并不包含类型的名字、方法的名字、方法的参数等详细信息,要获取这些信息,我们需要调用MetadataReader的GetTypeDefinition()、GetMethodDefinition()等方法来获取。如下的代码用来加载一个程序集,并且输出程序集中所有的类型信息以及类型中定义的方法:

//Install-PackageSystem.Reflection.Metadata
using System.Reflection.Metadata;
using System.Reflection.PortableExecutable;string file =@"E:\Microsoft.AspNetCore.Components.Web.dll";
using FileStream fileStream =File.OpenRead(file);
using PEReader peReader = newPEReader(fileStream);
if(!peReader.HasMetadata)
{Console.WriteLine($"{file} doesn't contain CLI metadata.");return;
}
var mdReader =peReader.GetMetadataReader();
if (!mdReader.IsAssembly)
{Console.WriteLine($"{file} is not an assembly.");return;
}
foreach (var typeHandler inmdReader.TypeDefinitions)
{var typeDef = mdReader.GetTypeDefinition(typeHandler);string name = mdReader.GetString(typeDef.Name);string nameSpace = mdReader.GetString(typeDef.Namespace);Console.WriteLine($"***********{nameSpace}.{name}***********");foreach (var methodHandler in typeDef.GetMethods()){var methodDef = mdReader.GetMethodDefinition(methodHandler);Console.WriteLine(mdReader.GetString(methodDef.Name));}
}

       使用PEReader的时候,我们需要先获得XXXHandler,然后再调用MetadataReader获取句柄的详细信息,这样做尽管性能比较高,但是代码比较繁琐,而且在实现某些高级操作的时候比较麻烦。比如,如果我们要获取一个程序集的CustomAttribute信息,PEReader并没有提供比较简单的方法,需要我们对PE格式非常精通,才能编写出来对应的代码。

       我们可以使用AsmResolver.DotNet这个第三方Nuget包来简化程序集文件的读取分析,它是对PEReader的一个高级封装。如下的代码用来加载一个程序集,输出程序集的公司信息,并且输出程序集中所有的类型信息以及类型中定义的方法:

string file =@"E:\Microsoft.AspNetCore.Components.Web.dll";
var moduleDef =AsmResolver.DotNet.ModuleDefinition.FromFile(file);//用的不是System.Reflection.Metadata命名空间下的ModuleDefinition类
var asmCompanyAttr =moduleDef.Assembly.CustomAttributes.FirstOrDefault(c =>c.Constructor.DeclaringType.FullName =="System.Reflection.AssemblyCompanyAttribute");
var utf8Value =(Utf8String?)asmCompanyAttr.Signature.FixedArguments[0].Element;
var strValue = (string?)utf8Value;
Console.WriteLine($"companyname:{strValue}");
foreach(var typeDef inmoduleDef.GetAllTypes())
{string name = typeDef.Name;string nameSpace = typeDef.Namespace;Console.WriteLine($"***********{nameSpace}.{name}***********");foreach (var methodDef in typeDef.Methods){Console.WriteLine(methodDef.Name);}
}

       总之,如果我们需要分析一个程序集并且要运行其中的代码,我们可以使用Assembly.LoadFile();如果我们不需要运行程序集,只是想分析程序集,那么使用PEReader是更好的选择,当然我们也可以选择对PEReader进行封装的AsmResolver.DotNet这个NuGet包。本文作者杨中科在Zack.Commons这个开源项目中实现“判断一个程序集是否是微软开发的”这个功能的时候就用到了AsmResolver.DotNet,大家可以查看这个项目的GitHub代码仓库来查看源代码。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/291646.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C#学习笔记——通用对话框

Visual Studio提供的通用对话框控件有:ColorDialog、FolderBrowserDialog、FontDialog、OpenFileDialog、SaveFileDialog、PageSetupDialog、PrintDialog和PrintPreviewDialog。 在使用这些中的某个“通用对话框”控件时,可以向窗体添加该控件&#xff0…

动态ram依靠什么存储信息_ROM、RAM、DRAM、SRAM和FLASH傻傻分不清

ROM、RAM、DRAM、SRAM和FLASH各类储存器在电脑、手机、电子设备、嵌入式设备及相应的开发中普遍应用的,但是很多还是傻傻分不清楚。下面就简单介绍下这几个吧!ROM和RAMROM:只读存储器或者固化存储器;RAM:随机存取存储器…

软件项目管理课后题下载【共5个章(1、3、4、5、6)】

都整理好了,链接在此:https://download.csdn.net/download/qq_44872173/15560093 目录如下:

linux c之snprintf()和sprintf()区别

1、snprintf函数 int snprintf(char *str, size_t size, const char *format, ...); 将可变个参数(...)按照format格式化成字符串,然后将其复制到str中 (1) 如果格式化后的字符串长度 < size,则将此字符串全部复制到str中,并给其后添加一个字符串结束符(/0); (2) 如果…

Chrome中输入框默认样式移除

Chrome中输入框默认样式移除 在chrome浏览器中会默认给页面上的输入框如input、textarea等渲染浏览器自带的边框效果 IE8中效果如下&#xff1a; Chrome中效果如下&#xff1a; 这在我们未给输入框设置获取焦点时改变边框颜色时&#xff0c;chrome浏览器解析页面中默认将输入框…

MBR解析

先推广一下QQ群&#xff1a;61618925。欢迎各位爱好编程的朋友加入。 一、程序界面 二、关键部分代码&#xff1a; 1.数据结构定义 #define MBRSIZE 512 #define BOOTRECORDSIZE 440 #define DISKSIGNEDSIZE 4 #define RESERVESIZE 2 #define DPTNUMBER 4 #define DPTSIZE 16 #…

css sprite讲解与使用实例

转自&#xff1a;http://www.manongjc.com/article/886.html 一、什么是css sprites css sprites直译过来就是CSS精灵。通常被解释为“CSS图像拼合”或“CSS贴图定位”。其实就是通过将多个图片融合到一张图里面&#xff0c;然后通过CSS background背景定位技术技巧布局网页背景…

如何通过 HttpWebRequest 上传文件?

咨询区 dr. evil我不希望通过 WebDAV 文件夹的方式上传文件&#xff0c;我想通过相关的 HttpWebRequest 类&#xff0c;类库或者代码片段来帮我模拟浏览器行为来上传文件&#xff0c;请问是否有好的解决方案&#xff1f;回答区 Joshcodes如果你用的是基于 .NET 4.5 以上的版本&…

实验 2 关键字驱动测试(2 学时)实验报告--软件功能测试与性能测试实验

以下是实验要求部分&#xff1a;&#xff08;小伙伴们根据自己需求决定是否下载哈&#xff09; 下载位置链接&#xff1a;https://download.csdn.net/download/qq_44872173/20031354

小手工纸盒机器人_亲子手工 | DIY弹珠迷宫小黑手自制玩具系列

上周用鞋盒做的迷你桌球受到很多男孩子的喜欢今天小黑手又做了一个瓦楞纸手工「弹珠迷宫」也是喜欢的爱不释手呢暑假小黑手系列&#xff0c;希望也能攒出个自己的小游乐场自己动手做自己的玩具&#xff0c;买玩具的钱可以省了快速手工教程Let’s do it我们一起做起来吧&#xf…

linux网络编程之用select方法实现io复用(基于udp)

1、基本概念 IO多路复用是指内核一旦发现进程指定的一个或者多个IO条件准备读取,它就通知该进程。IO多路复用适用如下场合:   (1)当客户处理多个描述字时(一般是交互式输入和网络套接口),必须使用I/O复用。   (2)当一个客户同时处理多个套接口时,而这种情况是可能…

Linux screen 常用命令

想必&#xff0c;只要接触过Linux一段时间的人&#xff0c;一定知道screen这个神奇的工具了&#xff0c;它主要有如下些优势&#xff1a; 1. 后台运行&#xff1a;当你在ssh terminal执行shell时&#xff0c;如果网络这时断开&#xff0c;你的程序会怎样&#xff1f;TERMINATED…

实验 3 检查点和参数化实验报告--软件功能测试与性能测试实验

实验报告下载链接&#xff1a; https://download.csdn.net/download/qq_44872173/20031539 实验要求部分&#xff1a;

SNS社区

SNS&#xff0c;全称Social Networking Services&#xff0c;即社会性网络服务&#xff0c;专指旨在帮助人们建立社会性网络的互联网应用服务。1967年&#xff0c;哈佛大学的心理学教授Stanley Milgram(1933&#xff5e;1984)创立了六度分割理论&#xff0c;简单地说&#xff1…

C#中的语句

寄语接下来几篇文章&#xff0c;将和大家一起简单回顾下C#中常规的语法&#xff0c;也是平常我们在编码过程中都使用的。今天来介绍下C#中的语句。一般科班出身的程序猿们大家第一个学习的语言基本都是C语言&#xff0c;C语言里面在刚开始就介绍了语句。C#中介绍的语句和C中的基…

track文件 什么是git_Git 从入门到放弃命令大全

对于刚学 Git 的朋友来说太痛苦了&#xff0c;一堆命令&#xff0c;于是就有了这篇文章&#xff0c;对于常用的命令进行梳理。Workspace&#xff1a;工作区Index / Stage&#xff1a;暂存区Repository&#xff1a;仓库区(或本地仓库)Remote&#xff1a;远程仓库1. 初始化 在当前…

【51NOD】1201 整数划分

【题意】将n划分成不同正整数的和的方案数。 【算法】动态规划 【题解】 暴力&#xff1a;f[i][j]:只用前1..i的数字&#xff0c;总和为j的方案数 本质上是01背包&#xff0c;前i个物体&#xff0c;总质量为j的方案数 f[i][j]f[i-1][j]f[i-1][j-i] 复杂度O(n^2) 优化&#xff1…

linux c之assert函数使用总结

1、assert函数介绍 assert宏的原型定义在<assert.h>中&#xff0c;其作用是如果它的条件返回错误&#xff0c;则终止程序执行&#xff0c;原型定义&#xff1a;#include <assert.h> void assert( int expression ); assert的作用是现计算表达式 expression &#x…

Activity加载View调用顺序

2019独角兽企业重金招聘Python工程师标准>>> 在Activity的onCreate方法中&#xff0c;可以通过setContentView()方法来设置此Activity要显示的界面。在xml中的布局文件需要先解析成View树才能加载显示&#xff0c;通过View的onMeasure,onLayout,onDraw方法完成View的…

使用 kube-bench 和 kube-hunter 对 Kubernetes 集群风险评估

点击上方蓝字关注 &#x1f446;&#x1f446;↓推荐关注↓随着 Kubernetes 越来越受欢迎&#xff0c;门槛也越来越低。但是安全问题仍然存在&#xff0c;下面介绍两个审计集群安全的开源工具。kube-benchkube-bench[1] 是一个 Go 应用程序&#xff0c;拥有 4.5k star。用于检查…