将DLL打包在EXE文件中的两种方法
需求描述在C#的项目中,经常会引用一些外部的DLL库。在发布的时候,必需将这些库和可执行程序一起发布,否则会导致程序无法运行。在一些项目中,会有这样的需求:希望发布一个单独的可执行文件,将所引用的DLL文件打包入EXE程序中的方式来实现。实现原理想要实现这个库有以下三种方式:以嵌入的资源将DLL文件打包,然后在运行的时候再释放出来;以嵌入的资源将DLL文件打包,然后在运行时直接加载至内...
需求描述
在C#的项目中,经常会引用一些外部的DLL库。在发布的时候,必需将这些库和可执行程序一起发布,否则会导致程序无法运行。在一些项目中,会有这样的需求:希望发布一个单独的可执行文件,将所引用的DLL文件打包入EXE程序中的方式来实现。
实现原理
想要实现这个库有以下三种方式:
针对不同的需求可以选择以上三种情况的任意一种。这里介绍第1种和第2种两种方法。在介绍之前,首先了解一下什么是嵌入的资源。
嵌入的资源
在C#的项目中,我们可以添加任意类型的文件,作为一个纯二进制的文件嵌入至项目中,作为资源使用。以下对嵌入资源的添加和使用进行简要说明。
- 添加嵌入资源
在项目上中点击右键,选择“添加->现有项”,然后添加所需要的文件。如果要添加任意类型,在弹出的打开对话框中选择“所有文件(*.*)
”。然后选中已经添加的文件,在属性窗口中设置“生成操作
”的属性为“嵌入的资源
”。 - 嵌入资源的路径
已经添加的资源文件,使用绝对路径访问,格式为[解决方案名称].[文件夹路径].[文件名]
。比如在一个名为Test
的项目中,加入的资源文件a.dll
在根目录下,则访问路径为Test.a.dll
。如果a.dll
是放在文件夹下,比如Resource
目录下,则其路径为Test.Resource.a.dll
,以此类推。 - 使用嵌入资源
在C#中,一个DLL即是一个程序集,使用System.Reflection.Assembly
类来表示。加载一个程序集可以使用Assembly.GetExecutingAssembly().GetManifestResourceStream(resourcePath)
来实现,其中resoucePath
即为DLL的路径。详细操作可参见相关文章。
注意:以上的嵌入资源都是托管的DLL,即是使用.NET创建的类库。如果是非托管的DLL,如使用C++建立的,则不管用。如需要加载非托管DLL,可以使用以下办法:
1)从嵌入的DLL加载字节数据 data;
2)将data写至一个临时文件中;
3)使用 Assembly.LoadFile(path)
进行加载即可。
实现过程
方法1
第1种方法,只需要读取嵌入的资源,然后写到本地即可。以下代码展示了如何从EXE中读取指定的嵌入的资源文件,读取的结果为字节数组,即 byte[]
类型。
public byte[] GetResource(String respath)
{
System.IO.Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("Test.a.dll");
byte[] data = new byte[stream.Length];
stream.Read(data, 0, data.Length);
return data;
}
读取成功后的数据可以直接写回到磁盘保存为dll文件,然后程序即可正常调用。比如,我们可以使用使用 System.IO.File.WriteAllBytes("a.dll", data)
方法来保存读取至的程序目录下,名称为 a.dll
。
方法2
第2种方法,可参见 此文,以下为以加载 Test.a.dll
的示例代码。
static void Main(string[] args)
{
// 在整个程序最开始的地方进行引用DLL的内存载入
AppDomain.CurrentDomain.AssemblyResolve += (s, a) =>
{
using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("Test.a.dll"))
{
byte[] data = new byte[stream.Length];
stream.Read(data, 0, data.Length);
return Assembly.Load(data);
}
};
}
小结
本文介绍了两种将DLL嵌入至EXE,从而实现一个独立的EXE程序的实现办法。这两种办法都是通过嵌入的资源的方式将DLL文件嵌入在EXE中。不同之处在于,第1种方法将DLL文件在启动时读取出来,然后保存在本地,从而实现和一般C#项目一样的项目结构(即EXE+DLL的结构)。第2种方式则更为简单,直接加载至内存,从而在运行时,也不需要本地的DLL文件。具体使用,可以根据实际需求来决定。
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)