Announcement

Collapse
No announcement yet.

ActiveX ohne TLB ansprechen

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • ActiveX ohne TLB ansprechen

    Hallo,
    aus internen Gründen bringen wir unsere internen Tools auf eine gemeinsame Sprache, die Wahl ist auf C# gefallen.
    Bei der Migration eines kleinen Java-tools nach C# gibt es leider ein Problem da wir schlicht nicht wissen wie man das mit C# schreibt. Es geht um die Ansteuerung eines Importprogrammes via ActiveX.
    Der Hersteller liefert keine Type Library und fast alle Beispiele die wir gefunden haben verwenden eine solche, ActiveX muss hier also "von Hand" angesprochen werden.

    Herstellerseitig gibt es folgendes VBA Beispiel:
    Code:
    Dim App As Object
    Dim Import As Object
    Dim Success As Boolean
    Dim FehlerAufgetreten As Boolean
    Dim Historie_ID As String
    Dim Fehlermeldung As String
    Dim Meldung As String
    Dim Akten, Schuldner, KVerw, AdrAend, VBFehler, AnalyseFehler As Integer
    'Applikation starten
    Set App = CreateObject("IKAROS-ImportSQL.Application")
    'Anmelden
    Success = App.ConnectAsActiveX("USER", "PWD", "IKAROS")
    If Success Then 'Anmeldung gelungen?
    Set Import = App.gibActiveXImport()
    'Vorgaben setzen
    With Import
    .DateiPfad = "C:\TMP\Import-20100831.txt"
    .FormatDefinition = "STANDARD_0.1"
    .Mandant = 89561
    .Fortfahren = 3
    .Analyse = True
    .KAendern = True
    .ImportartBankverbindung = 3
    End With
    'Import starten
    Import.Starte
    'Ergebnisse holen
    If LenB(Import.Fehlermeldung) <> 0 Then 'Fehlermeldungen aufgetreten?
    FehlerAufgetreten = True
    Fehlermeldung = Import.Fehlermeldung
    Else
    FehlerAufgetreten = False
    Historie_ID = Import.Historie_ID
    Akten = Import.AnzAkten
    Schuldner = Import.AnzSchuldner
    KVerw = Import.AnzKVerw
    AdrAend = Import.AnzAdrAend
    VBFehler = Import.AnzVBFehler
    AnalyseFehler = Import.AnzAnalyseFehler
    Meldung = Import.Meldung
    End If
    'Applikation schliessen
    App.Quit
    End If
    'Ergebnisse anzeigen
    If FehlerAufgetreten Then
    MsgBox "Fehlermeldung: " + Fehlermeldung
    Else
    MsgBox "Historie_ID: " + Historie_ID & Chr(13) & Chr(10) _
    & "Anzahl Akten: " + Str(Akten) & Chr(13) & Chr(10) _
    & "Anzahl Schuldner: " + Str(Schuldner) & Chr(13) & Chr(10) _
    & "Anzahl Kontaktverw.: " + Str(KVerw) & Chr(13) & Chr(10) _
    & "Anzahl Adr.-Änd.: " + Str(AdrAend) & Chr(13) & Chr(10) _
    & "Anzahl Verb.-Fehler: " + Str(VBFehler) & Chr(13) & Chr(10) _
    & "Anzahl Analysefehler: " + Str(AnalyseFehler) & Chr(13) & Chr(10) _
    & "Meldungen: " + Meldung _
    , 0
    End If
    Wir hatten das in Java wie folgt erfolgreich programmiert (Auszug):
    Code:
    		ActiveXComponent xl;
    		try {
    			xl = new ActiveXComponent(props
    					.getProperty("dcom.app"));
    		} catch (Exception e1) {
    			// TODO Auto-generated catch block
    			e1.printStackTrace();
    			return false;
    		}
    
    		// Object xlo = xl.getObject();
    		Variant v1 = new Variant();
    		Variant v2 = new Variant();
    		Variant v3 = new Variant();
    		v1.putString(props.getProperty("import.user"));
    		v2.putString(props.getProperty("import.pw"));
    		v3.putString(props.getProperty("import.service"));
    
    		// Rufe den DCOM Baustein auf und melde an das System an, liefert FALSE
    		// falls es Probleme gibt
    		Variant success = xl.invoke("ConnectAsActiveX", v1, v2, v3);
    		if (success.getBoolean() == false) {
    			System.out
    					.println("ERROR: Die Komponente "
    							+ props.getProperty("dcom.app")
    							+ " kann nicht konnektiert werden, Zugangsdaten falsch oder System läuft bereits in der Instanz "
    							+ props.getProperty("sql.service") + ".");
    		}
    
    		// Da hier unsere DCOM Komponente (oder ganz Ikaros in dem Fall) bereits
    		// gestartet
    		// ist setzen wir alles in einen Try, wir koennen dann auf jeden Fall im
    		// Final-Block die Anwendung schliessen
    		try {
    			// Hole den ActiveXBaustein gibActiveXImport als Object (Pointer?)
    			Variant import2 = xl.invoke("gibActiveXImport");
    			Object importo = import2.toDispatch();
    			// Object importo3 =
    			// xl.getPropertyAsComponent("gibActiveXImport");//.toDispatch();
    
    			// Beschicke die Prosaroutine mit verschiednen Inputparametern
    			Dispatch.put((Dispatch) importo, "DateiPfad", fileName);
    			Dispatch.put((Dispatch) importo, "FormatDefinition",
    					formatDefinition);
    			// "ES_WEB_VORGANG");
    			Dispatch.put((Dispatch) importo, "Fortfahren", 1);
    			Dispatch.put((Dispatch) importo, "Analyse", true);
    			Dispatch.put((Dispatch) importo, "KWarnung", true);
    
    			// Fuehre die Methode starte die im gibActiveXImport definiert ist
    			// aus
    			Dispatch.callSub((Dispatch) importo, "starte");
    			Variant u = Dispatch.get((Dispatch) importo, "Historie_ID");
    			if (u == null) {
    				return false;
    			}
    			String historieId = u.toString();
    			if (historieId.compareTo("") == 0) {
    				return false;
    			}
    
    			System.out.println(u.toString());
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    			// Schliesse die Anwendung immer.
    			xl.invoke("Quit", new Variant[] {});
    		}
    		return true;
    Was wir jetzt in C# gar nicht auf die Reihe bekommen ist das setzen der Variablen in ActiveX.
    Das ActiveX-Objekt wird angesprochen, die Importersoftware startet, jetzt müßten die Werte gesetzt werden (das was in VBA z.b. mit
    Code:
    Import.DateiPfad = "c:\..."
    gemacht wird und auch in Java ging (
    Code:
    Dispatch.put((Dispatch) importo, "DateiPfad", fileName);
    ).

    Hier ein Auszug aus unserem C#-Code (nicht lauffähig):
    Code:
                var t = Type.GetTypeFromProgID(ConfigurationManager.AppSettings["DCOM-APP"], ConfigurationManager.AppSettings["DCOM-HOST"], true);
                var comObject = Activator.CreateInstance(t);            
                var teste = t.InvokeMember("ConnectAsActiveX", System.Reflection.BindingFlags.InvokeMethod | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public, null, comObject, new String[] { "user", "pass", "System" });
                var b = t.InvokeMember("gibActiveXImport", System.Reflection.BindingFlags.InvokeMethod | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public, null, comObject, new String[] { });
                var tempa = t.GetType().InvokeMember( null, BindingFlags.IgnoreCase | BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetField, null, b, new object[] {fileName});
                t.InvokeMember("DateiPfad",  BindingFlags.IgnoreCase| BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetField, null, comObject, new object[] {fileName} );
    Der Code enthält schon nicht funktionsfähige Versuche die Variablen zu setzen, ich hoffe hier gibt es jemanden der mich erläuchten kann wie der C# Pedant hierzu lautet.

    Beste Grüße,
    Jochen
    Zuletzt editiert von jochen-s; 13.08.2014, 19:55. Reason: ich habe es mal ein wenig bunter gemacht. Grün ist Code der soweit funktionsgleich ist und läuft, Rot ist Müll

  • #2
    comObject wird aber noch erzeugt? Es wäre hilfreich zu wissen was für Fehler du wo bekommst nicht nur das

    Wenn es frühzeitig scheitert wäre mein erste Vermutung das du versuchst eine 32Bit COM DLL in einem 64Bit Prozess zu verwenden. Das wird nicht gehen.

    Comment


    • #3
      Sorry wenn das nicht so rüber gekommen ist.
      ich habe es jetzt mal ein wenig bunter gemacht.
      Grün ist funktionsgleicher Code, das heisst im C# funktioniert dieser, verbindet sich mit der ActiveX Komponente, die macht auch fein ein Fenster auf und müßte jetzt wie im VBA Beispiel zu sehen ist ein wenig konfiguriert werden, z.B. den DateiPfad gesetzt bekommen.
      Alles was Rot ist kannst du vergessen, das ist Schrott der aus unzähligen verzweifelten Versuchen übrig geblieben ist, ich könnte ihn auch löschen aber vieleicht ist ja ein Ansatz dabei der hilft.
      Was nach dem grünen bereich gemacht werden soll ist die Variablen vorzubelegen analog des VBA oder auch java codes.

      Jochen

      Comment

      Working...
      X