• 微软MVP手把手教你如何修改.NET Framework


    这段时间为跟踪一个Bug而焦头烂额,最后发现是.NET Framework的问题,这让人多少有些绝望。所以到微软论坛提了个帖子,希望能得到些帮助。虽然论坛智能到能够判断楼主是否是MSDN订阅用户,以便尽快解决(传说MSDN订阅用户的问题能在两天内得到回复的,当时还很得意公司为我们购买的MSDN订阅账号),但得到的回复是“Could you file a bug report for this issue through Connect?”,绝望之后的又一次寒心啊。

    看过payeasy的广告之后,便有了以下的这些内容,如何修改.NET Framework: 

    这里我们以修改Guid类为例,我们将修改这个类的内部构造,以便其始终构造值为0值(00000000-0000-0000-000000000000)的对象

    1,知道你要修改.NET Framework中的谁(dll的名称)

    这很简单, 翻翻MSDN,你应该能找到你所调用的类库是哪一个,或者使用reflector可以得到更详尽的信息。从MSDN得知,Guid类在mscorlib.dll中

    2,找到你要修改的dll,并拷贝出来,以便修改

    mscorlib.dll位于GAC中,很可惜,windows只允许按照“可远观不可亵玩"的方式静静欣赏(尽管心急如焚)


    我们现在需要将该dll在操作系统中的实际路径找出来

    2.1 下载FileMon,其用于监视文件的被访问情况,我们可以通过他,找到文件路径

    2.2  写一个小程序,让该程序去访问(引用)你需要查找路径的文件,这里也就是我们的mscorlib

            static void Main(string[] args)
    {
    Guid guid = Guid.NewGuid();
    Console.WriteLine(guid);
    Console.Read();
    }

    代码中的Guid以及Console等都会访问mscorlib.dll

    2.3 运行FileMon,让他去监视mscorlib的访问,由于我们不知道mscorlib的具体路径(废话),但我们至少知道它在C:\WINDOWS\assembly下(至少知道在系统盘下),那么我们就将这个文件夹及其所有文件一块监视吧: 

    监视文件


    2.4,运行我们的小程序,FileMon将监视到所有到C:\WINDOWS\assembly下的访问,并将包含mscorlib的高亮,双击列表中的条目,其将自动打开文件所在的文件夹:

    打开文件所在的文件夹


    OK,现在找到该dll文件了,将其拷贝出来,以供我们修改,并将其路径记录下来以备将来使用(C:\WINDOWS\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089)。另外,建议备份一下拷出来的dll。

    3,利用ildasm反编译该dll,生成中间语言(IL)文件,我们将修改该IL文件

    ildasm是.NET自带的一个反编译工具,可以再SDK中找到,但通过VS的控制台便可以使用了(具体使用方式,参考MSDN)

    VS控制台


    然后可以得到该程序集的IL文件

    得到IL文件

    它其实是一个文本文件,所以可以直接打开进行编辑,但建议使用Notepad++或 UltraEdit 文本编辑器,但打开后似乎有些让人有些崩溃,汪洋大海啊,如何找到我们需要修改的代码所在的位置呢

     

    2009-6-7 9:02:33 天天烹饪,教你制作可口一流的美食 顶部
    沉yuren生
    头像
    等级:职业侠客
    权限:普通用户
    积分:64
    金钱:198
    声望:84
    经验:84
    发帖数:84
    注册:2009年5月27日
      资料  消息 短消息 编辑 删除 引用 第2楼
     

    4,利用reflector查看所要寻找的类或方法的定义

    打开reflector,查找所要寻找的类或方法,并查看其定义,假设我们需要的是Guid.NewGuid()方法:

    打开reflector

    切换到IL视图: 

    '切换到IL视图""'


    OK,有了该IL片段,要在mscorlib.dll.il的汪洋大海中查找该方法就很简单了(Ctrl-F)

    5,修改IL代码

    在notepad++或UltraEdit中找到对应的方法。我们发现NewGuid()实际是调用其Guid(bool)方法,我们可以将其替换成默认构造函数(默认构造函数构造的guid为00000000-0000-0000-000000000000)这样一来调用NewGuid()方法时则始终返回0值了,也可以在调用Guid(bool)时传入true,我们采用后者:

      .method public hidebysig static valuetype System.Guid 
    NewGuid() cil managed
    {
    // 代码大小       7 (0x7)
        .maxstack  8
    IL_0000:  ldc.i4.0
    IL_0001:  newobj     instance void System.Guid::.ctor(bool)
    IL_0006:  ret
    // end of method Guid::NewGuid

    上面代码中的IL_0000:  ldc.i4.0 表示将0(false)作为4字节整数入栈,我们将其中的0改成1:

      .method public hidebysig static valuetype System.Guid 
    NewGuid() cil managed
    {
    // 代码大小       7 (0x7)
        .maxstack  8
    IL_0000:  ldc.i4.1
    IL_0001:  newobj     instance void System.Guid::.ctor(bool)
    IL_0006:  ret
    // end of method Guid::NewGuid

    (注意,这里的操作很简单,所以很单纯地修改了,若对于比较复杂的操作请先学习IL相关知识)
    然后保存你的修改。

    6,编译IL代码,生成新的DLL

    利用ms提供的ilasm可以将IL文件编译成dll:

    生成新的DLL


    (编译前别忘记关闭文本编辑器,比如ultraEdit会独占文件而导致无法访问)

    7,将修改后的DLL放回到GAC 

    你可能会想到按照MSDN上提到的方法就如同安装自己普通的程序集一样将其安装到GAC,大概能猜想到这是不可行的,否则”不安全了“。 或者,我们刚才不是记录了mscorlib的路径的吗,直接复制粘贴进去覆盖不就行了,也许可以,也许不可以,只所以说不可以,原因有可能有二,一是根本不让访问页不让覆盖,二是程序.net程序运行时会检查程序集版本。那么就试试看吧:
    直接访问指定的路径看来是不行的了,正如下图所示:

    检查路径


    不过没关系,我们可以通过第三方工具访问到该目录,可以通过刚才的FileMon,双击条目可以打开相应的文件目录,还有一种更常用的方便的方式是用TotalCommander,其可以方便的访问Windows的各种隐藏路径。

    '访问<aWindows的各种隐藏路径""' src="/saveimage/2009-6/7/200906070902540537.PNG" twffan="done">

    将文件拖放到对应目录便可以覆盖了.

    8, 删除程序集的本机映像(native image)

    回到刚才用FileMon监视mscorlib访问时,大家可能会发现我们的小程序直接访问的并非mscorlib.dll, 而是一个名为mscorlib.ni.dll的文件(在C:\WINDOWS\assembly\NativeImages_v2.0.50727_32\mscorlib\9adb89fa22fd5b4ce433b5aca7fb1b07\ 路径下),这是mscorlib.dll的本机映像(native image), 关心过.net优化的朋友应该会知道我们可以通过ngen来将程序集生成本机映像以提高运行速度. 那么程序将直接去访问该映像而非我们修改过的mscorlib.dll,这会导致我们的修改看不到效果。所以我们要将该映像删除。为什么是删除,而不是将修改过的mscorlib.dll利用ngen来生成一个新的映像而覆盖之? 原因很简单,大家自己想想吧。
    首先,利用ngen uninstall 命令从本机映像缓存中卸载本地映像,然后利用TotalCommander将其删除(注意,先关闭可以对所覆盖的程序集有所引用的应用程序,最好重启一下电脑,应该不用进安全模式删那么费劲)

    9,验证一下修改.NET Framework成果

        class Program
    {
    static void Main(string[] args)
    {
    Guid guid1 = Guid.NewGuid();
    Guid guid2 = Guid.NewGuid();
    Console.WriteLine("the first  GUID: {0}", guid1);
    Console.WriteLine("the second GUID: {0}", guid2);
    Console.Read();
    }
        }
    如果使用MS原版的mscorlib.dll我们将得到类似于下面的输出: 

    使用MS原版

    使用我们修改过的mscorlib.dll:

    修改过的mscorlib.dll

    (另外,值得注意的是,Visual studio对某些程序集的引用来自于C:\Program Files\Reference Assemblies 下,所以,对于某些程序集如果要对VS引用造成影响则应该覆盖C:\Program Files\Reference Assemblies下的对应文件。这里的mscorlib不需要)

  • 相关阅读:
    ajax专题
    luogu P1346 电车 最短路
    luogu P1462 通往奥格瑞玛的道路 最短路
    luogu P1328 生活大爆炸版石头剪刀布
    luogu P1315 联合权值 枚举
    luogu P1156 垃圾陷阱 背包问题
    luogu P1217 回文质数 枚举
    luogu P3650 滑雪课程设计 枚举
    luogu1209 修理牛棚 贪心
    luogu P1223 排队接水 贪心
  • 原文地址:https://www.cnblogs.com/zhangchenliang/p/2655661.html
Copyright © 2020-2023  润新知