Autor Beitrag
researcher
Hält's aus hier
Beiträge: 14



BeitragVerfasst: Mi 11.03.09 17:51 
Hallo!

Ich habe eine .NET DLL (ClassLibrary) mittels Visual Studio erstellt und versuche diese in Delphi einzubinden.

Dabei habe ich versucht eine eigene Unit zu schreiben, in welcher die Methode mit

external 'COMLib.dll';

ergänzt wird. Doch leider stürzt das Programm mit der Meldung "...konnte nicht richtig initialisiert werden" ab, wenn ich es versuche zu starten.

Wie kann ich sonst die ClassLibrary in Delphi einbinden?

lg

Peter
researcher Threadstarter
Hält's aus hier
Beiträge: 14



BeitragVerfasst: Do 12.03.09 10:42 
Ok...ich habe das Projekt nun etwas erweitert, damit ich es in Delphi importieren kann.

In C# habe ich die Option 'Register for COM interop' aktiviert.

Nach der Registrierung der DLL durch REGASM habe ich diese in Delphi mittels 'Komponente - Komponente importieren - ActiveX' importiert und es wurde eine neue .pas Datei erzeugt. Hier sehe ich dann auch das Interface (zB GiveMeAReturnValue()), welches in C# implementiert wurde.

Nur wie kann ich die entsprechende Methode in Delphi ansprechen?

Hier der C# Code

ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
    public interface IMyClass
    {
        int GiveMeAReturnValue();
    }

    [ClassInterface(ClassInterfaceType.AutoDual)]
    public class MyClass : IMyClass
    {
        public int GiveMeAReturnValue()
        {
            return 12;
        }
    }


Auszug aus der Delphi-.pas Datei

ausblenden volle Höhe Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
interface

uses Windows, ActiveX, Classes, Graphics, mscorlib_TLB, OleServer, StdVCL, Variants;
  

// *********************************************************************//
// In der Typbibliothek deklarierte GUIDS. Die folgenden Präfixe werden verwendet:        
//   Typbibliotheken      : LIBID_xxxx                                      
//   CoClasses            : CLASS_xxxx                                      
//   DISPInterfaces       : DIID_xxxx                                       
//   Nicht-DISP-Interfaces: IID_xxxx                                        
// *********************************************************************//
const
  // Haupt- und Nebenversionen der Typbibliothek  COMLibMajorVersion = 1;
  COMLibMinorVersion = 0;

  LIBID_COMLib: TGUID = '{4B1F832E-BC8B-49E7-85B7-36E46DC8F72D}';

  IID_IMyClass: TGUID = '{3D44571B-AC9A-34C2-9D44-46E14740E740}';
  IID__MyClass: TGUID = '{E4EA0A3A-DD45-379D-ACF6-C2B7CC047C66}';
  CLASS_MyClass: TGUID = '{D1F3B286-EF9A-38FB-A83C-42D1F40FE1FA}';
type
// *********************************************************************//
// Forward-Deklaration von in der Typbibliothek definierten Typen                    
// *********************************************************************//

  IMyClass = interface;
  IMyClassDisp = dispinterface;
  _MyClass = interface;
  _MyClassDisp = dispinterface;

// *********************************************************************//
// Deklaration von in der Typbibliothek definierten CoClasses             
// (HINWEIS: Hier wird jede CoClass ihrem Standard-Interface zugewiesen)              
// *********************************************************************//


  MyClass = _MyClass;


// *********************************************************************//
// Interface: IMyClass
// Flags:     (4416) Dual OleAutomation Dispatchable
// GUID:      {3D44571B-AC9A-34C2-9D44-46E14740E740}
// *********************************************************************//
  IMyClass = interface(IDispatch)
    ['{3D44571B-AC9A-34C2-9D44-46E14740E740}']
    function GiveMeAReturnValue: Integer; safecall;
  end;

// *********************************************************************//
// DispIntf:  IMyClassDisp
// Flags:     (4416) Dual OleAutomation Dispatchable
// GUID:      {3D44571B-AC9A-34C2-9D44-46E14740E740}
// *********************************************************************//
  IMyClassDisp = dispinterface
    ['{3D44571B-AC9A-34C2-9D44-46E14740E740}']
    function GiveMeAReturnValue: Integer; dispid 1610743808;
  end;

// *********************************************************************//
// Interface: _MyClass
// Flags:     (4432) Hidden Dual OleAutomation Dispatchable
// GUID:      {E4EA0A3A-DD45-379D-ACF6-C2B7CC047C66}
// *********************************************************************//
  _MyClass = interface(IDispatch)
    ['{E4EA0A3A-DD45-379D-ACF6-C2B7CC047C66}']
  end;

// *********************************************************************//
// DispIntf:  _MyClassDisp
// Flags:     (4432) Hidden Dual OleAutomation Dispatchable
// GUID:      {E4EA0A3A-DD45-379D-ACF6-C2B7CC047C66}
// *********************************************************************//
  _MyClassDisp = dispinterface
    ['{E4EA0A3A-DD45-379D-ACF6-C2B7CC047C66}']
  end;
researcher Threadstarter
Hält's aus hier
Beiträge: 14



BeitragVerfasst: Do 12.03.09 11:45 
Wenn ich versuche, die DLL so zu laden, bekomme ich einen Zugriffsfehler:

ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
function GiveMeAReturnValue(): integer;
Var
 HND: THandle;
 GetReturnValue: Function (): integer;
Begin
    Result := -1;
    HND := LoadLibrary('COMLib.dll');
 Try
  If (HND >= 32) Then
  Begin
    GetReturnValue := GetProcAddress(HND,pChar('GiveMeAReturnValue'));
    result := GetReturnValue;
  End
  Else MessageBox(0,'ERROR: Could not find or load COMLib.dll','ERROR',MB_ICONERROR);
 Finally
    FreeLibrary(HND);
 End;
End;


Hat jemand eine Idee warum?
Sinspin
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1335
Erhaltene Danke: 118

Win 10
RIO, CE, Lazarus
BeitragVerfasst: Do 12.03.09 13:23 
user profile iconresearcher hat folgendes geschrieben Zum zitierten Posting springen:
Wenn ich versuche, die DLL so zu laden, bekomme ich einen Zugriffsfehler:

....

Hat jemand eine Idee warum?


Ganz einfach, es ist keine wirkliche Dll. Nur der Container scheint bei DOT Net im PE Format zu sein. Aber die Prozedur die du haben willst ist als DOT Net Code abgelegt und lässt sich leider nicht auf diese Art referenzieren.

Post mal die gesammte Typelib die dir beim Import erstellt wurde. Mir scheint es so als fehlt da das entscheitende Stück im Header, was man braucht um die Typelib zu verwenden.

_________________
Wir zerstören die Natur und Wälder der Erde. Wir töten wilde Tiere für Trophäen. Wir produzieren Lebewesen als Massenware um sie nach wenigen Monaten zu töten. Warum sollte unser aller Mutter, die Natur, nicht die gleichen Rechte haben?
researcher Threadstarter
Hält's aus hier
Beiträge: 14



BeitragVerfasst: Do 12.03.09 13:28 
ah ok...hier die erstellte LIB

ausblenden volle Höhe Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
176:
177:
178:
179:
180:
181:
182:
183:
184:
185:
186:
187:
188:
189:
190:
191:
192:
193:
194:
195:
196:
197:
198:
199:
200:
201:
202:
203:
204:
205:
206:
207:
208:
209:
210:
211:
212:
213:
214:
215:
216:
217:
218:
219:
220:
221:
222:
223:
224:
225:
226:
227:
228:
229:
230:
231:
232:
233:
234:
235:
236:
237:
238:
239:
240:
241:
242:
243:
244:
245:
246:
247:
248:
249:
250:
251:
252:
253:
254:
255:
256:
257:
258:
259:
260:
261:
262:
263:
264:
265:
266:
267:
268:
269:
270:
271:
272:
273:
274:
275:
276:
277:
278:
279:
280:
281:
282:
283:
284:
285:
286:
287:
288:
289:
290:
291:
292:
293:
294:
295:
296:
297:
298:
299:
300:
301:
unit COMLib_TLB;

// ************************************************************************ //
// WARNUNG                                                                    
// -------                                                                    
// Die in dieser Datei deklarierten Typen wurden aus Daten einer Typbibliothek
// generiert. Wenn diese Typbibliothek explizit oder indirekt (über eine     
// andere Typbibliothek) reimportiert wird oder wenn der Befehl            
// 'Aktualisieren' im Typbibliotheks-Editor während des Bearbeitens der     
// Typbibliothek aktiviert ist, wird der Inhalt dieser Datei neu generiert und 
// alle manuell vorgenommenen Änderungen gehen verloren.                                        
// ************************************************************************ //

// $Rev: 17252 $
// Datei am 12.03.2009 09:34:50 erzeugt aus der unten beschriebenen Typbibliothek.

// ************************************************************************  //
// Typbib.: C:\Users\goepet.HS\Documents\Projektarbeit\Projekte\COM\HostDelphi_PluginNET\Host\COMLib.dll (1)
// LIBID: {4B1F832E-BC8B-49E7-85B7-36E46DC8F72D}
// LCID: 0
// Hilfedatei: 
// Hilfe-String: 
// Liste der Abhäng.: 
//   (1) v2.0 stdole, (C:\Windows\system32\stdole2.tlb)
//   (2) v2.0 mscorlib, (C:\Windows\Microsoft.NET\Framework\v2.0.50727\mscorlib.tlb)
// Fehler//   Fehler beim Erzeugen von Palettenbitmap von (TMyClass) : Server mscoree.dll enthält keine Symbole
// ************************************************************************ //
// *************************************************************************//
// HINWEIS:                                                                      
//Von $IFDEF_LIVE_SERVER_AT_DESIGN_TIME überwachte Einträge, werden von  
// Eigenschaften verwendet, die Objekte zurückgeben, die explizit mit einen Funktionsaufruf  
// vor dem Zugriff über die Eigenschaft erzeugt werden müssen. Diese Einträge wurden deaktiviert,  
// um deren unbeabsichtigte Benutzung im Objektinspektor zu verhindern. Sie können sie  
// aktivieren, indem Sie LIVE_SERVER_AT_DESIGN_TIME definieren oder sie selektiv  
// aus den $IFDEF-Blöcken entfernen. Solche Einträge müssen jedoch programmseitig 
// mit einer Methode der geeigneten CoClass vor der Verwendung  
// erzeugt werden. 

          
                                              {$TYPEDADDRESS OFF} // Unit muss ohne Typüberprüfung für Zeiger compiliert werden. 

{$WARN SYMBOL_PLATFORM OFF}
{$WRITEABLECONST ON}
{$VARPROPSETTER ON}
{$ALIGN 4}
interface

uses Windows, ActiveX, Classes, Graphics, mscorlib_TLB, OleServer, StdVCL, Variants;
  

// *********************************************************************//
// In der Typbibliothek deklarierte GUIDS. Die folgenden Präfixe werden verwendet:        
//   Typbibliotheken      : LIBID_xxxx                                      
//   CoClasses            : CLASS_xxxx                                      
//   DISPInterfaces       : DIID_xxxx                                       
//   Nicht-DISP-Interfaces: IID_xxxx                                        
// *********************************************************************//
const
  // Haupt- und Nebenversionen der Typbibliothek  COMLibMajorVersion = 1;
  COMLibMinorVersion = 0;

  LIBID_COMLib: TGUID = '{4B1F832E-BC8B-49E7-85B7-36E46DC8F72D}';

  IID_IMyClass: TGUID = '{3D44571B-AC9A-34C2-9D44-46E14740E740}';
  IID__MyClass: TGUID = '{E4EA0A3A-DD45-379D-ACF6-C2B7CC047C66}';
  CLASS_MyClass: TGUID = '{D1F3B286-EF9A-38FB-A83C-42D1F40FE1FA}';
type
// *********************************************************************//
// Forward-Deklaration von in der Typbibliothek definierten Typen                    
// *********************************************************************//

  IMyClass = interface;
  IMyClassDisp = dispinterface;
  _MyClass = interface;
  _MyClassDisp = dispinterface;

// *********************************************************************//
// Deklaration von in der Typbibliothek definierten CoClasses             
// (HINWEIS: Hier wird jede CoClass ihrem Standard-Interface zugewiesen)              
// *********************************************************************//


  MyClass = _MyClass;


// *********************************************************************//
// Interface: IMyClass
// Flags:     (4416) Dual OleAutomation Dispatchable
// GUID:      {3D44571B-AC9A-34C2-9D44-46E14740E740}
// *********************************************************************//
  IMyClass = interface(IDispatch)
    ['{3D44571B-AC9A-34C2-9D44-46E14740E740}']
    function GiveMeAReturnValue: Integer; safecall;
  end;

// *********************************************************************//
// DispIntf:  IMyClassDisp
// Flags:     (4416) Dual OleAutomation Dispatchable
// GUID:      {3D44571B-AC9A-34C2-9D44-46E14740E740}
// *********************************************************************//
  IMyClassDisp = dispinterface
    ['{3D44571B-AC9A-34C2-9D44-46E14740E740}']
    function GiveMeAReturnValue: Integer; dispid 1610743808;
  end;

// *********************************************************************//
// Interface: _MyClass
// Flags:     (4432) Hidden Dual OleAutomation Dispatchable
// GUID:      {E4EA0A3A-DD45-379D-ACF6-C2B7CC047C66}
// *********************************************************************//
  _MyClass = interface(IDispatch)
    ['{E4EA0A3A-DD45-379D-ACF6-C2B7CC047C66}']
  end;

// *********************************************************************//
// DispIntf:  _MyClassDisp
// Flags:     (4432) Hidden Dual OleAutomation Dispatchable
// GUID:      {E4EA0A3A-DD45-379D-ACF6-C2B7CC047C66}
// *********************************************************************//
  _MyClassDisp = dispinterface
    ['{E4EA0A3A-DD45-379D-ACF6-C2B7CC047C66}']
  end;

// *********************************************************************//
// Die Klasse CoMyClass stellt die Methoden Create und CreateRemote zur      
// Verfügung, um Instanzen des Standard-Interface _MyClass, dargestellt 
// von CoClass MyClass, zu erzeugen. Diese Funktionen können                     
// von einem Client verwendet werden, der die CoClasses automatisieren    
// will, die von dieser Typbibliothek dargestellt werden.                                            
// *********************************************************************//

  CoMyClass = class
    class function Create: _MyClass;
    class function CreateRemote(const MachineName: string): _MyClass;
  end;


// *********************************************************************//
// OLE-Server-Proxy-Klassendeklaration
// Server-Objekt      : TMyClass
// Hilfe-String       : 
// Standard-Interface : _MyClass
// Def. Intf. DISP?   : No
// Ereignis-Interface : 
// TypeFlags          : (2) CanCreate
// *********************************************************************//
{$IFDEF LIVE_SERVER_AT_DESIGN_TIME}
  TMyClassProperties= class;
{$ENDIF}
  TMyClass = class(TOleServer)
  private
    FIntf: _MyClass;
{$IFDEF LIVE_SERVER_AT_DESIGN_TIME}
    FProps: TMyClassProperties;
    function GetServerProperties: TMyClassProperties;
{$ENDIF}
    function GetDefaultInterface: _MyClass;
  protected
    procedure InitServerData; override;
  public
    constructor Create(AOwner: TComponent); override;
    destructor  Destroy; override;
    procedure Connect; override;
    procedure ConnectTo(svrIntf: _MyClass);
    procedure Disconnect; override;
    property DefaultInterface: _MyClass read GetDefaultInterface;
  published
{$IFDEF LIVE_SERVER_AT_DESIGN_TIME}
    property Server: TMyClassProperties read GetServerProperties;
{$ENDIF}
  end;

{$IFDEF LIVE_SERVER_AT_DESIGN_TIME}
// *********************************************************************//
// OLE-Server-Eigenschaften-Proxy-Klasse
// Server-Objekt     : TMyClass
// (Dieses Objekt wird vom Eigenschaftsinspektor der IDE verwendet,
//  um die Eigenschaften dieses Servers zu bearbeiten)
// *********************************************************************//
 TMyClassProperties = class(TPersistent)
  private
    FServer:    TMyClass;
    function    GetDefaultInterface: _MyClass;
    constructor Create(AServer: TMyClass);
  protected
  public
    property DefaultInterface: _MyClass read GetDefaultInterface;
  published
  end;
{$ENDIF}


procedure Register;

resourcestring
  dtlServerPage = 'ActiveX';

  dtlOcxPage = 'ActiveX';

implementation

uses ComObj;

class function CoMyClass.Create: _MyClass;
begin
  Result := CreateComObject(CLASS_MyClass) as _MyClass;
end;

class function CoMyClass.CreateRemote(const MachineName: string): _MyClass;
begin
  Result := CreateRemoteComObject(MachineName, CLASS_MyClass) as _MyClass;
end;

procedure TMyClass.InitServerData;
const
  CServerData: TServerData = (
    ClassID:   '{D1F3B286-EF9A-38FB-A83C-42D1F40FE1FA}';
    IntfIID:   '{E4EA0A3A-DD45-379D-ACF6-C2B7CC047C66}';
    EventIID:  '';
    LicenseKey: nil;
    Version: 500);
begin
  ServerData := @CServerData;
end;

procedure TMyClass.Connect;
var
  punk: IUnknown;
begin
  if FIntf = nil then
  begin
    punk := GetServer;
    Fintf:= punk as _MyClass;
  end;
end;

procedure TMyClass.ConnectTo(svrIntf: _MyClass);
begin
  Disconnect;
  FIntf := svrIntf;
end;

procedure TMyClass.DisConnect;
begin
  if Fintf <> nil then
  begin
    FIntf := nil;
  end;
end;

function TMyClass.GetDefaultInterface: _MyClass;
begin
  if FIntf = nil then
    Connect;
  Assert(FIntf <> nil, 'DefaultInterface ist NULL. Die Komponente ist nicht mit dem Server verbunden. Sie müssen vor dieser Operation "Connect" oder "ConnectTo" aufrufen');
  Result := FIntf;
end;

constructor TMyClass.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
{$IFDEF LIVE_SERVER_AT_DESIGN_TIME}
  FProps := TMyClassProperties.Create(Self);
{$ENDIF}
end;

destructor TMyClass.Destroy;
begin
{$IFDEF LIVE_SERVER_AT_DESIGN_TIME}
  FProps.Free;
{$ENDIF}
  inherited Destroy;
end;

{$IFDEF LIVE_SERVER_AT_DESIGN_TIME}
function TMyClass.GetServerProperties: TMyClassProperties;
begin
  Result := FProps;
end;
{$ENDIF}

{$IFDEF LIVE_SERVER_AT_DESIGN_TIME}
constructor TMyClassProperties.Create(AServer: TMyClass);
begin
  inherited Create;
  FServer := AServer;
end;

function TMyClassProperties.GetDefaultInterface: _MyClass;
begin
  Result := FServer.DefaultInterface;
end;

{$ENDIF}

procedure Register;
begin
  RegisterComponents(dtlServerPage, [TMyClass]);
end;

end.
frank-wob
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Do 12.03.09 13:46 
Hallo,

du darfst die .NET DLL nicht behandeln wie eine normale Dll.
Die Schnittstelle stellt ja schon die tlb für dich.

Versuche mal:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
uses COMLib_TLB;

procedure test;
Var i:Integer;
 begin
  i := GiveMeAReturnValue;
  showMessage(inttostr(i));
 end;
researcher Threadstarter
Hält's aus hier
Beiträge: 14



BeitragVerfasst: Do 12.03.09 14:14 
Danke für eure bisherigen Antworten! :-)

Ich habe das Projekt nun folgendermaßen umgeschrieben:

ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
procedure TForm2.Button1Click(Sender: TObject);
Var i:Integer;
COMElement:COMLib_TLB.IMyClass;
begin
  i := COMElement.GiveMeAReturnValue();
  ShowMessage(IntToStr(i));
end;


Allerdings kommt beim anklicken auf den Button die Fehlermeldung:

Zugriffsverletzung bei Adresse 'blablabla' in Modul 'Project1.exe'. Lesen von Adresse 00000000000

hmm...ist doch zum verrückt werden...
Sinspin
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1335
Erhaltene Danke: 118

Win 10
RIO, CE, Lazarus
BeitragVerfasst: Do 12.03.09 14:46 
user profile iconresearcher hat folgendes geschrieben Zum zitierten Posting springen:
Danke für eure bisherigen Antworten! :-)

Ich habe das Projekt nun folgendermaßen umgeschrieben:

ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
procedure TForm2.Button1Click(Sender: TObject);
Var i:Integer;
COMElement:COMLib_TLB.IMyClass;
begin
  i := COMElement.GiveMeAReturnValue();
  ShowMessage(IntToStr(i));
end;


Allerdings kommt beim anklicken auf den Button die Fehlermeldung:

Zugriffsverletzung bei Adresse 'blablabla' in Modul 'Project1.exe'. Lesen von Adresse 00000000000


So dürfte das nichts werden.

versuch es mal so:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
procedure TForm2.Button1Click(Sender: TObject);
Var 
  i:Integer;
  MyClass: TMyClass;

begin
  myClass := TMyClass.Create(self);
  try 
    i := MyClass.GiveMeAReturnValue;
    ShowMessage(IntToStr(i));
  finally
    myClass.Free; // hm, könnte sein das du das nicht brauchst, da die Klasse ein Interface implementiert und sich damit selber verwaltet
  end;
end;


Ich finde aber an der generierten TLB einige Merkwürdigkeiten die sie von anderen TLB die ich bisher verwendet habe ein bisschen unterscheidet. Aber gehen tut es auf jeden Fall in dem Moment wie eine DOT Net dll COM Compatibel erzeugt wurde.

_________________
Wir zerstören die Natur und Wälder der Erde. Wir töten wilde Tiere für Trophäen. Wir produzieren Lebewesen als Massenware um sie nach wenigen Monaten zu töten. Warum sollte unser aller Mutter, die Natur, nicht die gleichen Rechte haben?
researcher Threadstarter
Hält's aus hier
Beiträge: 14



BeitragVerfasst: Do 12.03.09 17:08 
Super Danke - funktioniert einwandfrei!!! :-)