[C#.NET] 合併 .net 組件 / 將 .dll 嵌入 .exe
日前,同事向我反應,應用程式引用太多的 dll 會讓應用程式(exe)資料夾裡有太多的 dll,這看起來很亂。
簡單來說,如何只交付一個檔案,就能讓功能順利執行?如何合并 dll 或是應用程式?
相信,這樣的需求會一直存在,目前我知道有三種方式可以合并 dll。
1.SmartAssembly.exe,需付費,使用簡單,在此就不多說了
2.ILMerge.exe
保哥有相當詳細的介紹
http://blog.miniasp.com/post/2009/08/07/Useful-tool-ILMerge.aspx
要注意並非所有組件都可合併,若有使用非拖管的組件可能會合併失敗
3.AppDomain.CurrentDomain.AssemblyResolve,利用資源檔動態載入組件
- 利用 Visual Studio 呼叫 ILMerge.exe 合并組件
Step1.下載安裝ILMerge
http://www.microsoft.com/en-us/download/details.aspx?id=17630
Step2.在Winform專案裡,加入ILMerge 至 Visual Studio(為了讓 ILMerge.exe 上版控)
Step3.在Winform專案裡,加入 ResolveAssembly 及 ResolveAssemblyContract 專案,撰寫所需的功能
Step4.定義Build Command Line
以下是.NET 4.0的組件用法
ILMerge.exe /log:log.txt /targetplatform:"v4,c:\windows\Microsoft.NET\Framework\v4.0.30319" /out:Merged.ResolveAssembly.Demo.exe ResolveAssembly.Demo.exe ResolveAssembly.dll ResolveAssemblyContract.dll
這樣的用法每次 Build 的時候就會自動合併,為來只要交付 Merged.ResolveAssembly.Demo.exe 及可,同理可証,若你要交付的是 dll 檔就把這個方式用在 dll 專案上
- 將組件變成資源檔
Step1.加入需要參考的組件至Visual Studio裡,並將建置動作改成 Embedded Resource
Step2.在Winform專案裡,加入 ResolveAssembly 及 ResolveAssemblyContract 專案,並設定 Copy Local = false
Step3.在程式載入前註冊 AppDomain.CurrentDomain.AssemblyResolve
@Program.cs
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Windows.Forms;
namespace ResolveAssembly.Demo
{
internal static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
private static void Main()
{
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
string resourceName = "ResolveAssembly.Demo." + new AssemblyName(args.Name).Name + ".dll";
using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName))
{
byte[] assemblyData = new byte[stream.Length];
stream.Read(assemblyData, 0, assemblyData.Length);
return Assembly.Load(assemblyData);
}
}
}
}
當應用程式執行時找不到相依組件時,就會依上述程式碼載入組件
下圖為載入ResolveAssembly.Demo.ResolveAssembly.dll
下圖為載入ResolveAssembly.Demo.ResolveAssemblyContract.dll
若有謬誤,煩請告知,新手發帖請多包涵
Microsoft MVP Award 2010~2017 C# 第四季
Microsoft MVP Award 2018~2022 .NET