--- tags: WPF lang: zh-TW --- # 將WPF打包成單一EXE執行檔 OK, 這是從stackoverflow學來的一招。 [https://stackoverflow.com/questions/1025843/merging-dlls-into-a-single-exe-with-wpf](https://stackoverflow.com/questions/1025843/merging-dlls-into-a-single-exe-with-wpf) 原始Blog: [http://www.digitallycreated.net/Blog/61/combining-multiple-assemblies-into-a-single-exe-for-a-wpf-application](http://www.digitallycreated.net/Blog/61/combining-multiple-assemblies-into-a-single-exe-for-a-wpf-application) 有時候我們開發小型專題,並沒有很多DLL,但是你知道使用者總是會不知道應該要開哪個檔案(又不能總是像Apple一樣來個pkg全包)。 但是你知道,路是人走出來的,你會遇到的問題,通常前輩們也都走過。 stackoverflow上的路人查到了這招。在原始資料全部消滅前,讓我在這裡偷偷把這招抄下來。 ## 第一步:修改你的.csproj檔 修改你的.csproj檔,加入以下內容: ```C# <Target Name="AfterResolveReferences"> <ItemGroup> <EmbeddedResource Include="@(ReferenceCopyLocalPaths)" Condition="'%(ReferenceCopyLocalPaths.Extension)' == '.dll'"> <LogicalName>%(ReferenceCopyLocalPaths.DestinationSubDirectory)%(ReferenceCopyLocalPaths.Filename)%(ReferenceCopyLocalPaths.Extension)</LogicalName> </EmbeddedResource> </ItemGroup> </Target> ``` ## 第二步:修改主程式(Program.cs)裡的Main區段 將Program.cs裡的main改成類似下面這個樣子 ```C# [STAThreadAttribute] public static void Main() { AppDomain.CurrentDomain.AssemblyResolve += OnResolveAssembly; App.Main(); } ``` ## 第三步:在Program.cs裡面追加OnResolveAssembly方法 ```C# private static Assembly OnResolveAssembly(object sender, ResolveEventArgs args) { Assembly executingAssembly = Assembly.GetExecutingAssembly(); AssemblyName assemblyName = new AssemblyName(args.Name); var path = assemblyName.Name + ".dll"; if (assemblyName.CultureInfo.Equals(CultureInfo.InvariantCulture) == false) path = String.Format(@"{0}\{1}", assemblyName.CultureInfo, path); using (Stream stream = executingAssembly.GetManifestResourceStream(path)) { if (stream == null) return null; var assemblyRawBytes = new byte[stream.Length]; stream.Read(assemblyRawBytes, 0, assemblyRawBytes.Length); return Assembly.Load(assemblyRawBytes); } } ``` ## The Fin 同樣一個問題,回答裡面有說到,在某些情形之下,或許要將OnResolveAssembly直接放到App.cs下面。無論如何。這應該算是某種公式解:畢竟他不需要第三方的程式來幫我們打包。 在最新的 .net 3.0以後,MS似乎有提供公式解來幫助我們封裝。 ```console dotnet publish -r win-x64 -p:PublishSingleFile=true ``` 或是在你的.csproj裡面加入下列內容 ```c# <PropertyGroup> <RuntimeIdentifier>win10-x64</RuntimeIdentifier> <PublishSingleFile>true</PublishSingleFile> </PropertyGroup> ``` 詳細可洽.net公式網站 [Single-file Publish(github)](https://github.com/dotnet/designs/blob/master/accepted/2020/single-file/design.md)