2010-06-02 18 views
49

dwa problemy:użyciu ILMerge z .NET 4 biblioteki

1) Basic .NET Zgromadzenie nie wliczony w ILMerged Zgromadzenie

Mam problemy z używaniem ILMerge w mój post-budować po uaktualniania. NET 3.5/Visual Studio 2008 do .NET 4/Visual Studio 2010. Mam rozwiązanie z kilkoma projektami, których struktura docelowa jest ustawiona na ".NET Framework 4". I użyć następującego polecenia ILMerge scalić poszczególne DLL projektowych w jednym pliku 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 

Gdybym opuścić off określająca położenie katalogu .NET Framework 4, pojawia się „odwołania do zestawu nierozwiązanych niedozwolone: ​​system "błąd z ILMerge. Jeśli zostanę wyłączając określenie lokalizacji katalogu MSTest, otrzymuję komunikat o błędzie "Nierozstrzygnięte odwołanie do zestawu niedozwolone: ​​Microsoft.VisualStudio.QualityTools.UnitTestFramework".

Powyższe polecenie ILMerge działa i tworzy bibliotekę DLL. Kiedy odsyłającego wynika, że ​​DLL w innym projekcie .NET 4 C#, jednak i spróbuj użyć kodu w nim, pojawia się następujące ostrzeżenie:

The primary reference "MyILMergedDLL" could not be resolved because it has an indirect dependency on the .NET Framework assembly "mscorlib, Version=4.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" which has a higher version "4.0.65535.65535" than the version "4.0.0.0" in the current target framework.

Gdybym wtedy usunąć flagę /targetplatform:v4 a także używać MyILMergedDLL.dll , Pojawia się następujący błąd:

The type 'System.Xml.Serialization.IXmlSerializable' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.

Nie wydaje mi się, że powinienem to zrobić. Ktokolwiek używa mojego API MyILMergedDLL.dll nie powinien dodawać odniesień do jakichkolwiek bibliotek, do których się odwołuje. Jak mogę to obejść?

2) TypeLoadException tylko w przypadku korzystania Połączony Assembly

Edit: poza tym, nawet jeśli robię dodać odwołanie do System.Xml w projekcie konsumenta, który korzysta MyILMergedDLL.dll, wykorzystanie niektórych kodu w MyILMergedDLL.dll daje ten wyjątek:

System.TypeLoadException: Could not load type 'System.Func`2' from assembly 'MyILMergedDLL, Version=1.0.1.1, Culture=neutral, PublicKeyToken=...'.

To jest kod w moim projekcie konsumenckim; linia, która spowodowała TypeLoadException jest druga:

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

Szczególna konstruktor, który rzuca TypeLoadException jest zdefiniowany w publicznych klasy w MyILMergedDLL, a kiedy użyć tego konstruktora po przedstawieniu poszczególnych DLL projektu, to działa w porządku. Dopiero gdy użyję tego konstruktora podczas odwoływania się do biblioteki DLL połączonej z IL, otrzymam wyjątek. Nie wiem, co się dzieje.

Oto że konstruktor:

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

A base, do którego odnosi się ma ten kod:

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

Mimo że to pytanie nie wymaga alternatywy, muszę zalecić użycie [Costura Fody] (http://stackoverflow.com/questions/189549/embedding-dlls-in-a-compiled-executable/20306095#20306095). To działa jak urok. Pakowanie jest tak proste jak dodanie referencji NuGet :) – Matthias

Odpowiedz

47

Było very recent release rozwiązywać problemy x64.Skontaktować się z Mike Barnett bezpośrednio, jeśli nadal mają problemy (mbarnett na Microsoft kropka com)


Uzupełnienie. Jest coś bardzo, bardzo nie tak z Twoją opcją /lib:"C:\Windows\Microsoft.NET\Framework64\v4.0.30319". Ostatnio pojawiły się kłopoty z programistami po wydaniu programu .NET 4.5. Ten katalog to , a nie właściwy dla zestawów referencyjnych .NET 4.0. Jego zawartość zostaje nadpisana przez 4.5 złożeń, nie można jej już używać do kierowania instalacji .NET 4.0. Otrzymany błąd środowiska wykonawczego jest bardzo niezręczny, program nie może już znaleźć niektórych typów. Zazwyczaj bombardowanie przy użyciu atrybutu [Extension], czasami w interfejsie ICommand.

Te typy i niektóre inne zostały przeniesione z jednego zestawu do drugiego. Używanie właściwych zestawów referencyjnych jest wymaganiem twardym jak skała. Ci musi zastosowanie:

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

Regulacja pasujące do Twojego konkretnej maszyny i docelową wersję ramowego.

+0

Dzięki za informację. Nie mogę powiedzieć, patrząc na tę stronę, do czego są przeznaczone wydania: VS 2010, C#, .NET 4, ILMerge? –

+0

Nieważne, kopanie na stronie Mike'a Barnetta Widzę, że pracuje na ILMerge. :) –

+26

TAK! Nie pobrałem żadnego nowego wydania, ale nadal zaznaczam twoją poprawną odpowiedź (jedyną w tej chwili ...), ponieważ zaprowadziło mnie to na stronę Mike'a Barnetta, gdzie opisał użycie '/ targetplatform: v4, <ścieżka do katalogu framework v4> 'zamiast'/targetplatform: v4/lib: <ścieżka do katalogu framework v4>. –

21

Oto "Ciąg budowania postu" dla Visual Studio 2010 SP1, przy użyciu .NET 4.0. Buduję plik .exe z wszystkimi zawartymi w nim plikami sub-.dll.

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

Podstawowe wskazówki:

  • Wskazówka katalog "\ deploy \": to jest, gdy plik wyjściowy .exe kończy.
  • Zwróć uwagę na katalog "ILMerge \". Skopiowałem narzędzie ILMerge do mojego katalogu rozwiązań (dzięki czemu mogłem rozprowadzić źródło bez obawy o dokumentację instalacji ILMerge).

zaawansowane wskazówki:

Jeśli masz problemy z nim nie działa, należy dodać "echo" przed "post Build" polecenia. Następnie otwórz okno "Wyjście" w Visual Studio (Widok..Output) i sprawdź dokładnie polecenie wygenerowane przez Visual Studio. W moim konkretnym przypadku, dokładna komenda brzmiała:

"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 

Aktualizacja

dodanych w tym do mojego kroku "post Build", zastępuje wszystkie pliki .exe + .dll z jednym połączonym .exe. Utrzymuje on również plik .pdb debugowania nienaruszone:

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 
+0

Aktualizacja: Próbowałem tego łańcucha na dość złożonym projekcie z 10 niestandardowymi podzespołami i działało idealnie. – Contango

+1

+1 za włączenie ILMerge.exe z rozwiązaniem –

+0

Dla tych łączących się z. Dll jako wyjście, musisz zmienić/target: exe na/target: library I usunąć "$ (TargetDir) $ (TargetFileName)" inaczej będzie wczytaj główny plik .dll i w symbolu wieloznacznym * .dll, co powoduje błąd "ILMerge.Merge: ERROR !!: Duplicate type". – Despertar

2
+0

SmartAssembly może być drogie w porównaniu, ale jaki jest twój czas wart? Wydałem znacznie więcej pieniędzy w rozliczanych godzinach niż koszty SmartAssembly, aby przekonać się, że alternatywy nie działają i nie można ich debugować. Ten "drogi" produkt jest poparty jakością, łatwością użytkowania i doskonałym wsparciem. –

2

Można również dodać plik konfiguracyjny z następujących czynności:

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

Zrobione z here

+0

Gdzie umieszczasz ten plik? Jak to nazwałeś? – brenjt

+0

jeśli nie jest obecny, musisz utworzyć plik 'ildasm.exe.config' z xml, który umieściłem w mojej odpowiedzi – sebagomez

1

Wystarczy ustawić odniesień PresentationCore i PresentationFramework mieć "Kopia lokalna = True" we właściwościach Visual Studio (po wybraniu referencji w Eksploratorze rozwiązań). To rozwiąże problem bez twardego kodowania ścieżki szkieletu. Preferuję to rozwiązanie, ponieważ ścieżka jest różna w zależności od tego, czy serwer programisty/kompilacji ma 64-bitową czy 32-bitową wersję i nieuchronnie zmieni się wraz z wydaniem nowych wersji .NET/VS.