2015年8月23日 星期日

[常用]將所有dll檔封裝進exe檔(WPF)

一般我們寫程式的時候都會用到許多dll
但是把程式交出去的時候如果有一堆dll會很難管理,也不是很好看

這時候就需要把dll封裝進程式執行檔裡面

1.修改Project.csproj

參考自http://www.digitallycreated.net/Blog/61/combining-multiple-assemblies-into-a-single-exe-for-a-wpf-application
在最底部增加這幾行
<Target Name="AfterResolveReferences">
<ItemGroup>
<EmbeddedResource Include="@(ReferenceCopyLocalPaths)" Condition="'%(ReferenceCopyLocalPaths.Extension)' == '.dll'">
<LogicalName>%(ReferenceCopyLocalPaths.DestinationSubDirectory)%(ReferenceCopyLocalPaths.Filename)%(ReferenceCopyLocalPaths.Extension)</LogicalName>
</EmbeddedResource>
</ItemGroup>
</Target>

2.右鍵點選參考底下的dll,把複製到本機這個屬性改為False,該dll就不會一起複製到程式執行的資料夾內。
   但此動作會使得程式參考不到該dll檔

3.將dll檔加進Resources內,建置方式選擇內嵌資源,就跟一般放影像檔、音效檔一樣,會把dll封裝進exe執行檔內。
   但程式呼叫到該dll時不會自動找到Resources內的dll檔,必須自行對應

4.新建一支Program.cs檔,取代App.xaml.cs成為專案起始檔(右鍵點專案可以設定起始檔)

using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
namespace MyProject
{
public class Program
{
[STAThreadAttribute]
public static void Main()
{
var assemblies = new Dictionary<string, Assembly>();
var executingAssembly = Assembly.GetExecutingAssembly();
var resources = executingAssembly.GetManifestResourceNames().Where(n => n.EndsWith(".dll"));
//設定dll的參考路徑以供程式執行時對應
foreach (string resource in resources)
{
using (var stream = executingAssembly.GetManifestResourceStream(resource))
{
if (stream == null)
continue;
var bytes = new byte[stream.Length];
stream.Read(bytes, 0, bytes.Length);
try
{
assemblies.Add(resource, Assembly.Load(bytes));
}
catch (Exception ex)
{
System.Diagnostics.Debug.Print(string.Format("Failed to load: {0}, Exception: {1}", resource, ex.Message));
}
}
}
//當程式參考不到dll時會觸發,將我們對應好的dll位置回傳
AppDomain.CurrentDomain.AssemblyResolve += (s, e) =>
{
var assemblyName = new AssemblyName(e.Name);
var path = string.Format("{0}.dll", assemblyName.Name);
//不知道為什麼,自行加在Resources內的dll都會把路徑全部寫進名稱,所以這邊我自己把路徑補上以免對應不到
if (assemblies.ContainsKey(path) || assemblies.ContainsKey("Projectname.Resources."+path))
{
return assemblies["Projectname.Resources." + path];
}
return null;
};
App.Main();
}
}
}
view raw Program.cs hosted with ❤ by GitHub

完成以上步驟後,再建置程式,就會發現dll檔都不見了,而exe檔明顯變肥



沒有留言:

張貼留言