看完点推荐,推荐数目超过100,打包脚本+工具+运行时 所有分享哈。。。。。(无公司争议,请放心)html
接上一篇前端
【.Net Framework 体积大?】不安装.net framework 也能运行!?开篇叙述-1node
下一篇编程
【.Net Framework 体积大?】不安装.net framework 也能运行!?原理补充-3小程序
昨天写了一个引子,仍是有读者对这套“小把戏”感兴趣。那么不辜负你们的但愿,争取博主不作太监........设计模式
注意:笔者不想谈Link的方式,虽然很爽,可是不靠谱。毕竟解析翻译到原生的应用,微软到如今也就敢在Xaml系的应用作尝试,不知道是微软的策略,仍是自身都信心不大......api
至于Mono项目,笔者就不说它了,BUG真的多的一个接一个的,甚至2.0都过去了,3.0尚未修复。虽然它能够支持Link ,mkbundle 工具,可是bug太多,不当心就是一个雷......服务器
开篇先谈下原生的应用和虚机应用。架构
Native的程序,大多基于特定的平台硬件系统的,这里的系统 咱们就说三大主流系统中的Win/Mac/Linux。硬件部分嘛,主要是CPU的类型...原生应用跟随操做系统的兼容性,能够相似插入内存条同样,直接跟系统集成,运行速度快,处理数据速度效率高。开发语言:C/C++ 汇编?(呵呵,这都上个世纪的东东) 。基于C/C++ 衍生出来 主流的 QT VC .....VC 里有衍生出个MFC。。。。。。。app
虚机应用,这类应用大可能是基于虚机运行时,也就是将运行时 Run time SDK 安装到适配的操做系统后,SDK将硬件 操做系统的不一样 进行了自适应。应用开发者,只须要关注程序的运行效果。就好像坑坑哇哇的石头墙,摸了一层水泥,而后上面能够搭载各类形状的石头,而不是特定形状的石头(去适应石头缝大小形状)。特色是:平台适应强 开发速度快 迭代周期缩短...。开发语言:Python Java .net Framework node.js .......
虚机应用,又各自有各自的特定。有的是基于脚本执行,有的是强类型的编译执行。不过大同小异。都离不开运行时!!!
其余语言的运行时,咱们不谈,有兴趣,本身研究。咱们专门谈一下.net 的运行时 .net Framework.
特色:微软开发,大品牌。体积大,不能说大,简直是巨大!前面说了,从2.0 的几十兆 到3.5的几百兆 到4.0又回到几十兆(可是安装速度真慢的要命,由于要先自解压)。前面说了,十分佩服微软的 cab 压缩,愣是把一个几百兆的.net 4.0 压缩到了几十兆!!!4.5 4.6也都是4系列的。主版本号不变,改变次版本号,说明只是基于4的补丁,可是要亲命的是 4.5 抛弃了XP!!!!XP 啊,提到XP 就好像前端开发者对着IE6那个时代!!! 虽然痛苦恐怖,可是,XP在国内的使用群体依然大的离谱。
虽然 Win7普及的效果不错,可是那毕竟是XP 啊 XP 啊 ............泪奔。
因此,笔者认为 .net 4到目前为止 是兼容最全面的Win 系列的系统。对于开发者来讲 4版本无疑是一个划时代的东东,各类应用框架都有,并且性能比3.5好,并且体积小了好多。可是仅仅是相对小了。笔者认为,它依然巨大。相比较 Python Ruby Node.js Lua的运行时,都小巧,安装速度快,运行速度也能够。凭啥.net 这个鬼 体积那么大!??
实际上是有缘由的。如图:
C:\WINDOWS\Microsoft.NET
这个基本就是.net 的运行时集中营了(虽然在System目录也打入了其余的dll,后面说)
看到这里,咱们就须要回忆下,.net 的自身的架构
2.0
3.5
4.0
上图来自:http://www.cnblogs.com/xiaopin/archive/2011/01/07/1929467.html
是否是相似搭积木的方式,一块块的耦合上去的?确实,一个完整的.net framework安装包,须要把整个积木架构搭建起来。可是大多数状况下,咱们只须要积木的台子,也就是到 第一个图中的程序集那一层就完事,有GAC 有运行时 ,就足够咱们把程序集经过系统引导到 CLR 运行时解析 IL 中间语言到当前平台的原生代码,并执行原生代码。至关于,咱们只须要雇佣一个翻译,会翻译其余语言便可,不必长得高大威猛帅。。。。
那么咱们能把上面的枝枝叶叶修建掉么?笔者测试是能够的。
咱们只须要把GAC 的相关程序集,还有运行时便可。而后就是特定的引导目录+注册表。
笔者没有找到.net 程序引导的顺序,不过从笔者实验的结果来看。微软打包的程序的时候,给程序集打上了特殊的标识。而后由系统注册表注册的特定应用去解析程序集。相似指定默认程序同样的效果(不知道表述是否正确,欢迎你们指正)。
好,既然是指定的注册表来注册引导程序,那么哪一个才是The One? 不卖关子,直接给答案!
注册表:SOFTWARE\Microsoft\.NETFramework\
这个注册表项,有一个安装路径的项,指定到.net的运行时目录。笔者的机器是64位机器,x86的机器就没有64.
而后,注册完路径后,还有它下面的一个注册表键值对:policy
注意其中的键值对:
这个支持策略,相似设计模式中的策略模式。根据特定的场景,使用特定的策略支撑。咱们注册4.0后,天然也就支持.net 4.0。
好,注册表关键就这2个,接下来还有关键的一个步骤,在系统目录
一个是箭头指向的dll 还有一个
100那个是4.0的 120那个是笔者安装了 VC 分布包的 VC++2013的。咱们须要的是上面的那个哈。。。
好,把这两个程序集 在特定的机器上,也打入进去后,好,咱们的精简版本的.net framework就完成了!!
而后,还能够在运行时程序集 目录下,裁剪不须要的程序集 好比什么 exe的小工具啊 WCF 啊 WPF啊什么的。最终就能够粗来一个体积小巧,性能不错,支持.net 4.0的运行时了。
也就是上面的3步走,有兴趣本身尝试,有疑问,请评论留言。笔者不会发布完整的小安装包。版权的问题很蛋痛 呵呵,Congratulations..............
啰嗦一下,为何添加注册表就能访问策略进行引导,跟.net的历史有关系吧,由于XP系统上面,就已经集成了1.X的.net framework.后续系统Vista win7 server03 08 等等也同样。因此,注册个版本号,也就能够识别粗来了。。。。。
注册表献上:
Root: HKLM; Subkey: "SOFTWARE\Microsoft\.NETFramework";Permissions:admins-full; ValueType: string; ValueName: "InstallRoot"; ValueData: "{win}\Microsoft.NET\Framework\";Check:WebServerRuntimeNotInstall
Root: HKLM; Subkey: "SOFTWARE\Microsoft\.NETFramework\policy\v4.0";Permissions:admins-full;Check:WebServerRuntimeNotInstall
Root: HKLM; Subkey: "SOFTWARE\Microsoft\.NETFramework\policy\v4.0"; Permissions:admins-full; ValueType: string; ValueName: "30319"; ValueData: "30319-30319";Check:WebServerRuntimeHasNotV4SubKey
不要问我,上面是什么鬼,inno setup 又是什么鬼。尽情享用吧.........
---------------------延伸:mscoree.dll-----------------------------
如今作.NET Framework的开发的朋友应该是愈来愈多了,可是可能并不是人人都对MSCOREE.DLL很是了解。而事实上,绝不夸张地说,MSCOREE.DLL是.NET Framework中最为核心的DLL之一,没有这个DLL,托管程序根本没法开始执行起来,可是因为这个DLL藏在System32目录下,根本无人问津,能够说是有点委屈了这位.NET Framework中的幕后英雄。本文主要讨论MSCOREE.DLL的几大做用,以及MSCOREE.DLL的兼容性问题。
首先写一个最最简单的Hello World程序,用csc编译(固然你用VS我也没意见):
public class Program
{
public static void Main(string[] args)
{
System.Console.WriteLine("Hello World!");
}
}
|
C:/Windows/System32> ren mscoree.dll mscoree_.dll |
而后,再把mscoree.dll名字改回去,再次运行A.EXE,此次正确打印出了Hello World。
那么为何一旦没有MSCOREE.DLL,就算是最简单的Hello World也没法运行呢?
有在Windows用C/C++编程的朋友们应该熟悉上面那个出错对话框的意思,这个对话框一般在程序找不到所需的DLL的时候出现。咱们能够经过运行Visual Studio中自带的Depends.exe来查看A.EXE的对于DLL的依赖关系:
Microsoft (R) COFF/PE Dumper Version 8.00.50727.762 Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file a.exe
PE signature found
File Type: EXECUTABLE IMAGE
FILE HEADER VALUES
14C machine (x86)
3 number of sections
46C83E12 time date stamp Sun Aug 19 20:56:50 2007
0 file pointer to symbol table
0 number of symbols
E0 size of optional header
10E characteristics
Executable
Line numbers stripped
Symbols stripped
32 bit word machine
OPTIONAL HEADER VALUES
10B magic # (PE32)
8.00 linker version
400 size of code
600 size of initialized data
0 size of uninitialized data
23DE entry point (004023DE)
2000 base of code
4000 base of data
400000 image base (00400000 to 00407FFF)
|
0:000> lmm a
start end module name 00de0000 00de8000 a (deferred) |
0:000> u de23de
a+0x23de:
00de23de ff250020de00 jmp dword ptr [a+0x2000 (00de2000)] |
0:000> dds 2000+de0000
00de2000 5b034e50 mscoree!_CorExeMain
|
能够想象的到,假如你的系统中没有安装.NET Framework,那么执行托管程序也会马上一样的对话框。显然根据这个信息用户自己很难推断出发生了什么问题。一个可行的方案是Windows老是自带一个MSCOREE.DLL,这个MSCOREE.DLL若是发现没有.NET Framework则会给出比较清晰的报错信息。不过因为从Windows 2003以后(包括Vista)的全部Windows版本都会自带.Net Framework,那么这个问题基本上不会出现了。
MSCOREE.DLL有个很是特殊的地方,也就是它位于C:/Windows/System32目录下,换句话说,无论你的系统上面安装了多少个不一样的.NET Framework版本,这个DLL都最多只可能有2份(32位/64位各一份),而在C:/Windows/Microsoft.NET/Framework 或者C:/Windows/Microsoft.NET/Framework64下面,则会有多份不一样的.NET Framework同时存在。那么,这个MSCOREE.DLL又是如何对应不一样版本的.NET Framework呢?答案很简单:MSCOREE.DLL经过注册表信息肯定系统上面安装的.NET Framework版本号码,而后根据应用程序自己的所要求的版原本选择一个合适的.NET Framework版原本执行。真正的工做则是交给实际的某个版本的 .NET的DLL执行,在一般状况下,这个DLL是Work Station版本的CLR,名为MSCORWKS.DLL,而服务器版本的CLR则对应MSCORSVR.DLL
MSCOREE.DLL导出了大量的函数,那么这些函数是否公开而且能够调用呢?答案是确定的。几乎全部这些函数在MSDN中均可以查到对应的文档,而且在.NET Framework SDK的Include目录中有一个对应的mscoree.h,提供了这些函数的Prototype。应用程序经过这些函数,能够访问CLR提供的各项功能,好比:
函数名
|
用途
|
GetCORSystemDirectory
|
得到进程中加载的CLR的安装目录
|
GetCORVersion
|
得到进程中加载的CLR的版本西nxi
|
GetFileVersion
|
得到指定文件的CLR版本信息
|
GetRequestedRuntimeInfo
|
得到指定版本CLR的相关信息
|
GetRequestedRuntimeVersion
|
得到应用程序运行所须要的CLR版本信息
|
ClrCreateManagedInstance
|
建立一个.NET对象并返回指定的接口,使用此函数能够访问大量的.NET Framework的已有功能
|
CorBindToRuntime
|
加载指定版本CLR
|
CorBindToRuntimeHost
|
在Host中加载指定版本CLR,Hosting时候使用
|
CreateDebuggingInterfaceFromVersion
|
得到对应版本CLR的ICorDebug接口,用于编写调试器(好比Visual Studio)
|
CorLaunchApplication
|
以指定参数启动托管程序
|
除此以外还有不少,这里只是列了一些比较经常使用的功能而已。能够看到这些功能都很是有用,特别值得提出的是CorBindToRuntimeHost和CreateDebuggingInterfaceFromVersion。前者提供了对CLR各个方面的定制功能,功能很是强大,有兴趣的朋友能够参考MSDN或者Customizing the Common Language Runtime一书。然后者则提供了对托管程序的调试支持,经过ICorDebug接口。
非托管代码能够经过COM直接调用.NET的Assembly中的托管对象。如下面这个对象为例,该对象CLSID为{0029598F-26Fa-46F7-953B-86E2947AB19F},类型为Microsoft.SqlServer.Replication.ComErrorRecord,线程模型为Both,Assembly名称为Microsoft.SqlServer.Replication, Version=9.0.242.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91,所需CLR版本为v2.0.50727 (2.0 RTM)。最值得注意的是,入口点为mscoree.dll。
除了对用户自定义的托管对象提供COM支持以外,MSCOREE.DLL本身也支持少许COM对象,所以MSCOREE.dll支持DllGetClassObject, DllRegisterServer, DllUnregisterServer, DllCanUnloadNow这些COM DLL所须要支持的标准函数。
咱们能够考虑一下,假如咱们如今有了.NET Framework 1.0,而后安装了.NET Framework 2.0,那么MSCOREE.DLL会发生变化吗。答案是可能会,若是到2.0到1.0发生了改变须要修改MSCOREE.DLL(好比多加了一个函数),那么确定要更新MSCOREE.DLL,可是这个MSCOREE.DLL必须彻底支持全部.NET Framework 1.0中的MSCOREE.DLL中的函数,不然能够想象全部依赖于这些变化的MSCOREE.DLL中的函数程序都会出错。所以MSCOREE.DLL必需要作到彻底向前兼容。
再考虑卸载的状况,假如这个时候.NET Framework 2.0被卸载,那么MSCOREE.DLL会被还原成.NET Framework 1.0的吗?此次答案则是不会。由于2.0的MSCOREE.DLL自己支持.NET Framework 1.0,所以无须替换。这样最为简单。
事实上是,CLR Team通常不多改动MSCOREE.DLL,避免出现兼容性问题,所以能够预见,MSCOREE.DLL将会是.NET Framework/CLR中变化最少的DLL。换句话说,这篇文章的内容,在能够预见的将来几个版本基本上不会过期。OK,对于MSCOREE.DLL的讨论到这里就告一段落,有兴趣的朋友能够本身动手写一些小程序,实际体会一下MSCOREE.DLL所提供的各项功能。
https://docs.microsoft.com/en-us/dotnet/framework/unmanaged-api/hosting/deprecated-clr-hosting-functions
https://docs.microsoft.com/en-us/dotnet/framework/unmanaged-api/hosting/cordllmain-function
Initializes the common language runtime (CLR), locates the managed entry point in the DLL assembly's CLR header, and begins execution.
BOOL STDMETHODCALLTYPE _CorDllMain ( [in] HINSTANCE hInst, [in] DWORD dwReason, [in] LPVOID lpReserved );
hInst
[in] The instance handle of the loaded module.
dwReason
[in]Indicates why the DLL entry-point function is being called. This parameter can be one of the following values: DLL_PROCESS_ATTACH, DLL_THREAD_ATTACH, DLL_THREAD_ATTACH, or DLL_PROCESS_DETACH. For descriptions of these values, see the DllMain
documentation in the Platform SDK.
lpReserved
[in] Unused.
This method returns true
for success and false
if an error occurs.
This function is called by the operating system loader for DLL assemblies. For executable assemblies, the loader calls the _CorExeMain function instead.
The operating system loader calls this method regardless of the entry point specified in the DLL file.
In Windows 98, Windows ME, Windows NT, and Windows 2000, the _CorDllMain
function is called indirectly through a fixupin the operating system loader. In all other versions of Windows, it is called directly by the operating system loader.
For additional information, see the Remarks section in the _CorValidateImage topic.
Platforms: See System Requirements.
Header: Cor.h
Library: Included as a resource in MsCorEE.dll
.NET Framework Versions: Available since 1.0
Metadata Global Static Functions
Initializes the common language runtime (CLR), locates the managed entry point in the executable assembly's CLR header, and begins execution.
__int32 STDMETHODCALLTYPE _CorExeMain ();
This function is called by the loader in processes created from managed executable assemblies. For DLL assemblies, the loader calls the _CorDllMain function instead.
The operating system loader calls this method regardless of the entry point specified in the image file.
In Windows 98, Windows ME, Windows NT, and Windows 2000, the _CorExeMain
function is called indirectly through a fixup in the operating system loader. In all other versions of Windows, it is called directly by the operating system loader.
For additional information, see the Remarks section in the _CorValidateImage topic.
Platforms: See System Requirements.
Header: Cor.h
Library: Included as a resource in MsCorEE.dll
.NET Framework Versions: Available since 1.0