Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to merge files to single executable or decrease the number of distributed files

Tags:

c#

.net

wpf

ilmerge

I have such output files of my WPF application:

de\
es\
fr\
hu\
it\
pt-BR\
Resources\
ro\
ru\
sv\
zh-Hans\
FileHelpers.dll
FileHelpers.DataLink.dll
FileHelpers.ExcelStorage.dll
Interop.Excel.dll
Interop.Office.dll
Ionic.Zip.dll
wpftoolkit.dll
Xceed.Wpf.AvalonDock.dll
Xceed.Wpf.AvalonDock.Themes.Aero.dll
Xceed.Wpf.AvalonDock.Themes.Metro.dll
Xceed.Wpf.AvalonDock.Themes.VS2010.dll
Xceed.Wpf.DataGrid.dll
Xceed.Wpf.Toolkit.dll
MyApp.Common.Extensions.dll
MyApp.Common.Helpers.dll
MyApp.Common.Types.Attributes.dll
MyApp.Security.dll
MyApp.Wpf.Controls.dll
MyApp.exe
MyApp.exe.config
licence.key
error.log

Everything started from MyApp is developed by myself, everything else done by 3dParty I want to distribute my app but in order to do that I want to merge everything what is possible to distribute the minimum ammmount of files.

I was trying to use ilmerge to merge my files in to single one but was getting an error:

ILMerge.Merge: ERROR!!: Duplicate type 'XamlGeneratedNamespace.GeneratedInternal TypeHelper' found in assembly 'Xceed.Wpf.DataGrid'. The answer on that question I found here xeed error reason Than I've being reading ilmerge limitations and assembly as resources by Jeffrey Richter

So I found Jeffrey Richter solution is quite useful. But I cant apply that for my program because there is no 'Build Action' attribute on assemblies.

Is there anything I can do in order to achieve my goal?

enter image description here

like image 490
sreginogemoh Avatar asked Jan 13 '23 00:01

sreginogemoh


2 Answers

To make Jeffrey's idea working you should add your assemblies not only as references. Just add dlls as existing item (right click on project->Add->Existing Item) to your project and you will get Build Action property on them. Also set Copy local property to false on the references that you add as an embedded resource.

enter image description here

App class constructor:

public partial class App : Application
{
    public App()
    {
        AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
    }
    static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
    {
        var dllName = new AssemblyName(args.Name).Name + ".dll";
        var execAsm = Assembly.GetExecutingAssembly();
        var resourceName = execAsm.GetManifestResourceNames().FirstOrDefault(s => s.EndsWith(dllName));
        if (resourceName == null) return null;
        using (var stream = execAsm.GetManifestResourceStream(resourceName))
        {
            var assbebmlyBytes = new byte[stream.Length];
            stream.Read(assbebmlyBytes, 0, assbebmlyBytes.Length);
            return Assembly.Load(assbebmlyBytes);
        }

    }
}

Pay attention that this method consume more memory than usual dll loading.

like image 169
Deffiss Avatar answered Jan 25 '23 23:01

Deffiss


Take a look at RedGate's SmartAssembly.

like image 45
gap Avatar answered Jan 26 '23 01:01

gap