dll 打包
开发程序的时候经常会引用一些第三方的DLL,然后编译生成的exe文件就不能脱离这些DLL独立运行了。
但是,很多时候我们本想开发一款只需要一个exe就能完美运行的小工具。那该怎么办呢?
下文介绍一种超简单的方法,不用写一行代码就可轻松实现。
这里我们需要用到一款名为Costura.Fody的工具。Costura.Fody是一个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实现原理的简单介绍。
dll 打包的更多相关文章
- .Net将多个DLL打包为一个DLL(ILMerge)
在做.Net底层编码过程中,为了功能独立,有可能会生成多个DLL,引用时非常不便.这方面微软提供了一个ILMerge工具原版DOS工具,可以将多个DLL合并成一个.下载完成后需要安装一下,然后通过DO ...
- 将Qt 动态链接生成的exe及依赖dll打包方法
源地址:http://blog.csdn.net/ztz0223/article/details/8939341 将Qt 动态链接生成的exe及依赖dll打包方法 原文:http://www.qtcn ...
- C# 将dll打包到程序中
本文告诉大家如何把 dll 打包到程序中.很多时候的 软件 在运行的时候需要包括很多 dll 或其他的文件,这样的软件在给其他小伙伴,就需要做一个压缩包,或者用安装软件.这样感觉不太好,所以本文告诉大 ...
- 将Winform程序及dll打包成可执行的exe
使用场景 通常开发的Winform程序,引用了其他类库后,在输出目录下都会产生很多DLL文件,exe执行时必须依赖这些DLL.想要Winform程序只有一个可执行exe文件,又不想打包成安装包,就可以 ...
- 2018-4-29-C#-将dll打包到程序中
title author date CreateTime categories C# 将dll打包到程序中 lindexi 2018-04-29 09:43:22 +0800 2018-2-13 17 ...
- Winform程序及dll打包成一个可执行的exe
使用场景 通常开发的Winform程序,引用了其他类库后,在输出目录下都会产生很多DLL文件,exe执行时必须依赖这些DLL.想要Winform程序只有一个可执行exe文件,又不想打包成安装包,就可以 ...
- C#将dll打包到程序中
最近比较懒,加上内容也不多就懒得排版了,字放大了,看起来应该方便一点 直接进入主题 先来看一个栗子,假设现在有一个第三方dll namespace TestLibrary1 { public clas ...
- 将Qt5.5 动态链接生成的exe及依赖dll打包方法
Qt静态编译链接生成的exe文件,不需依赖七大姑八大姨的一堆dll,可以独立运行,发布很方便.但绝大多数用的都是Qt开源版本,如果用静态链接,会有些限制.那有没有办法即能享受静态编译的方便,又不受开源 ...
- Unity3D引用dll打包发布的问题及解决
今年我们开始使用Unity3D开发MMORPG,脚本语言使用C#,这样我们就可以使用以往积累的许多类库.但是,在U3D中使用.NET dll的过程并不是那么顺利,比如我们今天遇到的这种问题. 一.问题 ...
随机推荐
- iOS sqlite3数据库解析
看来从版本3.3.1基本上已经支持线程句柄的传递功能.具体限制我标记了一下.(6) Is SQLite threadsafe?SQLite is threadsafe. We make this co ...
- 【解惑】让人头疼的"相等"关系
Java中判断相等关系一般有两种手段:(1) “==”关系操作符 (2) equals()方法. 显然,基本数据类型变量之间只能用"==".而对象之间两种手段都是合法的.但是有很 ...
- 应用scikit-learn做文本分类
文本挖掘的paper没找到统一的benchmark,只好自己跑程序,走过路过的前辈如果知道20newsgroups或者其它好用的公共数据集的分类(最好要所有类分类结果,全部或取部分特征无所谓)麻烦留言 ...
- opencv显示鼠标所在位置的rgb值
#include"highgui.h" #include"cv.h" #include"cxcore.h" #include<stdl ...
- MapReduce读取hdfs上文件,建立词频的倒排索引到Hbase
Hdfs上的数据文件为T0,T1,T2(无后缀): T0: What has come into being in him was life, and the life was the light o ...
- NDK(1)配置ndk,含eclipse,Android Studio1.5.1
现在的ndk配置已经非常简单,如果看到要cygwin的请关闭. 1,Eclipse 添加ndk linux,mac ,windows 相似, a.下载 ndk并解压, b.在eclipse的andro ...
- 网易新闻页面信息抓取 -- htmlagilitypack搭配scrapysharp
最近在弄网页爬虫这方面的,上网看到关于htmlagilitypack搭配scrapysharp的文章,于是决定试一试~ 于是到https://www.nuget.org/packages/Scrapy ...
- Codeforces Beta Round #97 (Div. 1)
B 判矩阵的时候 出了点错 根据点积判垂直 叉积判平行 面积不能为0 #include <iostream> #include<cstdio> #include<cstr ...
- Debian 如何更改hdmi接口输出的分辨率
1. 先删除无用的文件: a) Boot/boot.src b) Boot/script.bin 2. 打开boot/script.fex,找到disp_init节点 a) 将screenX_outp ...
- Strongly connected 挺简单的tarjan
题意:给你一个连通图,问你最多加多少条边,还能保证该图不是强连通图. 对整个图求强连通分量,然后对图缩点,记录一下缩点之后每隔点包含的原来的点的个数,找出最少的那个点,然后对这个点建成完全图,对另外的 ...