[59186] in SAPr3-news

home help back first fref pref prev next nref lref last post

Re: .net Connector, DCOM Connector und Logon Component

daemon@ATHENA.MIT.EDU (Tibor Gerke)
Wed Apr 4 16:11:22 2007

To: sapr3-news@mit.edu
Date: Wed, 04 Apr 2007 22:11:02 +0200
From: Tibor Gerke <tibor.gerke@gmx.de>
Message-ID: <4614065a$0$20294$9b4e6d93@newsspool3.arcor-online.net>

wundertier@web.de wrote:

> Hast Du da schon was zum Laufen bekommen?

Ich hab es für den STFC_STRUCTURE vollständig durchgespielt,
garnicht schön zu programmieren.

Die automatische Generierung der Interop-Klassen scheint mit
SAP OCX nicht 100% zu funktionieren. Ich hab aber auch nichts
im Internet gefunden, wie man da per Hand dran drehen könnte.

Alles in C#, Formatierung vermutlich wegen 72 Zeichen etwas zerschossen:

Für das Setzen der Connection-Parameter hab ich eine Wrapper-Klasse in 
VB6 anglegt, in der Art

-- VB6 Wrapper --
Public Sub ApplicationServer(ByRef objSAPLogonCtrl As 
SAPLogonCtrl.Connection, ByVal sValue As String)
     objSAPLogonCtrl.ApplicationServer = sValue
End Sub
-- VB6 Wrapper --

Damit lässt sich erstmal das Connection-Objekt ohne Exception mit Daten 
füllen.

SAPFunctionsOCX.SAPFunctions control = new SAPFunctionsOCX.SAPFunctions();
SAPLogonCtrl_Wrapper.clsConnectionClass connectionWrapper = new 
SAPLogonCtrl_Wrapper.clsConnectionClass();
connectionWrapper.UseSAPLogonIni(ref connection, false);
connectionWrapper.User(ref connection, "username");
connectionWrapper.Password(ref connection, "password");
connectionWrapper.Language(ref connection, "DE");
connectionWrapper.Client(ref connection, "000");
connectionWrapper.ApplicationServer(ref connection, "server");
connectionWrapper.SystemNumber(ref connection, 00);

Die Verbidung wird dann mit
if (!connection.Logon(0, true))
ohne Probleme aufgebaut.


Das Hinzufügen eines FuBas macht auch keine Probleme
// STFC_STRUCTURE
SAPFunctionsOCX.Function functionSTFC_STRUCTURE = 
(SAPFunctionsOCX.Function)control.Add("STFC_STRUCTURE");

Das Ansprechen der Parameter artet ein wenig in eine Casting Orgie aus,
die Import- und Exportparameter lassen sich ohne grosse Probleme 
ansprechen. Beim Setzen habe ich nur String ausprobiert.
((SAPFunctionsOCX.Structure)functionSTFC_STRUCTURE.get_Exports("IMPORTSTRUCT")).set_Value("RFCFLOAT", 
"123,456");

Wenn man die Parameter ausliesst, muss man entsprechend casten.
double echostruct1 = 
(double)((SAPFunctionsOCX.Structure)functionSTFC_STRUCTURE.get_Imports("ECHOSTRUCT")).get_Value("RFCFLOAT");
Da ist man im VB6 über die Auto-Konvertierung flexibler.

ABAP  = C#
FLOAT = double
INT2  = Int32
INT1  = Int32
CHAR  = string
HEX   = string
TIME  = DateTime
DATE  = DateTime

Bei Tabellen wird es noch ein wenig schlimmer.
SAPTableFactoryCtrl.Table tableRFCTABLE = 
(SAPTableFactoryCtrl.Table)((SAPTableFactoryCtrl.Tables)functionSTFC_STRUCTURE.Tables).get_Item("RFCTABLE");
SAPTableFactoryCtrl.Row row = 
(SAPTableFactoryCtrl.Row)((SAPTableFactoryCtrl.Rows)tableRFCTABLE.Rows).Add(null);

In VB6 hat die Add-Methode keine Parameter, in der Interop-Version 
schon, allerdings kann man einfach 'null' übergeben.

Der Schreibzugriff auf eine Spalte mit SetValue löst wieder eine 
Exception aus. Ich hab alle verstreuten Möglichkeiten für das Setzen
eines Wertes ausprobiert. Es kommt immer diegleiche Exception.
((SAPTableFactoryCtrl.Column)((SAPTableFactoryCtrl.Columns)tableRFCTABLE.Columns).get_Item("RFCFLOAT")).set_Value(1, 
"123.234");
funktioniert also nicht. Der Lesezugriff mit get_Value funktioniert.

Für den Schreibzugriff hab ich wieder einen Wrapper in VB6 benutzt.
-- VB6 Wrapper --
Public Sub SAPTableFactoryCtrl_SetValue(ByRef objRow As 
SAPTableFactoryCtrl.Row, ByVal sColumn As String, ByVal sValue As String)
     objRow.Value(sColumn) = sValue
End Sub
-- VB6 Wrapper --

Damit lassen sich die Tabellenwerte setzen:
connectionWrapper.SAPTableFactoryCtrl_SetValue(ref row, "RFCFLOAT", 
"123.456");

Eine Tabelle vollständig auslesen ist auch möglich.
tableRFCTABLE = 
(SAPTableFactoryCtrl.Table)((SAPTableFactoryCtrl.Tables)functionSTFC_STRUCTURE.Tables).get_Item("RFCTABLE");
int rowCount = tableRFCTABLE.RowCount;
for (int i=1;  i <= rowCount; i++)
{
row = 
(SAPTableFactoryCtrl.Row)((SAPTableFactoryCtrl.Rows)tableRFCTABLE.Rows).get_Item(i);
echostruct1 = (double)row.get_Value("RFCFLOAT");
}

Beim Auslesen von Werten aus einer Tabelle wird RFCINT2, RFCINT1 als 
Int16 Objekt zurückgeliefert, in der Struktur wurde es als Int32 
zurückgeliefert.

Bis auf die Einschränkung beim Connection-Objekt und dem Setzen von 
Tabellenwerten scheint das SAPFunctionsOCX von .net aus benutzbar zu 
sein. Es macht bloss keinen Sinn mit diesen Einschränkungen. Es dürfe 
viel einfacher sein, eine komplette Proxy-Klasse für einen RFC in VB6
zu schreiben und diese Proxy-Klasse dann von .net zu rufen.

> Hab ich das eigentlich falsch in Erinnerung, oder sind generic calls
> mit dem JCo möglich???

Generic calls sind mit JCo (manchmal auch JayCo in Hinweisen ;-)) ohne
Probleme möglich.

/Tibor

home help back first fref pref prev next nref lref last post