it-swarm.com.de

verwenden von ILMerge mit .NET 4-Bibliotheken

Zwei Probleme:

1) Grundlegende .NET-Assembly nicht in ILMerged-Assembly enthalten

Ich habe Probleme mit ILMerge in meinem Post-Build nach einem Upgrade von .NET 3.5/Visual Studio 2008 auf .NET 4/Visual Studio 2010. Ich habe eine Lösung mit mehreren Projekten, deren Zielframework auf ".NET Framework 4" gesetzt ist. . Ich verwende den folgenden ILMerge-Befehl, um die einzelnen Projekt-DLLs in einer einzelnen DLL zusammenzuführen:

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 

Wenn ich den Speicherort des .NET 4-Framework-Verzeichnisses nicht angeben, erhalte ich die Fehlermeldung "Nicht aufgelöste Assembly-Referenz nicht zulässig: System" von ILMerge. Wenn ich den Speicherort des MSTest-Verzeichnisses nicht angeben, erhalte ich die Fehlermeldung "Unaufgelöste Assemblyreferenz nicht zulässig: Microsoft.VisualStudio.QualityTools.UnitTestFramework".

Der obige Befehl ILMerge funktioniert und erzeugt eine DLL. Wenn ich jedoch auf dieses DLL in einem anderen .NET 4 C # -Projekt verweise und versuche, Code darin zu verwenden, erhalte ich die folgende Warnung:

Der primäre Verweis "MyILMergedDLL" konnte nicht aufgelöst werden, da er indirekt von der .NET Framework-Assembly "mscorlib, Version = 4.0, Culture = neutral, PublicKeyToken = b77a5c561934e089" mit einer höheren Version als "4.0.65535.65535" abhängig ist "4.0.0.0" im aktuellen Zielframework.

Wenn ich dann das Flag /targetplatform:v4 entferne und versuche, MyILMergedDLL.dll zu verwenden, erhalte ich die folgende Fehlermeldung:

Der Typ 'System.Xml.Serialization.IXmlSerializable' ist in einer Assembly definiert, auf die nicht verwiesen wird. Sie müssen einen Verweis auf Assembly 'System.Xml, Version = 4.0.0.0, Culture = neutral, PublicKeyToken = b77a5c561934e089' hinzufügen.

Es scheint nicht so, als müsste ich das tun. Wer meine MyILMergedDLL.dll-API verwendet, sollte keine Verweise auf die von ihm referenzierten Bibliotheken hinzufügen müssen. Wie kann ich das umgehen?

2) Nur TypeLoadException, wenn zusammengeführte Assembly verwendet wird

Edit: darüber hinaus, auch wenn ich im Consumer-Projekt, das MyILMergedDLL.dll verwendet, einen Verweis auf System.Xml hinzufüge, führt die Verwendung von etwas Code in MyILMergedDLL.dll zu dieser Ausnahme:

System.TypeLoadException: Der Typ 'System.Func`2' konnte nicht aus Assembly 'MyILMergedDLL, Version = 1.0.1.1, Culture = neutral, PublicKeyToken = ...' geladen werden.

Dies ist der Code in meinem Verbraucherprojekt. Die Zeile, die die TypeLoadException verursacht hat, ist die zweite:

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

Der bestimmte Row-Konstruktor, der die TypeLoadException auslöst, ist in einer öffentlichen Klasse in MyILMergedDLL definiert. Wenn ich diesen Konstruktor beim Referenzieren der einzelnen Projekt-DLLs verwende, funktioniert das problemlos. Nur wenn ich diesen Konstruktor verwende, wenn auf das IL-merged DLL verwiesen wird, erhalte ich die Ausnahme. Ich weiß nicht was los ist.

Hier ist dieser Konstruktor:

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

Und die base, auf die sie sich bezieht, hat diesen Code:

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

Es gab ein sehr aktuelles Release , um x64-Probleme zu lösen. Wenden Sie sich direkt an Mike Barnett, wenn Sie weiterhin Probleme haben (mbarnett unter Microsoft dot com)


Nachtrag. Ihre /lib:"C:\Windows\Microsoft.NET\Framework64\v4.0.30319" -Option ist sehr, sehr falsch. Dies hat in letzter Zeit viele Programmierer in Schwierigkeiten gebracht, nachdem .NET 4.5 veröffentlicht wurde. Dieses Verzeichnis ist nicht das richtige für .NET 4.0-Referenzassemblys. Sein Inhalt wird mit den Assemblys 4.5 überschrieben. Sie können ihn nicht mehr für eine .NET 4.0-Installation verwenden. Der Laufzeitfehler, den Sie bekommen, ist sehr umständlich, das Programm kann bestimmte Typen nicht mehr finden. Bombardieren Sie normalerweise das Attribut [Extension], manchmal die ICommand-Schnittstelle.

Diese und einige andere Typen wurden von einer Versammlung in eine andere versetzt. Die Verwendung der richtigen Referenzbaugruppen ist eine unabdingbare Voraussetzung. Sie müssen verwenden:

 /lib:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0"

Passen Sie die Einstellungen an Ihren Computer und Ihre Ziel-Framework-Version an.

48
Hans Passant

Hier ist der "Post Build String" für Visual Studio 2010 SP1 unter Verwendung von .NET 4.0. Ich baue eine Konsolen-EXE-Datei mit allen darin enthaltenen Sub-DLL-Dateien.

"$(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

Grundlegende Hinweise:

  • Beachten Sie das Verzeichnis "\ deploy \": Hier endet die .exe-Ausgabedatei.
  • Beachten Sie das Verzeichnis "ILMerge \". Ich habe das ILMerge-Dienstprogramm in mein Lösungsverzeichnis kopiert (damit ich die Quelle verteilen kann, ohne sich um die Installation von ILMerge kümmern zu müssen).

Fortgeschrittene Hinweise:

Wenn Sie Probleme haben, damit es nicht funktioniert, fügen Sie vor dem Befehl "Post Build" ein "Echo" ein. Öffnen Sie dann das Fenster "Ausgabe" in Visual Studio (View..Output) und überprüfen Sie den genauen Befehl, den Visual Studio tatsächlich generiert hat. In meinem speziellen Fall lautete der genaue Befehl:

"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

Update

Dies wurde meinem Schritt "Post Build" hinzugefügt und ersetzt alle EXE- und DLL-Dateien durch eine einzige kombinierte EXE-Datei. Es hält auch die Debugging-.pdb-Datei intakt:

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
21
Contango

Sie können auch eine Konfigurationsdatei mit folgendem Inhalt hinzufügen:

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

Aus hier

2
sebagomez

Andere Alternativen:

2
Contango

Legen Sie für PresentationCore- und PresentationFramework-Referenzen einfach fest, dass im Eigenschaftenfenster von Visual Studio "Copy Local = True" angezeigt wird (nachdem Sie die Referenzen im Projektmappen-Explorer ausgewählt haben). Es löst das Problem, ohne den Rahmenpfad fest zu codieren. Ich bevorzuge diese Lösung, da der Pfad unterschiedlich ist, je nachdem, ob der Entwickler-/Build-Server 64-Bit- oder 32-Bit-Server ist und sich zwangsläufig mit der Veröffentlichung neuer .NET/VS-Versionen ändert.

1
Tony Wall

Für diejenigen, die ILMerge aus Community-Aufgaben verwenden in .csproj:

<ILMerge InputAssemblies="@(MergeAssemblies)"
         ...
         TargetPlatformVersion="v4"
         TargetPlatformDirectory="$(ProgramFiles)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0"
/>

Wir verfügen über gemischte CI-Build-Agenten. Daher verwenden wir die Umgebungsvariable $ (ProgramFiles), um den richtigen Pfad anzugeben (Laufwerk + x86/x64-Ordner), wie es von MSBuild Team empfohlen wurde.

0
ursa