[你必须知道的.NET]第三十五回,判断dll是debug还是release,这是个问题
问题的提出
晚上翻着群里的聊天,发现一个有趣的问题:如何通过编码方式来判断一个dll或者exe为debug build还是release build?由于没有太多的讨论,所以我只好自己找点儿办法,试图解决这个问题,为夜生活带点刺激。于是,便有了本文的探索和分析。
当然,为了充分的调动起大家的主意,省去不必要的google操作,我觉得有必要对Debug和Release两种模式的异同进行一点提纲挈领式的分析,从而为接下来的解决方案打好基础。
Debug & Release
我们应用Visual Studio对代码文件进行F5操作(Build)时,实际是发生了一系列语法检查、词法检查和编译过程,通常情况下我们有两种Build模式,这就是常说的Debug Build和Release Build。望文知意,Debug Build模式通常应用于开发时,便于调试反馈;而Release Build则应用于部署时,这是因为Release模式下,编译器做了很多的优化操作(代码冗余、循环优化等),省去了对调试信息的记录。因此,两种Build模式是各不相同的,我们对其二者进行一点总结如下:
- Debug用于开发时,Release用于部署时。
- Debug模式下,将产生pdb文件,用于保存状态信息和调试信息;Release模式下,不产生调试信息,也没有pdb文件。
- Debug模式下,System.Diagnostics.Debug.Write(或WriteLine)可以向跟踪窗口(Output)输出跟踪信息;而Release模式下,System.Diagnostics.Debug.WriteLine将被忽略。不过,可以考虑System.Diagnostics.Trace.Write,其人缘较好,对Debug和Release左右通吃,都可输出调试信息。
- Debug模式下,#define DEBUG将作为默认预定义常量,参与编译过程;而在Release模式下,该预编译将被省略。例如如果执行:
#if DEBUGConsole.WriteLine("Hi");#endif
在Debug模式下,Console.WriteLine(“Hi”)将参与编译,而Release模式下,会忽略该语句的执行。不过,如果你手动添加
#define DEBUG
在两种模式下,都会执行Console.WriteLine(“Hi”)的编译。究其原因,是Visual Studio在默认情况下预定义了#define DEBUG,我们可以通过开关来设置:
关于预编译指令可详查《你必须知道的.NET》的相关章节。
解决方案
既然对Debug Build和Release Build有个基本的了解,那么也由此可以推断我们解决开篇问题的依据。在.NET中以DebuggableAttribute来控制CLR如何处理模块代码规则,而属性IsJITTrackingEnabled属性来标识运行库在代码生成过程中是否跟踪调试信息的标识,如果IsJITTrackingEnabled为true,表示运行库跟踪调试信息,可推断为Debug Build模式;如果IsJITTrackingEnabled为false,表示运行库没有跟踪调试信息,可推为Release Build模式。所以,解决的方案,最终着眼于对IsJITTrackingEnabled信息的获取上,可想而知,最简单的办法莫过于神兵利器——反射。
那么,我们开始吧。
构建
首先我们创建一个AnyContext来承载通用的上下文服务,在这里主要包含的就是:
/// <summary> /// A common context /// </summary> /// <remarks> /// Anytao, http://www.anytao.com /// </remarks> public class AnyContext : IAnyObject {public static DebugMode GetDebugMode(string assemblyName){ } } 其中,DebugMode是一个简单的枚举:
/// <summary> /// Debug mode type /// </summary> /// <remarks> /// Anytao, http://www.anytao.com /// </remarks> public enum DebugMode {Debug,Release }
可向而知,我们需要实现一个根据Assembly信息获取DebuggrableAttribute的Helper类,既然是Helper类我们希望能够兼顾各种情况,因此通过泛型方法是做好的选择,具体实现如下:
/// <summary> /// Common helper /// </summary> /// <remarks> /// Anytao, http://www.anytao.com /// </remarks> public static class Utils {/// <summary>/// Get GetCustomAttribute/// </summary>/// <typeparam name="T">CustomAttribute Type</typeparam>/// <param name="provider"></param>/// <returns></returns>public static T GetCustomAttribute<T>(this ICustomAttributeProvider provider)where T : Attribute{var attributes = provider.GetCustomAttributes(typeof(T), false);return attributes.Length > 0 ? attributes[0] as T : default(T);} }
此处的GetCustomAttribute被实现为扩展方法,那么任何实现了ICustomAttributeProvider接口的类型,都可以通过其获取CustomAttribute了,例如:Type、Assembly、Module、MethodInfo,都可以实现对GetCustomAttribute的调用。
接下来,GetDebugMode的逻辑就变得很简单,我们传入assembly路径即可获取DebuggrableAttribute,并由此推导IsJITTrackingEnabled的情况:
public static DebugMode GetDebugMode(string assemblyName) {if (string.IsNullOrEmpty(assemblyName)){throw new ArgumentNullException("assemblyName");}DebugMode ret = DebugMode.Debug;try{// Get assebly by nameAssembly ass = Assembly.LoadFile(assemblyName);// Get DebuggableAttribute infoDebuggableAttribute att = ass.GetCustomAttribute<DebuggableAttribute>();ret = att.IsJITTrackingEnabled ? DebugMode.Debug : DebugMode.Release;}catch (Exception){throw;}return ret; } 好了,这就是一个简单的判断逻辑,在AnyContext中包含了很多诸如此类的上下文定义,而GetDebugMode提供了本文开头的解决方案。
测试
- 新建两个project,并分别以Debug模式和Release模式编译,生成对应的exe(或dll):
- debugass.exe
- releaseass.exe
- 新建TestProject,并对GetDebugMode进行测试如下:
[TestClass] public class AnyContextTest {[TestMethod]public void TestIsDebugOrRelease(){// Arrangestring ass1 = @"D:\debugass.exe";string ass2 = @"D:\releaseass.exe";// Act string mode1 = AnyContext.GetDebugMode(ass1).ToString();string mode2 = AnyContext.GetDebugMode(ass2).ToString();// AssetAssert.AreEqual(mode1, "Debug");Assert.AreEqual(mode2, "Release");} }
一切OK,你不妨试试。
注:本测试在.NET 2.0及其以上版本测试通过,如您有更多精力,可对其以下版本进行分析。
参考文献:
- ms-help://MS.MSDNQTR.v90.chs/fxref_mscorlib/html/9f109812-3c14-dcb2-9aff-e18e20dc33ff.htm
- http://blogs.msdn.com/jb/archive/2006/06/14/631469.aspx
[你必须知道的.NET]第三十五回,判断dll是debug还是release,这是个问题相关推荐
- [你必须知道的.NET]第三十四回,object成员,不见了!
在.NET世界了,object是公认的造物主,其麾下的7大成员,个顶个的横行在任何系统的任何代码角落. public class Object {public Object();public virt ...
- [你必须知道的.NET]第三十二回,,深入.NET 4.0之,Tuple一二
anytao.net | <你必须知道的.NET>网站 | Anytao技术博客 发布日期:2009.06.01 作者:Anytao © 2009 Anytao.com ,Anytao原 ...
- [你必须知道的.NET]第三十回:.NET十年(下)
引言 语言是程序开发者行走江湖的手上利器,各大门派的高手在论坛.博客为了自家门派争吵不已早是技术世界中的亮丽风景,虽多少为刚刚踏入江湖的新手提供了思考的素材,但也同时迷惑了初出茅庐的前行方向. 本文不 ...
- [你必须知道的.NET]第三十一回,深入.NET 4.0之,从“新”展望
总体来说,这是一篇介绍性的文章,不会涉及过多技术细节和研究过程.但是,作为拉开序幕的第一页,本文以提纲挈领的方式展开对.NET 4.0的初次体验.从What's new的角度,开始我对.NET 4.0 ...
- [你必须知道的.NET]第三十三回,深入.NET 4.0之,LazyT点滴
对象的创建方式,始终代表了软件工业的生产力方向,代表了先进软件技术发展的方向,也代表了广大程序开发者的集体智慧.以new的方式创建,通过工厂方法,利用IoC容器,都以不同的方式实现了活生生实例成员的创 ...
- [你必须知道的.NET] 第三回:历史纠葛:特性和属性
本文将介绍以下内容: • 定制特性的基本概念和用法 • 属性与特性的区别比较 • 反射的简单介绍 1. 引言 attribute是.NET框架引入的有一技术亮点,因此我们有必要花点时间来了解本文的内容 ...
- [导入][你必须知道的.NET] 第三回:历史纠葛:特性和属性
摘要: 博客园中,关于attribute的讨论不是很多,所以本文也有了存在的意义.attribute是.NET框架引入的有一技术亮点,因此我们有必要花点时间来了解本文的内容,走进一个发现attribu ...
- 艾伟:[你必须知道的.NET] 开篇有益
本系列文章导航 [你必须知道的.NET] 开篇有益 [你必须知道的.NET] 第一回:恩怨情仇:is和as [你必须知道的.NET] 第二回:对抽象编程:接口和抽象类 [你必须知道的.NET] 第三回 ...
- [你必须知道的.NET]第十四回:认识IL代码---从开始到现在
本文将介绍以下内容: · IL代码分析方法 · IL命令解析 · .NET学习方法论 1. 引言 自从『你必须知道.NET』系列开篇以来,受到大家很多的关注和支持, ...
最新文章
- thrift框架使用C++
- Linux下安装Oracle参数自动初始化脚本
- pandas 增加行、列
- 【alibaba-cloud】SpringCloud和SpringCloud对比
- python爬虫 -- 正则表达式 与 Re模块的介绍
- wxWidgets:wxTrackable类用法
- python学习教程(链接)
- 设有n 个程序{1,2,…, n }要存放在长度为L的磁带上。程序i存放在磁带上的长度是Li, 1<= i<= n。这n 个程序的读取概率分别是p1,p2,...,pn,且pi+p2+...+pn =
- Error:java: 无效的目标发行版: 11解决方案
- 了解Java中的可克隆接口
- 安装mysql5 1步骤_Linux系统安装MySQL详细步骤(mysql-5.1等)
- Python教学与学习过程中应注意的九句话
- sonarqube汉化
- 解决ichat模块调用过程中——登录微信网页版失败的方法
- GIS应用技巧之空间插值
- 录像机人机界面蓝屏怎么处理
- torch.optim的一些方法
- 解决KETTLE9 连接MYSQL 8 Error connecting to database: (using class org.gjt.mm.mysql.Driver)
- revit二开之过滤族(Family)
- Docker专题(六)-Docker镜像详解
热门文章
- 在vue中操作DOM--this.$nextTick()
- java- WatchService监控
- hdu4353 Finding Mine三角形内的点数
- 修改Fiddler实用插件JsonViewer
- Response.Redirect(),Server.Transfer(),Server.Execute()的区别
- php 强制刷新一次,强制浏览器使用PHP刷新所有内容
- okhttp3 请求html页面,OkHttp3源码详解(二) 整体流程
- java面向对象程序设计董小园_java面向对象程序设计(董小园版).doc
- boot返回码规范 spring_sprigboot-new-coding-standards
- python股票交易模型_如何用Python建模GGM模型并对股票估值?