A DotNet Raider

My adventures in the .NET world!
posts - 49, comments - 12, trackbacks - 0

My Links

News

Website View Martino Bordin's profile on LinkedIn

Archives

Post Categories

Merge di DLL in un’applicazione WPF

Recentemente ho dovuto creare un’applicazione WPF che fosse facilmente distribuibile (leggi: distribuire solo l’exe).

Purtroppo il tool ILMerge non funziona per applicazioni WPF, a causa di problemi con le risorse contenute in esse (esistono comunque tool funzionanti di terze parti, a pagamento).

Seguendo questo post, ho creato un esempio che qui illustro e che potete scaricare qui.

L’applicazione visualizza semplicemente il fullname di due classi presenti in 2 assembly referenziati:

image

 

Per prima cosa è necessario modificare il file di progetto dell’applicazione WPF aggiungendo, dopo “Microsoft.CSharp.targets” , il seguente snippet:

  1. <Target Name="AfterResolveReferences">
  2.     <ItemGroup>
  3.       <EmbeddedResource Include="@(ReferenceCopyLocalPaths)" Condition="'%(ReferenceCopyLocalPaths.Extension)' == '.dll'">
  4.         <LogicalName>%(ReferenceCopyLocalPaths.DestinationSubDirectory)%(ReferenceCopyLocalPaths.Filename)%(ReferenceCopyLocalPaths.Extension)</LogicalName>
  5.       </EmbeddedResource>
  6.     </ItemGroup>
  7.   </Target>

Semplicemente, andiamo ad indicare di inserire tutti i file referenziati con estensione “.dll” come “emdedded resource” nell’exe principale. In questo modo eviteremo di eseguire a mano l’inclusione dell’ultima versione delle librerie compilate.

Nelle proprietà del progetto, impostiamo il seguente comando da eseguire durante la fase di post-build: “del $(TargetDir)*.dll” per cancellare tutte le librerie presenti nella “bin”, che non ci serviranno più...

image

 

Impostiamo quindi come oggetto di avvio la classe Bootstrapper (potete ovviamente cambiare il nome):

image

 

Questa, infine, è come definita la classe BootStrapper:

  1. public class BootStrapper
  2. {
  3.     [STAThread]
  4.     public static void Main(string[] args)
  5.     {
  6.         AppDomain.CurrentDomain.AssemblyResolve += OnResolveAssembly;
  7.         App.Main();
  8.     }
  9.  
  10.     private static Assembly OnResolveAssembly(object sender, ResolveEventArgs args)
  11.     {
  12.         var executingAssembly = Assembly.GetExecutingAssembly();
  13.         var assemblyName = new AssemblyName(args.Name);
  14.  
  15.         string path = string.Format("{0}.dll", assemblyName.Name);
  16.         if (assemblyName.CultureInfo.Equals(CultureInfo.InvariantCulture) == false)
  17.         {
  18.             path = string.Format(@"{0}\\cf4 {1}", assemblyName.CultureInfo, path);
  19.         }
  20.  
  21.         using (var stream = executingAssembly.GetManifestResourceStream(path))
  22.         {
  23.             if (stream == null)
  24.             {
  25.                 return null;
  26.             }
  27.  
  28.             var assemblyRawBytes = new byte[stream.Length];
  29.             stream.Read(assemblyRawBytes, 0, assemblyRawBytes.Length);
  30.             return Assembly.Load(assemblyRawBytes);
  31.         }
  32.     }
  33. }

 

Sostanzialmente ci agganciamo all’evento AssemblyResolve dell’AppDomain corrente, che viene sollevato ogni volta che la risoluzione di un’assembly fallisce, e ritorniamo l’assembly che abbia in canna nelle embedded resources.

Ecco infatti come si presenta il nostro exe “aprendolo” con ILSpy:

image

E’ anche più semplice di usare la riga di comando di ILMerge ! A bocca aperta

Print | posted on giovedì 5 aprile 2012 17:07 | Filed Under [ WPF VISUAL STUDIO ]

Feedback

Gravatar

# re: Merge di DLL in un’applicazione WPF

Ciao,
ho praticamente affrontato la seguente cosa solo che in vb net. Il problema di aggiungere la dll in "Embedded resources", si presenta quando riduciamo la dll. Nel momento in cui si aggiungono elementi alla dll il wpf non ha problemi, legge lo stesso la dll; ma nel momento in cui riduciamo la dll il wpf da un errore di memoria.
Articolo interessante e ben sviluppato.

Grazie

Nicola
10/11/2014 14:52 | Nicola
Comments have been closed on this topic.

Powered by:
Powered By Subtext Powered By ASP.NET