dotnet学习笔记二 - 运行.net程序的秘密

.NET Framework学习总结 专栏收录该内容
5 篇文章 0 订阅

.NET Framework给我们提供了良好的开发平台。有很好的类库,可以跨语言,跨平台等等。但是他的内部实现细节是怎样的呢?.NET编译出来的exe文件并不是机器码,它是怎样和CLR结合起来的呢?下面就让我们揭开这个小秘密。

首先做一个简单的.NET应用,把它编译成EXE文件。然后用Visual Studio 6.0带的工具Depends把它打开。如下图:

这里可以看到一个很奇怪的现象,我的.net应用程序只直接依赖于一个dll – MSCOREE.DLL。而且这个DLL输出的这么多函数中也只用到了一个_CorExeMain。我的这个APPENDLINE.EXE中还用到了自己做的一个.NET组件,在这里也看不到。

再让我们借助一些PE察看工具来分析一下这个EXE文件。这一步得到的结果是什么呢?在这个PE文件的入口函数上可以看到一条唯一的汇编语句:

JMP  DS:_CorExeMain

经过上面的步骤,我们可以明确的断定所有的.net编译后的EXE文件一旦运行,就执行MSCOREE.DLL输出的一个函数_CorExeMain。而在开发过程中我们使用到的一些外部组件、控件由于是被.net编译器编译成了中间代码,在Depends中是无法看到的,所有使用外部组件的过程全部由CLR处理。

幸运的是微软这次公布了一个CLI实现的代码,我们可以看个究竟。我下载的代码中没有找到_CorExeMain,只找到了一个_CorExeMain2。参数有5个:

PBYTE   pUnmappedPE,                // -> memory mapped code

    DWORD   cUnmappedPE,                // Size of memory mapped code

    LPWSTR  pImageNameIn,               // -> Executable Name

    LPWSTR  pLoadersFileName,           // -> Loaders Name

    LPWSTR  pCmdLine

一目了然,pUnmappedPEcUnmappedPE就是.net编译后的中间代码的内存缓冲和长度。pImageNameIn就是这个EXE的名字,pLoadersFileName是载入者的名字,pCmdLine就是命令参数。有了这几个参数我们就可以猜到.net将中间代码编译后放入到PE文件中,再加入一段代码直接执行MSCOREE.DLL_CorExeMain,参数就是中间代码的内存指针。JIT就把这段中间代码编译成机器代码执行。

_CorExeMain2代码不长,简单总结一些,做了如下的5步工作:

1.         验证签名。

2.         初始化CLR环境

3.         创建了一个代表EXE文件的PEFile对象

4.         使用SystemDomain的静态方法执行这个PEFile

5.         执行后,做一些清除工作,退出。

 

很明显,上面5个步骤里最重要,最关键的就是第4步了,究竟做了什么呢?有兴趣的朋友可以去看微软的CLI代码,我在以后的文章中也会进一步分析。

  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

技术基础 New Folder 多样式星期名字转换 [Design, C#] .NET关于string转换一个小Bug Regular Expressions 完整.net后台执行javascript脚本集合 ASP.NET正则表达式 常用匹配正则表达式和实例 经典正则表达式 delegate vs. event 我是谁?[C#] 表达式计算引擎 正式发布表达式计算引擎WfcExp V0.9(附源码) 运算表达式类原理及其实现 #实现18位身份证格式验证算法 身份证15To18 算法(C#) 一组 正则表达式 静态构造函数 忽略大小写Replace效率瓶颈IndexOf 随机排列算法 理解C#中委托[翻译] 利用委托机制处理.NET异常 与正则表达式相关几个小工具 你真了解.NETString吗? .NET方法及其调用(一) 如何判断ArrayList,Hashtable,SortedList 这类对象是否相等 帮助解决网页和JS文件中中文编码问题工具 慎用const关键字 装箱,拆箱以及反射 动态调用对象属性和方法——性能和灵活性兼备方法 消除由try/catch语句带来warning 微软应试题完整版(附答案) 一个时间转换问题,顺便谈谈搜索技巧 .net正则表达式使用高级技巧 (一) C#静态成员和方法学习小结 C#中结构与类区别 C#中 const 和 readonly 区别 利用自定义属性,定义枚举值详细文本 Web标准和ASP.NET - 第一部分 XHTML介绍 在ASP.NET页面中推荐使用覆写(Override)而不是事件处理(Event Handler) 常用编码工具类,支持base64,md5,des,crc32 也谈谈技术面试 在C#里把ArrayList转换为Array 或 把Array转换为ArrayList C# 2.0 在.NET 2.0中,让你组件也可以绑定 .NET20 一种简单窗口控件UI状态控制方法 翻译MSDN文章 —— 泛型FAQ:最佳实践 Visual C# 3.0 新特性概览 C# 2.0会给我们带来什么 泛型技巧系列:如何提供类型参数之间转换 C#2.0 - Object Pool 简单实现 Attributes in C# 手痒痒,也来个c# 2.0 object pool 泛型技巧系列:用泛型打造可复用抽象工厂 体验.net2.0优雅(四):Provider、策略、控制反转和依赖注入 泛型最佳实践 asp.net 2.0下嵌套masterpage页可视化编辑 C# 2.0与泛型 动态调用对象属性和方法——性能和灵活性兼备方法 泛型技巧系列:用泛型打造可复用抽象工厂 泛型技巧系列:如何提供类型参数之间转换 .NET 2.0 泛型Quiz Visual Studio 2005体验泛型编程 C++ 泛型编程系列讲座之实施 泛型技巧系列:简单类型选择器 C# 泛型简介 我眼中C#2.0新功能特性 泛型技巧系列:避免基类及接口约束 New Article 不该用Generics实现Abstract Factory理由 C#2.0-泛型 C#2.0-extern C#2.0-可空类型 C#2.0-分部类 C#2.0-迭代器 C#2.0 新增功能学习 泛型序列化问题 .NET 2.0 泛型在实际开发中一次小应用 C#2.0 Singleton 实现 .Net Framwork 强类型设计实践 通过反射调用類方法,屬性,字段,索引器(2種方法) ASP.NET: State Server Gems 完整动态加载/卸载程序解决方案 从NUnit中理解.NET自定义属性应用(转载) 如何在.NET中实现脚本引擎 (CodeDom篇) .NET插件机制简单实现 我对J2EE和.NET一点理解 难分难舍DSO(一) InternalsVisibleToAttribute,友元程序集访问属性 Essential .NET 读书笔记 [第一部分] NET FrameWorkCollections支持 .NET反射在软件设计上应用 关于跨程序反射 实现C#和VB.net之间相互转换 深入剖析ASP.NET组件设计]一书第三章关于ASP.NET运行原理讲述补白 asp.net 运行机制初探(httpModule加载) 利用反射来查看对象中私有变量 关于反射中创建类型实例两种方法 ASP.Net应用程序多进程模型 NET委托:一个C#睡前故事 [推荐] - [原创] Microsoft .NET策略及框架概述 卸载Class? Web Form 窗体 如何实现web页面
相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值