Combining dll into one .exe with wpf

I am currently working on a project in which we have many dependencies. I would like to compile the entire reference dll in .exe in the same way as with the built-in resources. I tried ILMerge , but it cannot handle .xaml resources.

So my question is: is there a way to combine a WPF project with multiple dependencies into one .exe?

+50
c # dll wpf ilmerge
Jun 22 '09 at 7:14
source share
10 answers

. A NET reactor has the ability to merge assemblies and is not very expensive.

+7
Jun 22 '09 at 7:18
source share

http://www.digitallycreated.net/Blog/61/combining-multiple-assemblies-into-a-single-exe-for-a-wpf-application

It worked like a charm for me :) and its completely free.

Adding code in case the blog ever disappears.

1) Add this to your .csproj file:

 <Target Name="AfterResolveReferences"> <ItemGroup> <EmbeddedResource Include="@(ReferenceCopyLocalPaths)" Condition="'%(ReferenceCopyLocalPaths.Extension)' == '.dll'"> <LogicalName>%(ReferenceCopyLocalPaths.DestinationSubDirectory)%(ReferenceCopyLocalPaths.Filename)%(ReferenceCopyLocalPaths.Extension)</LogicalName> </EmbeddedResource> </ItemGroup> </Target> 

2) Make the main Program.cs look like:

 [STAThreadAttribute] public static void Main() { AppDomain.CurrentDomain.AssemblyResolve += OnResolveAssembly; App.Main(); } 

3) Add the OnResolveAssembly method:

 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); } } 
+57
Feb 14 '11 at 17:14
source share

Costura Fody is an open source tool designed to handle merging wpf assemblies.

https://github.com/Fody/Costura#how-it-works

+41
Aug 10 2018-11-11T00:
source share

{smartassembly} is one such product. It can dispute or embed your DLLs.

Try the following: http://www.smartassembly.com/

You can also make many improvements to your application to make it run faster.

And yes. You can use it for WPF.

06/08/2015 update: ILRepack 2.0.0 (which is an alternative to ILMerge open source) now supports most cases of WPF merging: https://twitter.com/Gluckies/status/607680149157462016 p>

+12
Jun 24 '09 at 4:48
source share

As hosted on the ILMerge website , treat these dlls as resources, from Jeffrey Richter here :

Many applications consist of an EXE file, which depends on many DLL files. When you deploy this application, all files must be deployed. However, there is a method that you can use to deploy just one EXE file. First, identify all the dll files that the exe file depends on which is not supplied as part of Microsoft.NET itself. Then add these DLLs to your Visual Studio project. For each added DLL file, display its properties and change its "Build Action" to "Embedded Resource". This causes the C # compiler to insert the DLL file into your EXE file, and you can deploy this EXE file. At run time, the CLR will not be able to find the dependent DLL, which is the problem. To fix this, when your application initializes, it registers a callback method with the AppDomains ResolveAssembly event. The code should look something like this:

 AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => { String resourceName = "AssemblyLoadingAndReflection." + 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); } }; 

Now, when the thread calls a method that references the type in the dependent DLL file, the AssemblyResolve event will be raised, and the callback code shown above will find the desired DLL resource and load it by overloading the Loads Loads method, which takes byte [] in as an argument.

+9
Aug 11 '11 at 12:17
source share

Use Costura.Fody . It is available as Nuget Pkg for the best and easiest way to embed resources in your assembly.

 Install-Package Costura.Fody 

After adding it to the project, it will automatically add all the added links to your main assembly.

+6
Oct 09 '15 at 17:04
source share

Try .Netz ( http://madebits.com/netz/ ) - it is free (like in beer) and does some nice things if you are the target.

+2
Jul 12 '11 at 12:57
source share

Here is a refined version of the cited code from Matthieu that does not require knowledge of the namespace to extract the code. For WPF, put this in the application launch event code.

 AppDomain.CurrentDomain.AssemblyResolve += (s, args) => { // Note: Requires a using statement for System.Reflection and System.Diagnostics. Assembly assembly = Assembly.GetExecutingAssembly(); List<string> embeddedResources = new List<string>(assembly.GetManifestResourceNames()); string assemblyName = new AssemblyName(args.Name).Name; string fileName = string.Format("{0}.dll", assemblyName); string resourceName = embeddedResources.Where(ern => ern.EndsWith(fileName)).FirstOrDefault(); if (!string.IsNullOrWhiteSpace(resourceName)) { using (var stream = assembly.GetManifestResourceStream(resourceName)) { Byte[] assemblyData = new Byte[stream.Length]; stream.Read(assemblyData, 0, assemblyData.Length); var test = Assembly.Load(assemblyData); string namespace_ = test.GetTypes().Where(t => t.Name == assemblyName).Select(t => t.Namespace).FirstOrDefault(); #if DEBUG Debug.WriteLine(string.Format("\tNamespace for '{0}' is '{1}'", fileName, namespace_)); #endif return Assembly.Load(assemblyData); } } return null; }; 

To make them available at compile time, I create a folder called ExternalDLLs and copy the dll there and set them to EmbeddedResource, as described above. To use them in your code, you still need to set a link to them, but set Copy Locally to False. To get the code to compile without errors, you also need to set the DLL namespaces using the statuses in your code.

Here is a small utility that rotates through the built-in resource names and displays their namespaces in the output window.

 private void getEmbeddedResourceNamespaces() { // Note: Requires a using statement for System.Reflection and System.Diagnostics. Assembly assembly = Assembly.GetExecutingAssembly(); List<string> embeddedResourceNames = new List<string>(assembly.GetManifestResourceNames()); foreach (string resourceName in embeddedResourceNames) { using (var stream = assembly.GetManifestResourceStream(resourceName)) { Byte[] assemblyData = new Byte[stream.Length]; stream.Read(assemblyData, 0, assemblyData.Length); try { var test = Assembly.Load(assemblyData); foreach (Type type in test.GetTypes()) { Debug.WriteLine(string.Format("\tNamespace for '{0}' is '{1}'", type.Name, type.Namespace)); } } catch { } } } } 
+1
Apr 19 '13 at 15:52
source share
  • add this to the .csprofj file:
<P →
 <Target Name="AfterResolveReferences"> <ItemGroup> <EmbeddedResource Include="@(ReferenceCopyLocalPaths)" Condition="'%(ReferenceCopyLocalPaths.Extension)' == '.dll'"> <LogicalName>%(ReferenceCopyLocalPaths.DestinationSubDirectory)%(ReferenceCopyLocalPaths.Filename)%(ReferenceCopyLocalPaths.Extension)</LogicalName> </EmbeddedResource> </ItemGroup> </Target> 
  1. right click on project / properties / application / starup object / select Sinhro.Program

  2. add this to your program.cs file:

    using System.Reflection; using System.IO; using System.Globalization;

     [STAThreadAttribute] static void Main() { AppDomain.CurrentDomain.AssemblyResolve += OnResolveAssembly; ... 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); } } 

source: http://www.digitallycreated.net/Blog/61/combining-multiple-assemblies-into-a-single-exe-for-a-wpf-application

0
Jul 22 '15 at 8:41
source share

Since all the other solutions are in C #, and I needed it for VB.NET, this includes explanations about where to insert the configuration change, the necessary import, and how to add a handler instead of C # + = syntax.

For any WPF application, and not for each project, you must add the following so that the code compiles into a single EXE file. It will still contain the DLLs in the output folder, but the EXE file will contain all of them.

  1. Upload a WPF project (usually view)
  2. Right-click on the project and edit it.
  3. In the document, paste the following code after this line
 <Import Project="$(MSBuildToolsPath)\Microsoft.VisualBasic.targets" /> 

Embed code

 <Target Name="AfterResolveReferences"> <ItemGroup> <EmbeddedResource Include="@(ReferenceCopyLocalPaths)" Condition="'%(ReferenceCopyLocalPaths.Extension)' == '.dll'"> <LogicalName>%(ReferenceCopyLocalPaths.DestinationSubDirectory)%(ReferenceCopyLocalPaths.Filename)%(ReferenceCopyLocalPaths.Extension) </LogicalName> </EmbeddedResource> </ItemGroup> </Target> 
  1. Close it, save and reload the project
  2. In the Application.xaml.vb file, add the following code or, if something already exists in the file, add it to it:
 Imports System.Reflection Imports System.Globalization Imports System.IO Class Application Public Sub New() AddHandler AppDomain.CurrentDomain.AssemblyResolve, AddressOf OnResolveAssembly End Sub Private Shared Function OnResolveAssembly(ByVal sender As Object, ByVal args As ResolveEventArgs) As Assembly Dim executingAssembly As Assembly = Assembly.GetExecutingAssembly() Dim assemblyName As AssemblyName = New AssemblyName(args.Name) Dim path = assemblyName.Name & ".dll" If assemblyName.CultureInfo.Equals(CultureInfo.InvariantCulture) = False Then path = String.Format("{0}\{1}", assemblyName.CultureInfo, path) Using stream As Stream = executingAssembly.GetManifestResourceStream(path) If stream Is Nothing Then Return Nothing Dim assemblyRawBytes = New Byte(stream.Length - 1) {} stream.Read(assemblyRawBytes, 0, assemblyRawBytes.Length) Return Assembly.Load(assemblyRawBytes) End Using End Function End Class 
0
Jun 20 '19 at 21:09 on
source share



All Articles