Laden...

COM-Interop-Problem: Programm "hängt" auf einem anderen Rechner

Erstellt von bredator vor 8 Jahren Letzter Beitrag vor 8 Jahren 3.194 Views
B
bredator Themenstarter:in
357 Beiträge seit 2010
vor 8 Jahren
COM-Interop-Problem: Programm "hängt" auf einem anderen Rechner

Hallo zusammen,

momentan soll ich für eine native Applikation das Auslesen einer elektronischen Gesundheitskarte umsetzen. Da ich sowas schonmal halbfertig rumliegen hatte, habe ich das Projekt herangenommen und fertiggestellt. Es handelt sich um eine Dll, die aus dem nativen Code aufgerufen wird und ein String-Array zurückgibt. Die Technik dahinter ist nicht weiter aufregend. Es wird ein Interface definiert und dadurch bekomme ich auf nativer Seite den Pointer zur Klasse und kann die Methoden aufrufen. Ähnlich wird das schon an etwa 4-5 weiteren Stellen der nativen Anwendung so gemacht.

Der einzige Unterschied zu den bisherigen .NET-Komponenten ist der, dass dies die erste ist, die DllImport nutzt. Um den Kartenleser anzusprechen (via CTAPI) brauche ich die entsprechende Dll:


[DllImport(@"CTPCSCCD.dll", EntryPoint = "CT_init", SetLastError = true)]
        private static extern sbyte CT_init(ushort ctn, ushort pn);

        [DllImport(@"CTPCSCCD.dll", EntryPoint = "CT_close", SetLastError = true)]
        private static extern sbyte CT_close(ushort ctn);

        [DllImport(@"CTPCSCCD.dll", EntryPoint = "CT_data", SetLastError = true)]
        private static extern sbyte CT_data(ushort ctn, ref byte dad, ref byte sad, ushort lenc, ref byte command, ref ushort ulenr, ref byte response);

Das Problem ist nun: Auf dem Entwicklungsrechner funktioniert der Aufruf der entsprechenden Methode völlig unproblematisch. Auch auf einem anderen Entwicklungsrechner geht das perfekt. Gehe ich nun allerdings an einen anderen Rechner (native Exe + .NET-Dll + CT-API-Dll) und führe die Schritte dort durch, hängt die native Anwendung und es passiert nichts mehr. Per remote Debugger sehe ich, dass ich den Pointer auf meine Dll korrekt bekomme, allerdings beim Aufruf der eigentlichen Hauptmethode hängt sich die Anwendung auf. Keine Debug-Ausgabe auf der Konsole, keine Return-Werte, einfach überhaupt nichts mehr.

Der Aufruf sieht auf nativer Seite so aus:


CoInitialize(NULL);
this->s_ptrApoCT = ApoCT::_IApoCTAPIPtr(__uuidof(ApoCT::CardTerminalClient));
SAFEARRAY * test1 = s_ptrApoCT->getEgkData();

Wie gesagt, den Pointer erhalte ich. Erst bei getEgkData() steht das Programm. Und das nur auf den nicht-Entwickler-Rechnern.

Um einen generellen Fehler der .NET-Dll auszuschließen habe ich eine schnelle Winforms-Anwendung gezimmert, die Dll dort eingebunden und dieselbe Methode von dort aus aufgerufen. Das funktionierte dann auf sämtlichen getesteten Rechnern völlig unproblematisch. Die entsprechend benötigten Dlls sind also alle vorhanden und funktionieren auch. Nur aus nativem Code nicht so richtig.

Die Frage ist nun, was habe ich übersehen? Gibt es etwas, worauf ich achten muss, wenn ich aus nativem Code eine .NET-Dll aufrufe, welche wiederum native Dlls nutzt? Mein Verdacht ging schon in Richtung GC, dass dieser mir meine Dll im Hintergrund schon wieder abgeräumt hat, bis ich die Methode aufrufen will und das Ganze dann ins Leere läuft. Allerdings fehlt mir auch hier das Wissen um das entweder zu verhindern oder zumindest es genau herauszufinden.

L
21 Beiträge seit 2015
vor 8 Jahren

Hi,
Ich durfte vor 2Monaten für ein Projekt auch Egk/kvk auslesen.
Kontrolliere mal ob du nach einem Aufruf auch wirklich das Token wieder frei gibst.
Ich hatte das gleiche Problem undzwar wurde bei mir ne exception geworfen wenn ich Lesent auf das Kartenlesegerät zugegriffen habe aber keine Karte vorhanden war. Das Token habe ich aber nur im try-block zurück gegeben. Das Token muss aber aufjedenfall IMMER zurückgegeben werden ansonsten hilft nur ein reset des Gerätes .

Mfg
Lacka

B
bredator Themenstarter:in
357 Beiträge seit 2010
vor 8 Jahren

Wie gesagt, so weit komme ich gar nicht erst. In dem Moment, wo quasi der DllImport kommt, bzw. die Methoden aus der importierten Dll aufgerufen werden sollen, hängt das Programm. Keine Exception oder sonstwas, die Nachrichtenverarbeitung findet gar nicht mehr statt.

B
bredator Themenstarter:in
357 Beiträge seit 2010
vor 8 Jahren

Update: ich bin noch immer kein Stück vorwärts gekommen. Habe meine Aufrufe in eigene Background-Worker gepackt um evtl. die Programmblockade zu umgehen (so dass nur die Dll selbst dicht ist), aber auch da hängt sich die Host-Applikation auf. 😦

C
1.214 Beiträge seit 2006
vor 8 Jahren

Kannst du da nicht reindebuggen? Entweder in den .NET Code, oder wenn du nicht so weit kommst, in den Aufruf? Bin mir nicht sicher, aber ich könnte mir vorstellen, dass man mit dem .NET Code sehen müsste, was hinter dem Aufruf alles passiert.

Da die sich "aufhängt", denke ich irgendwie an Thread/Apartment Marshalling Probleme.

B
bredator Themenstarter:in
357 Beiträge seit 2010
vor 8 Jahren

Leider nicht. Ich komme zwar auf die .NET-Seite mit dem Debugger, aber die Zeile, wo der Aufruf der nativen Funktion erfolgt lässt sich nicht weiter untersuchen mit F11. Da hängt der ganze Spaß dann und fertig. Über Tipps, wie ich das dann trotzdem irgendwie untersuchen kann, wäre ich dankbar.

M
171 Beiträge seit 2012
vor 8 Jahren

Vielleicht die falsche Dll für Deinen Kartenleser?

Zitat SCM-Webseite:

Verwenden Sie die Datei c:\windows\system32\CTPCSCCD.dll bei den Kartenlesern Cloud x700 und die Datei c:\windows\system32\CTPCSC31.dll bei den Kartenlesern SCR3xxx

Sind die betreffenden dlls alle registriert?

Vielleicht Marshalling-Probleme zwischen 32bit und 64bit Systemen?

W
872 Beiträge seit 2005
vor 8 Jahren

Ziemlich ins blaue geschossen - vielleicht fehlt Dir ein SDK auf dem anderen Rechner.
Das "Windows Platform sdk" wäre ein typischer Kandidat. Mir ist vor einer Weile auch so etwas passiert und ich habe auch sehr lange gebraucht....

C
1.214 Beiträge seit 2006
vor 8 Jahren

Ob Dlls oder Funktionen in Dlls fehlen könnte man evtl. mit dem Dependency Walker rausfinden. Allerdings sollte in dem Fall die Anwendung nicht hängen. Schwieriger wirds, wenn die benötigten Dlls und Funktionen zwar da sind, aber nicht wirklich zusammenpassen.

B
bredator Themenstarter:in
357 Beiträge seit 2010
vor 8 Jahren

Danke für die Vorschläge. Es handelt sich um einen Kartenleser vom Typ Cloud 2700. Die Dll ist also schon die richtige. Registrieren lassen die sich nicht, da bekomme ich zurück, dass kein Einstiegspunkt gefunden wurde. Marshalling hatte ich im Verdacht, da es sich bei den Entwicklerrechnern jeweils um 64 Bit Maschinen handelt. Allerdings hängt es auf Kundenrechnern sowohl unter 32 als auch unter 64 Bit.

Das Platform SDK muss ich mir mal anschauen, oder ob eben etwas anderes fehlt. Dependency Walker ist dafür ein guter Tipp, an den hatte ich schon gar nicht mehr gedacht. Ich melde mich, wenn ich was gefunden habe (oder auch wenn nicht 😉 )

B
bredator Themenstarter:in
357 Beiträge seit 2010
vor 8 Jahren

Nochmal alles ein bisschen angeschaut mit dem Dependency Walker, Dlls durchgeschaut etc. pp.

Leider erfolglos. Gegen das Fehlen von Dlls und dergleichen spricht eben auch, dass eine 0815-Winforms Anwendung mit Verweis auf die Dll anstandslos funktioniert. Es kann also nur damit zusammenhängen, dass die managed Dll aus unmanaged Code aufgerufen wird. Leider habe ich absolut keinen Ansatzpunkt mehr, woran das liegen könnte.

Wie schon gesagt, das Gerüst der Dll wird an anderen Stellen der nativen Anwendung mehrfach so eingesetzt. Der einzige markante Unterschied ist hier, dass erstmals eine C#-Dll mit DllImport arbeitet 😦

5.657 Beiträge seit 2006
vor 8 Jahren

Hi bredator,

diese Stelle haben die meisten wahrscheinlich überlesen:

Gibt es etwas, worauf ich achten muss, wenn ich aus nativem Code eine .NET-Dll aufrufe, welche wiederum native Dlls nutzt?

Mir selbst ist jedenfalls auch nicht ganz klar, an welcher Stelle in dieser Kette dein Problem auftritt. Oder wie die genaue Zugriffsreihenfolge ist. Oder wie du aus der nativen Anwendung die .NET-Methode aufrufst. Und was du überhaupt schon ausprobiert hast, um dem Problem auf die Spur zu kommen.

Nochmal alles ein bisschen angeschaut [...] Leider erfolglos.

Das ist halt nicht besonders aufschlußreich. Versuch mal zu erklären, was du dir da genau angeschaut hast, wie du den Debugger verwendet hast, und welche Resultate du hast. Sonst können wir hier auch höchstens mal mit den Schultern zucken.

Letztendlich mußt du herausfinden, in welcher deiner nativen und/oder managed Schichten ein Fehler auftritt, oder ein unerwartetes Ergebnis zurückgegeben wird. Ein guter Ansatzpunkt wäre ja auch zu schauen, was auf den Entwicklungsrechnern anders ist als auf den anderen Rechnern.

Christian

Weeks of programming can save you hours of planning

B
bredator Themenstarter:in
357 Beiträge seit 2010
vor 8 Jahren

Nun letztlich lief es darauf hinaus, dass ich den Remote Debugger auf dem Zielrechner gestartet habe, danach die native Applikation.

Im Code der nativen Applikation (auf dem Dev-Rechner) habe ich dann mich an den Prozess des Zielrechners drangehängt und dort die Prozedur aufgerufen, in der meine managed Dll verwendet wird. Der Aufruf selbst klappt auch (war zu erkennen an einer simplen Messagebox, die ich ganz an den Beginn gehängt habe), aber sobald ich mit F10 weiter steppe zu der Stelle an der die Methode der Cardreader-Dll (via DllImport) aufgerufen wird, geht nichts mehr weiter. Der Debugger macht dabei den Eindruck, als würde er etwas sehr zeitaufwändiges machen, allerdings passiert dann nichts mehr, egal wie lange ich warte. Das Programm hängt. Auch ein weiteres Einspringen via F11 bringt mich nur in Assembler-Code, aber nicht dorthin wo ich evtl. weitere Erkennnisse bekommen könnte.
Auch ein Debugger.Break wird einfach ignoriert.

Mit dem Dependency-Walker habe ich abgeklärt, ob irgendwelche Abhängigkeiten fehlen, dem ist nicht so.

Der nächste Schritt, den ich zwar vermeiden wollte, jetzt aber doch mache, ist, Visual Studio auf dem Zielrechner zu installieren (das ist der einzige Unterschied zwischen den Rechnern) und dann das Ganze nochmal zu versuchen. Aber alles noch sehr vage und ohne einen echten Ansatz, woran das jetzt liegen könnte.

5.657 Beiträge seit 2006
vor 8 Jahren

Kannst du sicherstellen, daß auf dem Anwendungsrechner

  • die gleichen API-DLLs zur Verfügung stehen, wie auf dem Entwicklungsrechner?
  • alle eventuellen Abhängigkeiten der API-DLLs zur Verfügung stehen?
  • die korrekten Daten an den API-Aufruf übergeben werden?
  • der Cardreader auch tatsächlich funktionsbereit (und -tüchtig) ist?
  • die API alle Zugriffsrechte hat, die sie benötigt?

Christian

Weeks of programming can save you hours of planning

B
bredator Themenstarter:in
357 Beiträge seit 2010
vor 8 Jahren

Wie gesagt, in einem kleinen Winforms-Progrämmchen macht meine managed Dll genau das, was sie soll - auf jedem Rechner. Erst wenn ich meine Dll aus einem nativen Programm heraus aufrufe, hängt das Ganze. Was ich noch probieren werde: Ich lege ein kleines MFC-Testprogramm an und mach den Aufruf aus diesem heraus mal.