惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

P
Proofpoint News Feed
U
Unit 42
V
Visual Studio Blog
D
DataBreaches.Net
F
Fortinet All Blogs
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
The GitHub Blog
The GitHub Blog
Y
Y Combinator Blog
月光博客
月光博客
大猫的无限游戏
大猫的无限游戏
T
The Blog of Author Tim Ferriss
GbyAI
GbyAI
博客园 - 叶小钗
Blog — PlanetScale
Blog — PlanetScale
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
MongoDB | Blog
MongoDB | Blog
The Cloudflare Blog
云风的 BLOG
云风的 BLOG
D
Docker
G
Google Developers Blog
罗磊的独立博客
博客园 - 三生石上(FineUI控件)
小众软件
小众软件
S
SegmentFault 最新的问题

博客园 - 漂泊者

开源客户关系管理系统SplendidCRM下的二次开发 SplendidCRM的个性化配置 开源CRM软件SplendidCrm的中文语言包 开源CRM的选择 开发模式的思考 双击打不开程序而是打开属性的解决方法 关闭移动硬盘或光盘的自动扫描 查询条件组件 日程排序 内嵌的主表明细显示 编译错误BC30318的解决方法 调试dnn4.0时出现的问题及解决办法 对NDoc支持.net2.0的异常分析及解决 《Visual Studio.NET Tips and Tricks》一书翻译下载 《Visual Studio.NET Tips and Tricks》第四章的翻译 《Visual Studio.NET Tips and Tricks》第三章的翻译 《Visual Studio.NET Tips and Tricks》第二章的翻译 《Visual Studio.NET Tips and Tricks》第一章的翻译 《Visual Studio.NET Tips and Tricks》目录
《Visual Studio.NET Tips and Tricks》第五章的翻译
漂泊者 · 2006-11-05 · via 博客园 - 漂泊者
 

第五章           其它.NET技巧

这章包含与.NET相关的技巧。它们中的大多数与VS.NET并没有关系。但是,我决定包含到这本书中,因为它们适用于大多数的VS.NET开发者。.NET亲手可能不熟悉这些技巧。

混淆你的.NET程序集

       当你编译.NET源代码时,这并不是被编译成机器码,而是编译成微软的中间语言(MISL)。在特定的机器上的.NET框架处理编译MISL代码成机器码的工作-叫做即时编译的过程。这说明MISL是个非常开放的格式。任何理解MISL的人都能探测,阅读和理解你的程序。

       因为你的代码并没有被编译成机器码,因此你的程序集非常容易被反编译-分析你的程序集并能中推断出你的源代码的过程。这个过程并不难,事实上,许多工具能高效地为你作这个工作:只要把你编译后的可执行的文件给工具,就会得到原始的C#VB.NET源代码。当然,所产生的源代码不同于你自己的,实际的源代码,但你确实能够阅读和理解的代码。

       为了补救这个问题,在编译代码后你需要混淆代码,混淆是改变你的源代码或中间语言代码,但并不改变整个程序的逻辑流程的过程。这涉及到对变量重命名,放几个无关的方法到一个重载的方法中,改变容易阅读的switch/case/if语句成难以阅读的goto语句等等。但是这些步骤并不能阻止反编译,只不过工具产生的源代码含义模糊,难于理解。

       VS.NET20032005本身带了第三方的混淆器叫做Dotfuscator。通过选择工具>Dotfuscator Community Edition能够运行它。

HTML代码改变后不用重新生成

       我看到Web开发者在调试过程中只因为编辑了应用的HTML部分就重新生成一个完整的Web应用。当你修改了一个.aspx文件的HTML部分时并不需要重新生成和重新开始Web应用。这包括改变Web控件的属性,即使它能非常显著地改变Web页面的输出。当你只是改变HTML时,简单地刷新浏览器并不用重新开始调试过程。变化就会立即生效。

在一个字符串通过一个字符或字符基迭代

       字符串在.NET中是非常奇异的变量类型。它们是引用类型的变量,即使它们的行为表现像值类型变量。虽然你能通过代码改变一个字符串的值,但它们仍然是不可变的(当你“改变”一个字符串时,一个新的字符串被创建)。

       关于字符串一个酷的事情就是它们经常行为表现像字符数组。这意味着你能使用简单的foreach循环通过单个字符迭代一个字符串。

       Foreach(char myChar in myString){…}

       同样,你能得到字符串中的第七个字符通过用方括号来索引它:

       char myChar=myString[6]

使用内连的字符串作为对象实例

       字符串似乎是更加深奥的,内边的字符串行为表现像对象实例。如果你一个字符串加上引号在你的编辑器中,保留在一个周期中,智能感知就会出现,允许你从同一个方法体内选择,就如同一个字符串变量一样:

       string prefixRemoved =myString.Substring(“INFORMATION”.Length)

在你的项目中增加app.config

       调用System.Configuration.ConfigurationSettings.AppSettings集合总是能够探测一个程序集的.config文件。对于Web应用,它是Web.config文件;对于Windows应用,这是MyWinodwsApp.exe.config文件。缺省状态下,VS.NET对于一个新的空Web应用会创建Web.config文件但是,对于Windows应用,你必须手工加这个文件。

       许多开发者创建一个文本文件以MyWindowsApp.exe.config命名并把它放在一个项目的输出目录。但是这是有问题的因为你必须作两次:一次对于Debug文件夹,一次对于Release文件夹。当你改变了输出程序集的名字时你也必须改变.config文件的名字。

       有一个更好的方法来管理.config文件。在你的项目上右击,从弹出的菜单上选择增加新的项目。在增加新的项目的对话框上,导航到当地项目项>工具文件夹,选择应用配置文件(对于VS.NET2005,简单地选择“app”项)。这会增加一个叫做App.config的文本文件到你的项目中(见图89)。

       注意:一些VS.NET安装在增加新项对话框上并不会显示应用配置文件。在这种情况下,你必须创建一个叫做App.config的文本文件并放到项目的根文件夹下。

89      增加一个应用配置文件

       关于配置文件的好的事情就是无论你什么时候生成项目,App.config文件会被拷贝到正确的文件夹下(DebugRelease,或你当前的可能的配置)适当地重命名(“MyWindowsApp.exe.config”)。

       注意:App.config只能应用于主程序集,并不能应用于类库DLLs

使用中间语言反编译器探视一个.NET程序集

       VS.NET安装过程中,你同样能选择安装.NET框架SDKSDK包含了许多有用的工具。其中一个就是中间语言反编译器(ildasm.exe),通常位于VS.NET的子目录中:

       VS.NET2002:C:\Program Files\Microsoft Visual Studio.NET\FrameworkSDK\Bin

       VS.NET2003: C:\Program Files\Microsoft Visual Studio.NET2003\SDK\v1.1\Bin

       VS.NET2005: C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin

       中间语言反编译器允许你打开和探测一个.NET程序集(见图90)。你能看到类中所有的命名空间和类,并能读到微软的中间语言代码。读MSIL代码是非常有用的,如果代码有性能问题需要你调整你的应用时。

90      使用ILDASM探测一个.NET程序集

       ILDASM工具对于探测编译器生成给定的程序集时使用的.NET框架版本时也是有用的。看一个程序集的manifest段能看到它引用的系统程序集的版本。一个版本号1:0:5000:0意味着它是用.NET框架1.0编译的,一个版本号1:0:3300:0指示它是用1.1版本编译的。并不惊奇,.NET框架2.0有一个以“2:0开头的版本号。

使用Windows类查看器反射一个类

       在和ILDASM工具在.NET框架SDK中同样的目录中你将发现另一个有用的工具叫做Windows类查看器(WinCV.exe)。这个程序担当一个快速搜索任何定义在.NET框架中的.NET类功能。使用类的一部分名字来搜索一个类,会列出所有可能匹配的类。搜索是相当快的,通过敲入更多地的字母结果会自动更新缩减你的搜索。

       一旦你选择了一个类,你将会看到C++头文件一样的信息,包括所有的构造体,方法,属性,事件,和别的成员域(见图91)。

91      WinCV.exe显示一个类的所有成员域

       注意:VS.NET2005提供给你非常类似的东西,当使用类定义视图时。

运行aspnet_regiis修补一个IIS安装

       当安装VS.NETVS.NET框架SDK到一个你想用来开发Web应用新的机器上时,最好的规则就是首先安装IIS,因为.NET安装会安装和注册必需的ASP.NET ISAIP扩展DLL。如果你在安装了.NET后安装IISIIS将不会正确地和ASP.NET一块工作。

       代替重新安装.NET,你能使用一个非常有用的和.NET框架SDK捆绑在一起的工具,在.NET框架目录(类型的是C:\Windows\Microsoft.NET\Framework\v1.1.4322,或你正在运行的.NET的版本号)有一个小的命令行工具,叫做aspnet-regiis.exe

       像下面一样运行这个工具能够重新安装.NETIIS的部分:

       Aspnet_regiis –i

       注意:这个技巧并不仅仅是“对.NET配置IIS”特性;当ASP.NET不能在你的机器上工作时,使用它来“修补”IIS

       如果你只是丢失了ASP.NET使用的客户端脚本文件(JavaScript文件,经常发现在/aspnet_client/system_web/version文件夹),只需运行这个工具如下:

       Aspnet_regiis –c

       最后,这个工具对于使ASP.NETIIS6下工作是有用的。如你所知的,Windows 2003服务器版缺省状态下ASP.NET并不能工作。通过选择IIS>扩展你能使ASP.NET工作,但如果你需要通过脚本让它工作,只需运行工具如下:

       Aspnet_regiis -enabled

预编译你的ASP.NET Web应用

       无论什么时候你使用VS.NET编译你的Web应用,所有它作的就是编译你的代码后置类到程序集中。对首次访问即时编译的Web站点时,你将发现ASP.NET引擎同样要经历它的编译器,这会引起的非常显著的初始延缓。.NET框架2.0安装提供给你几个有用的工具来执行这个ASP.NET编译。

       到虚拟的URLhttp://localhost/MyWebApplication/precompile.axd。如同你在第三章“通过Tarce.axd调试你的ASP.NET Web应用”中你遇到的trace.axd HTTP处理体一样,这个虚拟的URL也被实现使用一个HTTP处理体。处理体遍历你的整个Web应用并预编译所有的页面以避免这个初始延缓。所以在发布你的Web站点后,记住运行这个HTTP处理体。

       你也能使用新的aspnet-compiler.exe工具自动化完整的编译。它定位于.NET框架2.0目录(c:\Windows\Microsoft.NET\Framework\v2.0.*)。

       运行这个工具如下:

       Aspnet_compiler –v /MyWebApplication

       这个命令编译你的整个Web应用(VS.NET使用同样的过程)并预编译Web应用,所以当你首次访问你的Web站点时并不会经历初始延缓。

Web应用设置ASP.NET版本

       缺省状态下,ASP.NET Web应用总是使用给定机器上可用的最新的.NET框架版本(对于Windows应用正好相反,它总是试图使用它被编译时使用的.NET框架版本)。问题是在你安装了.NET框架2.0以后,你的所有的Web应用会使用.NET框架2.0版本,可能这并不是你相要的。

       .NET框架2.0安装会在IIS的虚拟目录的属性对话框上增加一新的Tab页。简单地到IIS,右击你的虚拟目录,从弹出的菜单上选择属性。在ASP.NET Tab页上现在你能设置你的Web应用运行时所需要的版本(见图92)。

92      IIS上对你的Web应用设置ASP.NET版本

手工清除程序集缓冲

       当嵌有Windows窗体应用的Web页面运行时,应用首先下载到你的计算机上,缓冲接着从缓冲处运行。在嵌在页面上的应用运行时(像Javaapplets),代码总是从你的当地的计算机上运行(当然,需要所有必需的高安全级的设置)。当原作者决定更新应用时,一个有新的版本号的生成版本会强迫IE下载新的版本。

       有时,你想强迫刷新下载一个新的Windows窗体应用。这典型发生在开发人员的计算机上,缓冲阻碍特定类型的Web应用的日常开发。清除临时的Internet文件夹并没有多大用处。相反,你需要手工清除下载的程序集缓冲,它一般处于C:\Windows\Assembly\Download下。作这个工作需要运行.NET工具叫做gacutil.exe,你能从C:\Windows\Microsfot.NET\Framework\v1.0.3705目录下找到。

       运行这个工具如下:

       Gacutil.exe -cdl

对字符串,标签和内连的.NET代码使用Unicode编码

       .NET框架是完全兼容Unicode编码。.NET中的字符串是Unicode字符串,对于处理Unicode编码的字符串并不需要特殊的工作。但更多的是VS.NET不但能让一个字符串拥有Unicode编码的值,而且它本身也完全支持Unicode

       我开发了几个越南的应用。开发者经常问我用越南字符如何显示一个Windows窗体应用或如何存储越南字符到数据库中。事实上你我并作什么特殊处理,它就能工作。

       VS.NET编辑器中设计我的Windows窗体应用时,我简单地转向语言工具(例如Windows的全局输入方法编辑器或第三方的工具如VPSKeys)接着用Unicode字符设置按钮和标签的值。

       因为VS.NET中的编辑器是Unicode兼容的,我能以Unicode编码输入字符串,通过选择文件>高级保存选项我能以Unicode编码兼容的格式(Unicode,UTF-8,和其它的)保存我的.cs/.vb文件。

       为了使事情更令人注目,我甚至使用Unicode编码于实际的代码。这种方式,代码的注释,区域标签,变量名称,类名称,甚至方法名称都能包含Unicode字符(见图93)。

93      在符号名称,字符串,注释等中使用Unicode编码

重新抛出同一个异常

       当一个异常需要记录时,开发者倾向使用类似下面的代码来记录一个异常,但并不吞没异常:

Try

{…}

catch(Exception ex)

{

Log(ex);

Throw ex;

}

       这段代码执行后异常并没有被吞没,因为在结尾处被重新抛出。但是,开发者并没有意识到以这种方式重新抛出异常会引发.NET清除异常的堆栈跟踪。当你探测异常的堆栈跟踪属性时,似乎在catch块中异常是第一次被抛出。

       为了正确地在一个catch块中抛出同样的异常,简单地使用“throw;”如下:

Try

{…}

catch(Exception ex)

{

Log(ex);

Throw;

}

       它会重新抛出同样的异常,并不会清除堆栈跟踪。