c# wpf dll ilmerge

c# - Fusionando dlls en un solo.exe con wpf



ilmerge (9)

  1. agregue esto al archivo .csprofj:

>

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

  1. Haga clic derecho en project / properties / application / starup object / seleccione Sinhro.Program

  2. agregue esto a su archivo program.cs:

    usando System.Reflection; usando System.IO; utilizando 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); } }

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

Actualmente estoy trabajando en un proyecto donde tenemos muchas dependencias. Me gustaría compilar todos los dll referenciados en el .exe de forma muy parecida a como lo harías con los recursos integrados. He intentado ILMerge pero no puede manejar los recursos .xaml.

Entonces mi pregunta es: ¿hay alguna manera de fusionar un proyecto de WPF con múltiples dependencias en un solo .exe?


Aquí hay una versión ajustada del código entrecomillado de Matthieu que no requiere conocer el espacio de nombres para extraer el código. Para WPF, coloque esto en el código de evento de inicio de la aplicación.

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; };

Para que estén disponibles en tiempo de compilación, creo una carpeta llamada ExternalDLLs y copio los dlls allí y los configuro a EmbeddedResource como se indicó anteriormente. Para usarlos en su código, aún necesita establecer una referencia a ellos, pero configure Copiar local en False. Para que el código se compile limpiamente sin errores, también debe establecer el uso de enunciados en su código en los espacios de nombres de los dlls.

Aquí hay una pequeña utilidad que gira a través de los nombres de recursos incrustados y muestra sus espacios de nombres en la ventana de resultados.

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 { } } } }



Pruebe .Netz ( http://madebits.com/netz/ ) - es gratis (como en la cerveza) y hace algunas cosas buenas si su objetivo es un exe.


Tal como se publicó en el ILMerge , trata a los dlls como recursos, de Jeffrey Richter here :

Muchas aplicaciones consisten en un archivo EXE que depende de muchos archivos DLL. Al implementar esta aplicación, todos los archivos se deben implementar. Sin embargo, hay una técnica que puede usar para implementar solo un archivo EXE. En primer lugar, identifique todos los archivos DLL de los que depende su archivo EXE que no se envían como parte del propio Microsoft .NET Framework. A continuación, agregue estos archivos DLL a su proyecto de Visual Studio. Para cada archivo DLL que agregue, muestre sus propiedades y cambie su "Acción de compilación" a "Recurso incrustado". Esto hace que el compilador de C # incruste los archivos DLL en su archivo EXE, y puede implementar este archivo EXE. En tiempo de ejecución, el CLR no podrá encontrar los ensamblados DLL dependientes, lo cual es un problema. Para solucionarlo, cuando la aplicación se inicialice, registre un método de devolución de llamada con el evento ResolveAssembly de AppDomain. El código debería verse más o menos así:

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); } };

Ahora, la primera vez que un hilo llama a un método que hace referencia a un tipo en un archivo DLL dependiente, se generará el evento AssemblyResolve y el código de devolución de llamada que se muestra arriba encontrará el recurso DLL incorporado y lo cargará llamando a una sobrecarga del método Load de Assembly eso toma un byte [] como argumento.


Use Costura.Fody : está disponible como paquete Nuget para la mejor y más fácil manera de incorporar recursos en su ensamblaje.

Install-Package Costura.Fody

Después de agregarlo al proyecto, incorporará automáticamente todas las referencias agregadas a su ensamblaje principal.


{smartassembly} es uno de esos productos. Puede oscurecer o incrustar tus dlls.

Pruebe esto: http://www.smartassembly.com/

También puede hacer muchas mejoras en su aplicación para que se ejecute más rápido.

Y si. Puedes usarlo para WPF.

Actualización 08/06/2015: ILRepack 2.0.0 (que es una alternativa de código abierto para ILMerge) ahora es compatible con la mayoría de los casos de fusión de WPF: https://twitter.com/Gluckies/status/607680149157462016


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

Esto funcionó como un encanto para mí :) y es completamente gratis.

Agregar código en caso de que el blog desaparezca alguna vez.

1) Agregue esto a su archivo .csproj :

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

2) Haz que tu programa principal se vea así:

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

3) Agregue el método OnResolveAssembly :

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); } }


El reactor .NET tiene la función de fusionar los ensamblajes y no es muy caro.