.NET 4.0新功能:Mscoree.dll + Mscoreei.dll=更少的Reboot (上)

一次Reboot=975

在开始本文之前先做一个小调查:有多少朋友喜欢Reboot?答案A:我喜欢,每天都要Reboot N次。答案B:我不喜欢,最好一个星期都不要Reboot。如果没有意外的话,相信大部分人都可以归到B那一类,毕竟很少人会愿意中断自己所做的事情,把正在编辑的文章、代码等等一一存盘,然后重新启动,等待几分钟,再重新打开文档、代码编辑的。

不过,很遗憾的是,新版本的.NET的安装在Vista以及以上(以后用Vista+表示)操作系统中安装通常是需要重新启动的,2003,XP或者以下则是不需要的。看到这里可能有些朋友会很奇怪:为什么XP不用重启,Vista反而要重启呢?这不是变差了吗?谈这个问题,必须要从Mscoree.dll谈起。大部分使用.NET编程的朋友可能并不熟悉mscoree.dll,但是,实际上mscoree.dll可以说是.NET/CLR中最为核心的一个部件之一,没有Mscoree,CLR根本无从加载。当你在执行一个.NET得EXE的时候,最先加载的不是CLR的DLL(mscorwks.dll),而是这个Mscoree.dll。详情可以参见我之前写过的一篇文章: .NET中的幕后英雄: MSCOREE.DLL

因为Mscoree.dll是.NET一个核心的组成部分,可想而知,每次在安装新版本的.NET的时候,Mscoree.dll都会被更新,以加入新功能或者Bug Fix。更新的时候所面临的主要问题是:如果Mscoree.dll正在被使用,如何更新mscoree.dll?在Vista之前,也就是2003,XP,乃至之前的操作系统中,安装程序(Admin也可以)可以直接重命名mscoree.dll(这个操作即使mscoree.dll正在被使用也可以成功),然后再copy新的mscoree.dll到系统目录即可。但是,在Windows Vista+,Mscoree.dll被认为是Windows的核心组成部分之一,并且由WRP(Windows Resource Protection)所保护。如果要更新,必须得通过一种叫做CBS(Component Based Servicing)的机制加以更新(注:我对这些安装相关的技术并不太熟悉,如果细节描述上有错误欢迎指正)。这种机制虽然更加安全、健壮,但是也多了一项限制:如果Mscoree.dll正在被使用,系统必须重启才可以完成对Mscoree.dll的更新。换句话说,在Windows Vista+,安装3.5,4.0,5.0,6.0,…的.NET每一次都得要重启。比如有1亿用户安装了NET 4.0而需要重启,假定重启一次需要5分钟(包括存盘等准备工作),那么这个重启动作就浪费了所有人500000000分钟=975年!!!如果考虑到每个.NET版本的安装都要这么来一次,那么总的时间浪费可以说是天文数字!这也许有点危言耸听,但是无论如何,有一件事情是清晰的:对于像.NET这种用户群比较广泛的程序平台而言(注意我说的是.NET,不是SDK也不是VS,.NET是一个运行时、虚拟机,是最终用户所运行程序使用的),任何一个微小的细节可能都有着巨大的影响。虽然.NET用户群尚未达到这种规模,我们也不希望因为这个问题影响.NET的普及率。

.NET 4.0的解决方案

我们的目标是希望减少重启的次数。这里谈到的重启是为了修改MSCOREE.dll而导致的重启。为了解决这个问题,我们可以先从DLL的本质入手。DLL是Windows的一种代码共享机制,这种共享是通过DLL输出函数、然后其他EXE/DLL来直接调用DLL所输出的函数来实现的。换句话说,一个DLL对于外部而言,最重要的是这个DLL的输出函数,包括其接口和功能。每次对DLL的修改,无非是接口的变化和功能的变化。接口的变化由于兼容性的要求,一般不会减少或者修改,而是增加。功能上,通常变化不会太大,一般是Bug Fix,同样,也是因为兼容性的要求。当然了,新的接口的新功能除外。那么有没有一种方法,可以自由修改MSCOREE.dll的功能和接口,而又不需要修改MSCOREE.dll的内容呢?听上去这似乎是不可能完成的任务,但是仔细思考一下,不难意识到:如果我们将MSCOREE.DLL的代码重新定位到另外一个DLL,这个DLL不受Windows约束,可以自由修改,那么问题是不是就解决了呢?答案是肯定的,这就是MSCOREEI.dll的由来。当然了,具体的细节要比这里讨论的复杂不少,这一次我就谈到这里,欢迎各位朋友参与讨论MSCOREE和MSCOREEI是如何共同作用的。因为现在这个相关项目还没有完全结束,现在暂时我还不能完全透露所有细节,在合适的时间内,我将发布本次文章的续集,并为大家公布答案。