Hi, ich will eine in VB6 erstellte DLL in C# benutzen. In VB6 habe ich dafür eine ActiveXDLL erstellt und diese mittels TlbImp-Tool exportiert. Füge ich die DLL als Verweis ein, kann ich ganz regulär auf den Namespace zugreifen und meine Funktionen wie gewohnt nutzen. Problem an dieser Methode ist allerdings, das die in der DLL aufgerufene Funktion, abstürzen kann. In C# reagiere ich mittels eines Watchdogs darauf, beende die Berechnung und zeige eine entsprechende Meldung an. Will ich jedoch anschließend eine neue Berechnung ausführen, bekomme ich nurnoch Timeouts und sehe die entsprechende Fehlermeldung. Das Problem liegt darin, das das "killen", den Zustand der DLL nicht sauber beendet. Ich brauche daher ein Verfahren, was die DLL komplett aus dem Speicher löscht und für die nächste Berechnung neu lädt. Ich dachte, ich könnte das Problem durch das dynamische Laden der DLL lösen. Dafür habe ich eine AppDomain (newDomainName) erstellt, und darin über newDomainName.Load("KMDLLCSHARP") die DLL zur Laufzeit geladen. In einem finally{} Block entlade ich die Domain am Ende. Aber auch dieses Verfahren schlägt fehl, da auch dabei die DLL nicht wirklich aus dem Speicher entfernt wird. Jetzt habe ich noch einen Ansatz über den Import mittels "LoadLibrary"-Aufrufes aus der Kernel32.dll gefunden. Das Beispiel schlägt dafür vor, das ganze zunächst in eine Klasse zu packen. static class NativeMethods { [DllImport("kernel32.dll")] public static extern IntPtr LoadLibrary(string dllToLoad); [DllImport("kernel32.dll")] public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName); [DllImport("kernel32.dll")] public static extern bool FreeLibrary(IntPtr hModule); } Anschließend soll man die Sachen importieren können: [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate int info(ref string infostring); ... IntPtr pDll = NativeMethods.LoadLibrary("KMDLLCSHARP"); IntPtr pAdressOfFunctionToCall = NativeMethods.GetProcAddress(pDll, "info"); info infofunction = (info)Marshal.GetDelegateForFunctionPointer(pAdressOfFunctionToCall, typeof(info)); Das funktioniert so allerdings nicht. Ich sehe, das pDLL korrekt geladen wird (der wert ist zumindest ungleich 0), GetProcAddress liefert allerdings stets 0 zurück. Nun weiß ich allerdings nicht genau, warum. Gebe ich den Namen der Funktion falsch an oder ist die CallingConvention in VB6 falsch (kp. wie die genau ist, oder wie ich darauf Einfluss nehmen könnte). Weiß da wer weiter?
Der richtige Ansatz wäre, Deine VB6-DLL so zu korrigieren, dass sie nach einem Absturz nicht in einem Zustand bleibt, so dass sie nicht mehr verwendbar ist. Das Problem von P-Invoke (DllImport, ...) ist nämlich, dass eine einmal geladene DLL solange im Speicher bleibt, bis das aufrufende Programm beendet wird. Da gibt es NICHTS dran zu drehen. Nimm also mal den VS-Debugger zur Hand und untersuche, warum Deine VB6-DLL abstürzt, so dass sie nicht mehr funktioniert. Wenn Du unbedingt mit der Holzhammer-Methode Programmierfehler umgehen willst, dann gibt es noch eine Möglichkeit, native DLLs über LoadLibrary und FreeLibrary zu laden und entladen. Wie das richtig geht, kannst Du diesem englischsprachigen Artikel entnehmen: http://www.codeproject.com/Articles/258270/How-to-release-non-managed-library-loaded-into-man. Allerdings ist das Einbinden der DLL-Funktionen nicht ganz so komfortabel, wie mit P-Invoke und mit vergleichsweise viel manuell zu erstellendem Code verbunden. Gruß Markus
Hey, danke schonmal für die Hilfe. Prinzipiell wäre mir ein Programm, das nicht oder nur "sauber" abstürzt, lieber. Das Programm wird allerdings nicht in unserer Firma erstellt, sondern extern zugekauft. Einflussnahme habe ich so nicht direkt. Ich kann zwar einzelne Fallstricke (es geht um eine iterative Berechnung) aufzeigen, die behoben werden, an die implementierung eines Watchdogs oder ähnlichen Sicherheitsmaßnahmen, ist aber leider nicht zu denken. Daher der Bedarf an die Holzhammermethode! So, habe mittlerweile herausgefunden, das meine Funktionen lediglich als "COM Method" exportiert wurden. Habe das ganze nun nochmal nach folgender Anleitung umgestellt: http://www.hermetic.ch/vbm2dll.htm#petrusha Meine Funktionen werden nun korrekt als "Exported Function" exportiert, ein aufruf funktioniert prinzipiell. Verzweige ich aber nun innerhalb der Funktionen weiter, (also auf die ursprünglichen Funktionen, die ich mit der ursprünglichen Methode aufrufen konnte), erscheint lediglich folgende Exception: "Attempted to read or write protected memory. This is often an indication that other memory is corrupt." Ich habe nun allerdings keine Ahnung, wie ich das umgehen koennte?
Hi Marcel, ich hatte den Eindruck, die VB6 DLL wäre von Dir... Ok. VB (6, .NET) muss ich leider passen. Die Exception riecht aber irgendwie nach korruptem Stack. Das wiederum ist ein Indiz dafür, dass beim DllImport Attribut das Property CallingConvention auf den richtigen wert gesetzt werden sollte. Welcher das ist, kann ich leider nicht sagen. Wahrscheinlich hilft dir aber eine Internetsuche weiter. Die Calling Convention gibt an, wer den Stack nach einem Funktionsaufruf aufräumt (Aufrufer oder Aufgerufene Funktion). Gruß Markus
Hi, mit den Calling Conventions habe ich bereits rumgespielt. Prinzipiell funktioniert ja auch der Aufruf, aber nicht die weiterführung. D.h. wenn das Programm innerhalb der Funktion bleibt, die ich aufrufe, klappt es. (Ich kann Rückgabe und Übergabewerte regulär benutzen.) Nur der Aufruf einer weiteren Funktion/Sub führt zum Absturz/Wurf der Exception. Irgendwie sehr dubios. Ich denke, ich werde mir eine weitere, WrapperDLL schreiben, die den Aufruf der VB6DLL für mich übernimmt und die ich dynamisch in C# nachladen kann. Würde das so funktionieren? Irgendwie traue ich dieser scheinbar einfachen Sache nichtmehr so ganz! =[
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.