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?
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.
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.
Take a look at RedGate's SmartAssembly.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With