steinadler Geschrieben 16. Juni 2010 Geschrieben 16. Juni 2010 (bearbeitet) Hallo ihr Lieben, in einem Programm rufe ich im Main() über Application.Run() ein Formular aus einer eigenen DLL auf. Wenn allerdings diese DLL fehlt und ich starte das Programm kommt aber nur eine Fehlermeldung "... hat ein Problem festgestellt und muss beendet werden". Klicke ich in diesem Dialog auf Debuggen, erscheint im VisualStudio plötzlich eine Exception "FileNotFoundException". Kann man die irgendwie abfangen? Habe schon um den Formularaufruf (Application.Run()) ein Try-Catch gebaut, aber er erzeugt die Exception irgendwie erst gar nicht. Es sieht eher so aus, als ob er die Main() gar nicht erst abarbeitet. Mein zweiter Test war, eine Messagebox vor dem Formularaufruf ausgeben zu lassen, aber nicht mal dieses funktionierte. Die Main() sieht im Prinzip so aus: Main() { Application.Run(new DLLForm()); // Vorprogramm ausführen Application.Run(new ProgramForm()); // Hauptprogramm ausführen } Hat jemand eine Idee? Wenn ich das Formular im Konstruktor der ProgramForm anzeige, funktionierts komischerweise auch mit der Exception. Bearbeitet 16. Juni 2010 von steinadler Einfall Zitieren
HJST1979 Geschrieben 16. Juni 2010 Geschrieben 16. Juni 2010 Main() { Application.Run(new DLLForm()); // Vorprogramm ausführen Application.Run(new ProgramForm()); // Hauptprogramm ausführen } Bin zwar jetzt nicht der C# - Programmierer aber wenn du die beiden Anweisungen jeweils in ein Try- Catch einfügst sollte es gehen Unter VB würde ich schreiben Try Anweisung Catch ex as Exception msgbox ("DLL nicht gefunden") End Try Gruß Hans-Jörg Zitieren
Gateway_man Geschrieben 16. Juni 2010 Geschrieben 16. Juni 2010 Das wirst du so nicht hinbekommen. Auch nicht mit einem Try Catch Fehlerhandling. Wenn du einer Anwendung einen Verweis hinzufügst spielst sich beim Starten folgendes ab: => Die Laufzeitumgebung sucht bevor die Anwendung überhaupt gestartet wird nach den dafür Notwendigen Ressourcen. Zuerst wird dannach in dem Pfad gesucht welcher die zu startende Anwendung beinhaltet und bei misserfolg dann im System32 Ordner. Wenn die Referenzierte Ressource nicht auffindbar ist, wirft die Laufzeitumgebung einen Fehler und es kommt garnicht zum Start deines Programms. Ich habe selbst möglichkeiten gesucht soetwas im .NET zu umgehn. Prinzipiell ist es möglich, nur der Aufwand ist dermaßen enorm. Ich rede davon die Dll dynamisch aufzurufen. D. h. du verweist in deinem Projekt nicht länger auf die entsprechenden DLL's sonder fügst an die Stelle wo du die jeweiligen Felder/Prozeduren/Funktionen benötigst eine Variable vom Typ Objekt ein und füllst diese per Reflection Klasse mit dem Inhalt deiner DLL. So kannst du auch ein Fehlerhandling machen. Sieht dann ungefähr so aus: Dim asmbl As [Assembly] = [Assembly].LoadFrom(path) Nachteil: Natürlich gibts so einen Luxus wie Intelisense auf diese weiße nicht. Lg Gateway Zitieren
Mcolli Geschrieben 16. Juni 2010 Geschrieben 16. Juni 2010 ne bessere Antwort als Gateways wirst Du nicht bekommen. Das Problem bei dynamischen Verweisen ist, dass ein Teil der typsicherheit flöten geht. Ein als Verweis referenziertes Assembly teilt dem Compiler u.a. mit welche Typen durch das Assambly möglich sind. Wenn Deine DLL z.B. die Klasse "meinNamespace.MeineKlasse" enthält kannst Du fortan Sachen in den Code reinschreiben wie using meinNamspace; ..... MeineKlasse toll = new MeineKlasse(); Ohne die using Direktive ist die Klasse im aktuellen Kontext nicht vorhanden. Ohne den Verweis auf die DLL kannst Du meinNamspace auch nicht in der Using Direktive verwenden .... Du kannst mehr oder weniger das Assembly wie oben beschrieben dynamisch zur Laufzeit und NICHT zum Compilezeitpunkt nachladen. Dann muss man aber auch mittels der Invoke Methode auf Member der zum Compilezeitpunkt unbekannten Klasse zugreifen: Assembly assem = Assembly. LoadFile("pfadAlsString"); Object meneInstanz = assem CreateInstance("MeineKlasse ", false, BindingFlags.ExactBinding, null, new Object[] { }, null, null); // InvokeMember ist statisch und in "Type" deffiniert. String meineKlasseStringProperty = (String) meineInstanz.GetType().InvokeMember("StringProperty", BindingFlags.GetProperty, null, meineInstanz, null); Assembly Klasse MSDN Type Klasse MSDN Zitieren
Gateway_man Geschrieben 16. Juni 2010 Geschrieben 16. Juni 2010 PS: Im diesem Aspekt lege ich mal ne kleine Spur aus Brotkrümmeln. In der am 12.April erschienen Version 4.0 von C# gibt es unter anderem einen neuen komplexen Datentyp namens Dynamic. Ich selbst habe leider noch keine Zeit gehabt VS2010 zu installieren und die neuen Funktionalitäten von C# ausgiebig zu genießen . Jedoch war ich bei einer Präsi von Microsoft dabei, wo einige Beispiele gezeigt wurden. Mit hilfe dieses Datentyps ist es beispielsweise möglich während der Laufzeit ganze Klassen dynamisch zu laden sowie zu erstellen. Was natürlich auch die Fehlerqote zur Laufzeit erhöht. Nuja ich bin selbst noch nicht ganz hinter dieses Konzept gestiegen. Aber sah auf jedenfall ganz Interessant aus. Lg Gateway Zitieren
steinadler Geschrieben 17. Juni 2010 Autor Geschrieben 17. Juni 2010 Wenn du einer Anwendung einen Verweis hinzufügst spielst sich beim Starten folgendes ab: => Die Laufzeitumgebung sucht bevor die Anwendung überhaupt gestartet wird nach den dafür Notwendigen Ressourcen. Zuerst wird dannach in dem Pfad gesucht welcher die zu startende Anwendung beinhaltet und bei misserfolg dann im System32 Ordner. Komischerweise tritt das Problem aber nur auf, wenn ich das Formular der DLL in der Main() selbst aufrufe. Rufe ich das Formular im Konstruktor des Programmformulars auf, funktioniert alles bestens. Auch der Try-Catch Block um die Application.Run()-Funktion in der Main(). Die DLL ist natürlich als Verweis eingebunden. Also prüft er beim Programmstart doch nicht alle eingebundenen Verweise??? Zitieren
Mcolli Geschrieben 17. Juni 2010 Geschrieben 17. Juni 2010 Die überprüfung findet zum COMPILE-Zeitpunkt statt....das ist dann wenn Du nen "Build" machst und ne Exe rauskriegst, zu min. wenn alles glatt geht. Die Überprüfung bezieht sich aber nur auf den Rechner auf dem auch der Build veranlasst wird. Damit ist in keinsterweise Sichergestellt, dass der Anwender-Rechner über die entsprechenden Assemblys verfügt. Du kannst Dir das relativ leicht klar machen, wenn Du versuchst für eine ATI Grafikkarte unter Windows XP das Catalyst Control Center zu installieren und auf dem Rechner gar kein .Net Framework 2.0 oder höher ist. Dann bricht der nämlich die Installation ab. D.h. in dem Fall wird die Tauglichkeit des Zielsystem mehr oder weniger im Installer überprüft. Grundsätzlich wird folgendermaßen vorgegangen wenn zur Laufzeit auf Programm-Externe-Assemblys zugegriffen wird: ES WIRD GANZ GENAU DAS ASSEMBLY GELADEN WAS BESCHRIEBENWORDEN IST. Es gibt keine 2 gleichen Assemblys auch wenn die Semantik die gleiche ist. Bei den Eigenschaften zu den Verweisen in Visual Studio (Verweis auswählen und Eigenschaftsfenster gucken) kann man Einfluss darauf nehmen, dass auch ein Assembly mit ner anderen GUID aber gleicher Namen und ggf. Versionsnummer pi pa po genommen werden darf. Soweit ich das in Erinnerung habe muss kein absoluter Pfad angegeben werden. Dann wird der GAC durchleuchtet, wenn da nix is in der Registry nachgeschaut und wenn da auch nix ist im Zweifel im Startordner der Anwendung was passendes gesucht. So kommen wir zu den Links: Evtl könnte Dir dasbei Deinem Problem weiterhelfen. Alle 3 Methoden da zielen darauf ab, dass das Assembly "vorhanden" sein wird. Die 3 Methode soltle interessant für dich sein. Da kannste mit dem AssemblyResolve-Ereignis praktisch einen Handler hinterlegen der für den CLR dann sicherstellen MUSS dass ein entsprechend gültiges Assembly zurückgegeben wird. Das ist aber als AUSNAHME gedacht, wenn das auf dem Entwicklungsrechner liegende genügende Assemby nicht zwangsläufig auf dem Zielrechner ist sondern evtl nur ein vergelichbares ("Visual Studio" muss ja wissen welche Methode es Dir zu einer Deiner Klassen z.B. nach drücken von "." anbieten kann). Da kannste also nicht Mini Maus zurück geben wenns Pluto nur im Micky Maus Assembly gibt. Und wenn Du Dich weiterbilden willst ist das auch ganz nett. Zitieren
Empfohlene Beiträge
Dein Kommentar
Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.