C#程序(含多个Dll)合并成一个Exe
把C#程序(含多个Dll)合并成一个Exe的超简单方法
开发程序的时候经常会引用一些第三方的DLL,然后编译生成的exe文件就不能脱离这些DLL独立运行了。
但是,很多时候我们本想开发一款只需要一个exe就能完美运行的小工具。那该怎么办呢?
下文介绍一种超简单的方法,不用写一行代码就可轻松实现。
这里我们需要用到一款名为Fody.Costura的工具。Fody.Costura是一个Fody框架下的插件,可通过Nuget安装到VS工程中。安装之后,就可以将项目所依赖的DLL(甚至PDB)文件全部打包到EXE文件里。
使用方法
- 在VS中,通过Nuget为目标EXE工程安装Costura.Fody。
- 重新构建项目。
构建完成后,到项目的输出目录下找到新生成的EXE文件,你同时会发现输出目录下仍然存在那些DLL。不过不用担心,这个EXE已经能够独立运行了。你可以把这些DLL全部删除后再运行EXE试试。
另外,Fody.Costura还支持一些进阶的特性,例如:
- 临时程序集文件:在运行EXE前自动,自动将DLL从EXE中解压到文件夹系统中,再通过常规的方式加载该DLL。
- 合并非托管的DLL:Fody.Costura可以合并非托管的DLL,但是不会自动合。如果你的程序涉及非托管DLL,那么你需要通过修改Fody.Costura的配置文件来显示地告诉它你想合并哪些非托管的DLL。
- 预加载DLL:Fody.Costura可以帮助你在程序启动时预先加载某些DLL,你甚至可以指定这些DLL的加载顺序。
以上这些进阶特性都需要你通过修改Fody.Costura的配置文件来实现,具体的操作步骤可以参考它的官方文档。
好了,Fody.Costura的使用方式已经介绍完了。如果你对Fody.Costura的实现原理感到好奇,可以接着往下看。
实现原理介绍
当CLR试图加载一个程序集但加载失败时,它会引发AppDomain.AssemblyResolve事件。我们的程序可以监听这个事件,并且在这个事件的处理函数中返回这个CLR试图加载的程序集,从而使程序得以继续正常运行。
Fody.Costura在构建项目时会把EXE引用到的DLL全部嵌入到EXE文件中。当程序在运行的过程中用到其中某个DLL的时候(此时由于CLR无法找到该DLL文件,导致AppDomain.AssemblyResolve事件被触发)再从EXE文件的嵌入资源中提取所需的DLL。
下面这两个函数就是Fody.Costura实现这部分逻辑的代码。
public static void Attach()
{
var currentDomain = AppDomain.CurrentDomain;
currentDomain.AssemblyResolve += (s, e) => ResolveAssembly(e.Name);
}
public static Assembly ResolveAssembly(string assemblyName)
{
if (nullCache.ContainsKey(assemblyName))
{
return null;
} var requestedAssemblyName = new AssemblyName(assemblyName); var assembly = Common.ReadExistingAssembly(requestedAssemblyName);
if (assembly != null)
{
return assembly;
} Common.Log("Loading assembly '{0}' into the AppDomain", requestedAssemblyName); assembly = Common.ReadFromEmbeddedResources(assemblyNames, symbolNames, requestedAssemblyName);
if (assembly == null)
{
nullCache.Add(assemblyName, true); // Handles retargeted assemblies like PCL
if (requestedAssemblyName.Flags == AssemblyNameFlags.Retargetable)
{
assembly = Assembly.Load(requestedAssemblyName);
}
}
return assembly;
}
可以看到,Attach方法监听了AppDomain.AssemblyResolve事件。当CLR无法成功加载某个程序集时, AssemblyResolve事件处理函数会被执行。AssemblyResolve会尝试通过Common.ReadFromEmbeddedResources方法从已加载的程序集的嵌入资源中获取目标程序集,并返回给CLR。
看到这里,你可能会问,Attach方法是在什么时候执行的呢?
其实是这样的,对于C#语言来说,CLR隐藏了一个大招——CLR可以在每个模块(每个程序集都含有一个或多个模块)加载之前执行一些初始化的代码。但是很遗憾,C#语言无法控制这部分代码。Fody.Costura则是在内部将IL代码直接注入到EXE程序集内部模块的初始化函数中,而这部分IL代码其实就是执行了Attach方法。这样一来,EXE程序集被加载后,Attach方法就能够立即得到调用了。
以上就是Fody.Costura实现原理的简单介绍。
C#程序(含多个Dll)合并成一个Exe的更多相关文章
- 将WinForm程序(含多个非托管Dll)合并成一个exe的方法
原文:将WinForm程序(含多个非托管Dll)合并成一个exe的方法 开发程序的时候经常会引用一些第三方的DLL,然后编译生成的exe文件就不能脱离这些DLL独立运行了. ILMerge能把托管dl ...
- 利用Costura.Fody制作绿色单文件程序(C#程序(含多个Dll)合并成一个Exe)
原文:利用Costura.Fody制作绿色单文件程序(C#程序(含多个Dll)合并成一个Exe) 开发程序的时候经常会引用一些第三方的DLL,然后编译生成的exe文件就不能脱离这些DLL独立运行了.这 ...
- 多个DLL合并成一个DLL
多个DLL合并成一个DLL,把DLL合并到Exe中的解决方案 1:) 下载 http://download.microsoft.com/download/1/3/4/1347C99E-9DFB-425 ...
- winform把所有dll打包成一个exe
大家都知道做winform开发,是可以利用visual studio进行打包的,但是这种打包的方式需要双击安装,那么有没有什么方法,可以把winform程序打包成绿色版呢?当然,这里的“绿色版”也是相 ...
- 把C#程序(含多个Dll)合并成一个Exe的超简单方法
开发程序的时候经常会引用一些第三方的DLL,然后编译生成的exe文件就不能脱离这些DLL独立运行了. 但是,很多时候我们本想开发一款只需要一个exe就能完美运行的小工具.那该怎么办呢? 下文介绍一种超 ...
- [C#]使用ILMerge将源DLL合并到目标EXE(.NET4.6.2)
本文为原创文章,如转载,请在网页明显位置标明原文名称.作者及网址,谢谢! 本文主要是使用微软的ILMerge工具将源DLL合并到目标EXE,因此,需要下载以下工具: https://www.micro ...
- C# 实现将多个word文档合并成一个word文档的功能
前段时间项目上遇到这么一个需求,需要将多个OCR识别的word文档合并成一个,于是就在网上找了找,自己修改了一下.在这里跟大家分享一下,希望有用的到的. 要做多word文档合并,首先要导入Micros ...
- ILMerge将源DLL合并到目标EXE
ILMerge将源DLL合并到目标EXE(.NET4.6.2) 本文为原创文章,如转载,请在网页明显位置标明原文名称.作者及网址,谢谢! 本文主要是使用微软的ILMerge工具将源DLL合并到目标EX ...
- 使用ILMerge将源DLL合并到目标EXE(.NET4.6.2)
本文为原创文章,如转载,请在网页明显位置标明原文名称.作者及网址,谢谢! 本文主要是使用微软的ILMerge工具将源DLL合并到目标EXE,因此,需要下载以下工具: https://www.micro ...
随机推荐
- 使用 DBMS_REPAIR 修复坏块
对于Oracle数据块物理损坏的情形,在我们有备份的情况下可以直接使用备份来恢复.对于通过备份恢复,Oracel为我们提供了很多种方式,冷备,基于用户管理方式,RMAN方式等等.对于这几种方式我们需要 ...
- 从零开始学Xamarin.Forms(一) 概述
原文:从零开始学Xamarin.Forms(一) 概述 Xamarin 读 "ˈzæmərin",是一个基于开源项目mono的能够使用C#开发的收费的跨平台(iOS.And ...
- android ksoap2调用.net Webservice 方法总结
android ksoap2调用.net Webservice 方法直接放到一个类里: package com.util; import org.ksoap2.SoapEnvelope; impor ...
- Graphics.DrawString 方法
MSDN上的解释: 在指定位置而且用指定的 Brush 和Font 对象绘制指定的文本字符串. public void DrawString( string s, Font font, Brush b ...
- 二分图行列匹配---> hdu2119,hdu1498
hdu2119 题意:给定一个矩形方格,每个格子里面的数字是0或者1,每次操作可以把一整行或列的1变成0,问最少多少次操作能将1全部变为0 一次可以消除某一行或者某一列的1但是可以这么想,最多有多少个 ...
- Android实现限制EditText输入文字的数量
一: 声明控件. TextView hasnumTV; TextView hasnum;// 用来显示剩余字数 int num = 50;// 限制的 ...
- SQL Server,Access数据库查询易混点和C#中parameter指定参数长度的优缺点
在学校的时候就经常做一些网站,所以这次在公司实习,组长第一次给了一个企业的网站还是很快的完成了.中间并没有遇到什么大的问题,但是还是遇到了两个新手非常容易混淆的小问题,所以拿出来跟大家分享一下. 主要 ...
- HDU1698_Just a Hook(线段树/成段更新)
解题报告 题意: 原本区间1到n都是1,区间成段改变成一个值,求最后区间1到n的和. 思路: 线段树成段更新,区间去和. #include <iostream> #include < ...
- sql server基本流程语句
- bootstrap的popover在trigger设置为hover时不隐藏popover
使用bootstrap的popover,trigger设置为hover时,可以实现当鼠标放置到目标元素上时显示popover,可是无法实现当鼠标移动到popover上时不隐藏popover,在网上找了 ...