none
Fehlermeldung System.IO.FileLoadException beim Start einer MFC-Anwendung die teilweise mit /CLR übersetzt wurde RRS feed

  • 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

    Donnerstag, 18. Juni 2009 07:15

Antworten

Alle Antworten

  • Die Warnungen haben mit dem Fehler nichts zu tun...

    Die DLL die nicht gefunden wurde, wird doch angezeigt: IPC-NT
    Jochen Kalmbach (MVP VC++)
    Donnerstag, 18. Juni 2009 07:35
  • IPC-NT ist keine DLL sondern das Hauptprogramm (.EXE) selbst. Ich vermute deshalb, dass es eher eine Abhängigkeit ist die nicht gefunden wird. Aber welche ?
    Donnerstag, 18. Juni 2009 07:41
  • Starte doch mal das Programm mit "DependencyWalker":
    www.dependencywalker.com

    Ein CRT-Manifest hat Dein programm aber, oder?
    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++)
    Donnerstag, 18. Juni 2009 07:57
  • 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?

    Donnerstag, 18. Juni 2009 14:01
  • Dann aktiviere doch mal einen Break bei Exceptions! (Debug|Exceptions...; Break on Throw); dann siehst Du wo er die Exception wirft...

    Ist das Projekt gross? Sonnst könntest Du es mir mal zukommen lassen...


    Jochen Kalmbach (MVP VC++)
    Donnerstag, 18. Juni 2009 15:40
  • 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

    Freitag, 19. Juni 2009 05:43
  • 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++)
    Freitag, 19. Juni 2009 08:59
  • 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
    Freitag, 19. Juni 2009 12:31
  • 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++)
    Freitag, 19. Juni 2009 16:10
  • 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
    Montag, 22. Juni 2009 07:30
  • 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
    Montag, 22. Juni 2009 07:35
    Moderator