微軟有一個工具叫ILMerge可以合並dll exe等,但是對於wpf的應用程序而言這個工具就不好用了。我的這方法也是從國外一個博客上找來的。僅供大家參考。
第一步:把下面的代碼寫到你的項目文件的標准的Microsoft.CSharp下面,也就是.csproj的文件里
<Target Name="AfterResolveReferences"> <ItemGroup> <EmbeddedResource Include="@(ReferenceCopyLocalPaths)" Condition="'%(ReferenceCopyLocalPaths.Extension)' == '.dll'"> <LogicalName>%(ReferenceCopyLocalPaths.DestinationSubDirectory)%(ReferenceCopyLocalPaths.Filename)%(ReferenceCopyLocalPaths.Extension)</LogicalName> </EmbeddedResource> </ItemGroup> </Target>
第二步:把你需要引用的dll復制到你當前項目的Resources文件夾下面,並把他們作為嵌入式資源(dll的屬性里有此設置),為了避免文件名沖突,把這些dll的后綴加上 resources (System.Windows.Interactivity.resources.dll)
第三步:通常WPF應用程序包含一個xaml文件,它充當一個神奇的入口點到應用程序和啟動的第一個窗口。然而,xaml其實沒那么神奇。如果你仔細看一下這些文件夾在您的項目文件夾obj,你會發現一個appg.cs文件,這是來自你的xaml。它包含一個正常的“靜態空隙主要“c#入口點所以為了得到在WPF之前,所有您需要做的就是定義自己的入口點進入一個新類,做你需要,然后調用正常WPF入口點。添加一個類Program.cs並把它設置成程序的入口點。
第四步:構建Program.cs的代碼
public class Program { [STAThreadAttribute] public static void Main() { AppDomain.CurrentDomain.AssemblyResolve += OnResolveAssembly; App.Main(); } private static Assembly OnResolveAssembly(object sender, ResolveEventArgs args) { Assembly executingAssembly = Assembly.GetExecutingAssembly(); AssemblyName assemblyName = new AssemblyName(args.Name); string 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; byte[] assemblyRawBytes = new byte[stream.Length]; stream.Read(assemblyRawBytes, 0, assemblyRawBytes.Length); return Assembly.Load(assemblyRawBytes); } } }
簡單的四步,如果引用的dll中的版本有低於當前項目版本的話會有錯誤,我是直接把這個dll拿出來和合並后的exe放在一起了。或者把當前引用的dll版本統一掉。出現此問題最多的時候是引用的第三方的dll。
原文地址:http://www.digitallycreated.net/Blog/61/combining-multiple-assemblies-into-a-single-exe-for-a-wpf-application