Benutzer mit den meisten Antworten
Fehlermeldung System.IO.FileLoadException beim Start einer MFC-Anwendung die teilweise mit /CLR übersetzt wurde

Frage
-
Beim Versuch eine MFC(C++)Anwendung auf .NET umzustellen, d.h. zumindest das Hauptprogramm und einige statische Bibliotheken mit der Option /CLR zu übersetzen, habe ich das Problem, dass das erstellte Programm beim Start immer mit folgender Meldung abbricht:
Eine nicht behandelte Ausnahme des Typs "System.IO.FileLoadException" ist in Unbekanntes Modul. aufgetreten. Zusätzliche Informationen: Die Datei oder Assembly "IPC-NT, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null" oder eine Abhängigkeit davon wurde nicht gefunden. Der Typ konnte nicht gefunden oder geladen werden. (Ausnahme von HRESULT: 0x80131522)
Gibt es eine Möglichkeit festzustellen, was da nicht gefunden bzw. geladen werden kann?
Die Projektmappe besteht aus diversen Projekten(typen) und wurde mit Visual Studio 2008 unter Windows XP übersetzt:
- MFC-Anwendung in gemeinsam genutzter DLL (mit /CLR übersetzt)
- Statische Bibliotheken mit C++ Code (mit /CLR übersetzt)
- Statische Bibliotheken mit C++ Code (ohne /CLR übersetzt)
- Statische Bibliotheken mit C Code (ohne /CLR übersetzt)
- Dynamische Bibliotheken mit C++ Code (ohne /CLR übersetzt)
- Dynamische Bibliotheken von Fremdanbietern
Bei der Übersetzung der statischen Bibliotheken sowie der MFC-Anwendung mit /CLR treten Compiler-Warnungen vom Typ C4793 auf:
- warning C4793: "CDlgWerkzeugBuchung::`vcall'{352}'" : Funktion wird als systemeigen kompiliert : vcall-Thunks, die nicht clrcall sind, müssen als systemeigen kompiliert werden.
- warning C4793: "CDlgSelectListe::SetColumns" : Funktion wird als systemeigen kompiliert : Varargs werden von "/clr" nicht unterstützt.
- warning C4793: "DlgMessage" : Funktion wird als systemeigen kompiliert :Es wurde eine systeminterne Funktion gefunden, die in verwaltetem Code nicht unterstützt wird.
Haben diese Warnungen vielleicht etwas mit dem Ausführungsproblem zu tun ?
Speedy
Antworten
-
Die Lösung ist, die Übersetzung mit der Compiler-Option /GF um die Anzahl der Felder in einer Klasse zu minimieren, da die Anzahl auf 65536 beschränkt ist.
Hier die entsprechende Diskussion:
http://social.msdn.microsoft.com/forums/en-US/vclanguage/thread/a52c3ee4-63f9-4ccd-b38c-b5cbefabc414/
Speedy- Als Antwort markiert Speedy G. _ Freitag, 19. Juni 2009 12:33
Alle Antworten
-
Starte doch mal das Programm mit "DependencyWalker":
Ein CRT-Manifest hat Dein programm aber, oder?
www.dependencywalker.com
Die Fehlermeldung ist ja "COR_E_TYPELOAD"...
Kannst Du die Anwendung im Debugger starten? Geht es dann?
Hast Du irgendwo StrongNames?
Jochen Kalmbach (MVP VC++)- Bearbeitet Jochen Kalmbach Donnerstag, 18. Juni 2009 08:03
-
Stand nach 1 Tag erfolgloser Fehlersuche: Keine Besserung in Sicht
- Dependency Walker findet keine fehlenden DLL
- CRT-Manifest ist selbstverständlich vorhanden
- Start unter Debugger bringt eben o.g. Meldung, aber keine Codestelle wo man mehr daraus schliessen könnte
- Keine StrongNames verwendet
Mich wundert dass die Meldung sagt "in unbekanntes Modul". Da muss doch irgendwas prinzipiell schief laufen und nicht 'einfach' eine normale Abhängigkeit fehlen. Sonst würde doch (hoffentlich!) die Fehlermeldung das entsprechende Modul nennen? -
Habs zuerst mal noch mit der Exception versucht, da das Projekt schon ziemlich gross ist. Folgende Execption wird ausgelöst:
Eine Ausnahme (erste Chance) bei 0x7c812afb (kernel32.dll) in IPC-NT.exe: Microsoft C++-Ausnahme: EETypeLoadException an Speicherposition 0x0012ea64..
Der Calltree sieht dann so aus:
kernel32.dll!RaiseException() + 0x52 Bytes
[Unten angegebene Rahmen sind möglicherweise nicht korrekt und/oder fehlen, keine Symbole geladen für kernel32.dll]
msvcr80.dll!_CxxThrowException() + 0x46 Bytes
mscorwks.dll!ThrowTypeLoadException() + 0xe5 Bytes
mscorwks.dll!Assembly::ThrowTypeLoadException() + 0x76 Bytes
mscorwks.dll!Assembly::ThrowTypeLoadException() + 0x13 Bytes
mscorwks.dll!MethodTableBuilder::BuildMethodTableThrowException() + 0x54 Bytes
mscorwks.dll!MethodTableBuilder::BuildMethodTableThrowException() + 0x36 Bytes
mscorwks.dll!MethodTableBuilder::InitializeFieldDescs() - 0x8e3cb Bytes
mscorwks.dll!MethodTableBuilder::BuildMethodTableThrowing() + 0x500 Bytes
mscorwks.dll!ClassLoader::CreateTypeHandleForTypeDefThrowing() + 0x47b Bytes
mscorwks.dll!ClassLoader::CreateTypeHandleForTypeKey() + 0x52 Bytes
mscorwks.dll!ClassLoader::DoIncrementalLoad() + 0x5c Bytes
mscorwks.dll!ClassLoader::LoadTypeHandleForTypeKey_Inner() + 0x103 Bytes
mscorwks.dll!ClassLoader::LoadTypeHandleForTypeKey_Body() + 0xeb Bytes
mscorwks.dll!ClassLoader::LoadTypeHandleForTypeKey() + 0xa4 Bytes
mscorwks.dll!ClassLoader::LoadTypeDefThrowing() + 0x66b3 Bytes
mscorwks.dll!MemberLoader::GetDescFromMemberDefOrRefThrowing() + 0x147f21 Bytes
mscorwks.dll!MemberLoader::GetMethodDescFromMemberDefOrRefOrSpecThrowing() + 0x81 Bytes
mscorwks.dll!Module::FindMethodThrowing() + 0x24 Bytes
mscorwks.dll!Module::FixupVTables() + 0xfd76d Bytes
> mscorwks.dll!DomainFile::DoIncrementalLoad() + 0xd39 Bytes
mscorwks.dll!AppDomain::TryIncrementalLoad() + 0x80 Bytes
mscorwks.dll!AppDomain::LoadDomainFile() + 0xf9 Bytes
mscorwks.dll!AppDomain::LoadDomainAssembly() + 0x7623 Bytes
mscorwks.dll!SystemDomain::ExecuteMainMethod() + 0x285 Bytes
mscorwks.dll!ExecuteEXE() + 0x49 Bytes
mscorwks.dll!__CorExeMain@0() + 0x98 Bytes
mscoree.dll!_CorExeMain() + 0x34 Bytes
kernel32.dll!RegisterWaitForInputIdle() + 0x49 Bytes
Vermute mal DoIncrementalLoad() oder FixupVTables() werfen die Exception . Das Dissassembly sagt mir allerdings leider nichts.
DoIncrementalLoad():
DomainFile::PreLoadLibrary:
79EBD2BB push ebp
79EBD2BC mov ebp,esp
79EBD2BE sub esp,1Ch
79EBD2C1 push ebx
79EBD2C2 mov ebx,ecx
79EBD2C4 mov ecx,dword ptr [ebx+8]
79EBD2C7 call PEFile::CanLoadLibrary (79EBD293h)
79EBD2CC test eax,eax
79EBD2CE je DomainFile::PreLoadLibrary+19h (79F6633Fh)
79EBD2D4 pop ebx
79EBD2D5 leave
79EBD2D6 ret
79EBD2D7 mov ecx,esi
79EBD2D9 call DomainFile::PostLoadLibrary (79EBD2E3h)
79EBD2DE jmp DomainFile::DoIncrementalLoad+0B4h (79EBC5E6h)
DomainFile::PostLoadLibrary:
FixupVTables():
79FBB0B9 je Module::FixupVTables+312h (7A024B6Eh)
79FBB0BF push dword ptr [ebp-40h]
79FBB0C2 mov ecx,ebx
79FBB0C4 call Module::FindMethodThrowing (79FBAF62h)Speedy
-
Vielleicht findest Du ja hier Antworten:
http://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/1c9c687f-4221-4cdd-8497-dd3bba97de6a/
Mir fällt gerade nichts mehr ein...
Jochen Kalmbach (MVP VC++) -
Die Lösung ist, die Übersetzung mit der Compiler-Option /GF um die Anzahl der Felder in einer Klasse zu minimieren, da die Anzahl auf 65536 beschränkt ist.
Hier die entsprechende Diskussion:
http://social.msdn.microsoft.com/forums/en-US/vclanguage/thread/a52c3ee4-63f9-4ccd-b38c-b5cbefabc414/
Speedy- Als Antwort markiert Speedy G. _ Freitag, 19. Juni 2009 12:33
-
Ich rate Dir, dass DU die /clr-Option wirklich nur für die Datein aktivierst, welche auch .NET benötigen!
Es kann auch sonst noch sehr viele andere Nebeneffekte haben, wenn Du es für alles aktivierst
Siehe auch z.B.:
http://blog.kalmbach-software.de/2009/05/12/ccli-quiz-answer/
Jochen Kalmbach (MVP VC++) -
Hallo Jochen,
danke für die Warnung. Kannst du mir sagen welche Programmteile unbedingt mit /CLR übersetzt sein müssen um .NET zu nutzen, genauer gesagt um Forms-(Dialoge) nutzen zu können.
- Hauptprgramm ohne direkten .NET-Code und kein direkter Aufruf von .NET-Funktionen
- statische Bibliothek 1 ohne eigentlichen .NET-Code aber mit Aufrufen von .NET-Funktion aus der statischen Bibliothek 2
- statische Bibliothek 2 mit .Net-Code (Windows-Forms-Dialoge)
Muss in einem solchen Fall neben Bibliothek 1 und 2 auch das eigentliche Hauptprogramm mit /CLR übersetzt werden ?
Speedy -
Du musst nur die C++ Dateien mit CLR übersetzen, die auch .NET Code nutzen. Alle anderen C++ Dateien benötigen diesen Schalter nicht.
Für den Fall 1 und 2 gilt einfach auch wieder: Enthält diese C++ Datei Aufrufe von .NET Code dann setze CLR ansonsten nicht.
Ich empfehle Dir klare Schnittstellen. D.h. z.B. eine Klasse die den .NET Code komplett kapselt. Alle Module können diese Klasse nutzen ohne .NET und /CLR zu benötigen. Die Klasse selbst und das Modul in dem sie existiert wird mit /CLR kompiliert.
Oder anders gesagt. Du solltest .NET Code und nativen Code gut und klar trennen.
Ich hoffe das macht das ganze klarer.
Martin Richter -- MVP for VC++ [Germany] -- http://blog.m-ri.de