51 votes

utiliser ILMerge avec les bibliothèques .NET 4

Deux problèmes:

1) de Base .NET un Montage Non Inclus dans ILMerged Assemblée

Je vais avoir de la difficulté à utiliser ILMerge dans mon post-construire après la mise à niveau à partir de .NET 3.5 et Visual Studio 2008 .NET 4/Visual Studio 2010. J'ai une Solution avec plusieurs projets dont la cible cadre est réglé sur ".NET Framework 4". J'utilise la suite ILMerge commande pour fusionner le projet individuel Dll en une seule DLL:

if not $(ConfigurationName) == Debug
  if exist "C:\Program Files (x86)\Microsoft\ILMerge\ILMerge.exe"
    "C:\Program Files (x86)\Microsoft\ILMerge\ILMerge.exe"
      /lib:"C:\Windows\Microsoft.NET\Framework64\v4.0.30319"
      /lib:"C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\PublicAssemblies"
      /keyfile:"$(SolutionDir)$(SolutionName).snk"
      /targetplatform:v4
      /out:"$(SolutionDir)bin\development\$(SolutionName).dll"
      "$(SolutionDir)Connection\$(OutDir)Connection.dll"
      ...other project DLLs...
      /xmldocs 

Si je quitte la spécification de l'emplacement de l' .NET 4 cadre de répertoire, j'obtiens une "en Suspens assemblée de référence non autorisé: le Système" erreur de ILMerge. Si je quitte la spécification de l'emplacement de la MSTest répertoire, j'obtiens une "en Suspens assemblée de référence non autorisé: Microsoft.VisualStudio.QualityTools.UnitTestFramework d'erreur".

Le ILMerge de commande ci-dessus fonctionne et produit une DLL. Quand j'ai la référence de cette DLL dans un autre .NET 4 projet C#, cependant, et essayez d'utiliser le code, j'obtiens le message d'avertissement suivant:

La base de référence "MyILMergedDLL" ne pouvait pas être résolu, car il a une dépendance indirecte sur l' .NET Framework assemblée "mscorlib, Version=4.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", qui a une version supérieur "4.0.65535.65535" à la version "4.0.0.0" dans l'infrastructure actuelle.

Si je puis retirez l' /targetplatform:v4 drapeau et essayer de l'utiliser MyILMergedDLL.dll, j'obtiens l'erreur suivante:

Le type de Système.Xml.La sérialisation.IXmlSerializable " est défini dans une assemblée qui n'est pas référencé. Vous devez ajouter une référence à l'assembly 'System.Xml Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.

Il ne semble pas comme je devrais le faire. Celui qui utilise mon MyILMergedDLL.dll l'API ne devraient pas avoir à ajouter des références à ce que les bibliothèques de références. Comment puis-je contourner ce problème?

2) TypeLoadException Uniquement Lors De L'Utilisation Fusionné Assemblée

Edit: au-delà de cela, même si je dois ajouter une référence à l' System.Xml dans le projet des consommateurs qui utilise MyILMergedDLL.dll en faisant usage d'un code de MyILMergedDLL.dll donne à cette exception:

Système.TypeLoadException: impossible de charger le type de Système.Func`2' à partir de l'assembly 'MyILMergedDLL, Version=1.0.1.1, Culture=neutral, PublicKeyToken=...'.

C'est le code dans mon projet des consommateurs; la ligne qui a provoqué l' TypeLoadException est la seconde:

var keys = new[] {"a", "b", "c"};
var row = new Row(keys);

Le particulier Row constructeur qui lève l' TypeLoadException est définie dans une classe publique en MyILMergedDLL, et quand j'utilise ce constructeur lors de la référence à la personne du projet de Dll, il fonctionne très bien. C'est seulement lorsque j'utilise ce constructeur lors du référencement de l'IL-fusionné DLL que je reçois l'exception. Je ne sais pas ce qu'il se passe.

Voici que le constructeur:

public Row(IEnumerable<string> keys) : base(keys) { }

Et l' base , à laquelle il est fait référence a ce code:

foreach (string key in keys.Where(
    key => !string.IsNullOrEmpty(key)
))
{
    _dic.Add(key, string.Empty);
}

48voto

Hans Passant Points 475940

Il y avait une version très récente pour résoudre les problèmes de x64. Contactez Mike Barnett directement si vous avez toujours des problèmes (mbarnett à microsoft dot com)

22voto

Contango Points 7976

Ici, c'est le "Post Chaîne de Build" pour Visual Studio 2010 SP1, en utilisant .NET 4.0. Je suis la construction d'une console .exe avec tous les sub-.dll les fichiers inclus.

"$(SolutionDir)ILMerge\ILMerge.exe" /out:"$(SolutionDir)\deploy\$(TargetFileName)" "$(TargetDir)$(TargetFileName)" "$(TargetDir)*.dll" /target:exe /targetplatform:v4,C:\Windows\Microsoft.NET\Framework64\v4.0.30319 /wildcards

Conseils basiques:

  • Notez le "\deploy\": c'est où la sortie .exe fichier se termine.
  • Notez le "ILMerge\". J'ai copié le ILMerge utilitaire dans ma solution répertoire (donc j'ai pu distribuer le code source sans avoir à vous soucier de documentation de l'installation de ILMerge).

Avancée de conseils:

Si vous avez des problèmes avec elle, pas de travail, ajouter un "echo" avant le "Post-construction de la commande". Ensuite, ouvrez la "Sortie" de la fenêtre de Visual Studio (Vue..Sortie), et vérifiez que la commande exacte que Visual Studio a effectivement généré. Dans mon cas particulier, la commande exacte est:

"T:\PhiEngine\CSharp\ILMerge\ILMerge.exe" /out:"T:\PhiEngine\CSharp\Server Side\deploy\NfServiceDataHod.History.exe" "T:\PhiEngine\CSharp\Server Side\NfServiceDataHod\bin\Debug\NfServiceDataHod.History.exe" "T:\PhiEngine\CSharp\Server Side\NfServiceDataHod\bin\Debug\*.dll" /target:exe /targetplatform:v4,C:\Windows\Microsoft.NET\Framework64\v4.0.30319 /wildcards

Mise à jour

Ajouté ça à mon "Post-construction" de l'étape, il remplace toutes les .exe + .les fichiers dll avec un seul combiné .exe. Elle conserve également le débogage .fichier pdb intacte:

rem Create a single .exe that combines the root .exe and all subassemblies.
"$(SolutionDir)ILMerge\ILMerge.exe" /out:"$(TargetDir)$(TargetName).all.exe" "$(TargetDir)$(TargetName).exe" "$(TargetDir)*.dll" /target:exe /targetplatform:v4,C:\Windows\Microsoft.NET\Framework64\v4.0.30319 /wildcards
rem Remove all subassemblies.
del *.dll
rem Remove all .pdb files (except the new, combined pdb we just created).
ren "$(TargetDir)$(TargetName).all.pdb" "$(TargetName).all.pdb.temp"
del *.pdb
ren "$(TargetDir)$(TargetName).all.pdb.temp" "$(TargetName).all.pdb"
rem Delete the original, non-combined .exe.
del "$(TargetDir)$(TargetName).exe"
rem Rename the combined .exe and .pdb to the original name we started with.
ren "$(TargetDir)$(TargetName).all.pdb" "$(TargetName).pdb"
ren "$(TargetDir)$(TargetName).all.exe" "$(TargetName).exe"
exit 0

2voto

Contango Points 7976

2voto

sebagomez Points 3305

Vous pouvez également ajouter un fichier de configuration avec les éléments suivants:

 <?xml version ="1.0"?>
<configuration>
  <startup useLegacyV2RuntimeActivationPolicy="true">
    <requiredRuntime safemode="true" imageVersion="v4.0.30319" version="v4.0.30319"/>
  </startup>
</configuration>
 

Tiré d' ici

1voto

Code Chief Points 422

Il suffit de définir les références PresentationCore et PresentationFramework pour que "Copier Local = True" dans la fenêtre de propriétés de Visual Studio (après avoir sélectionné les références dans l'Explorateur de solutions). Cela résoudra le problème sans coder en dur le chemin du framework. Je préfère cette solution car le chemin est différent selon que le serveur développeur / build est 64 bits ou 32 bits et changera inévitablement au fur et à mesure de la sortie des nouvelles versions .NET / VS.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X