AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein GUI-Design mit VCL / FireMonkey / Common Controls Delphi Welches Objekt für COM-Server mit AktivX-Schnittstelle verwe
Thema durchsuchen
Ansicht
Themen-Optionen

Welches Objekt für COM-Server mit AktivX-Schnittstelle verwe

Ein Thema von tgoessi · begonnen am 31. Mai 2005 · letzter Beitrag vom 7. Sep 2007
Antwort Antwort
Seite 1 von 2  1 2      
tgoessi

Registriert seit: 31. Mai 2005
34 Beiträge
 
Delphi 5 Enterprise
 
#1

Welches Objekt für COM-Server mit AktivX-Schnittstelle verwe

  Alt 31. Mai 2005, 14:50
Hallo

In einer Applikation muss ich einem anderen Programm eine Active-X Schnittstelle zur Verfügung stellen. Verwendet wird ein IDispatch-Interface. Es sollen auch Events gefeuert werden können.

Ich habe nun mal einen Automation-Server programmiert und dazu das Objekt TAutoObject verwendet. In der Schnittstelle wird eine Collection verwendet, für die ich das Objekt TAutoIntfObject verwendet habe.

Wenn ich nun die Applikation starte und anschliessend den Prozess, der auf die Active-X Schnittstelle zugreift, wird das TAutoObject erzeugt. Vom TAutoObject wird anschliessend auch automatisch die Collection erzeugt und die zu exportierenden Werte eingefüllt, soweit OK.
Wenn ich vom externen Prozess aber auf die Collection zugreife, kann ich zwar die Werte auslesen. Nach dem Ende des Auslesens wird aber das TAutoIntfObject der Collection zerstört. Bei einem weiteren Zuggriff erhalte ich eine Exception.

Wie kann ich das machen, dass die Collection nach dem externen Zugriff nicht zerstört wird. Muss ich ein anderes Objekt verwenden?

Eine Zusatzfrage:
Mit dem TAutoObject wird die Applikation automatisch gestartet, falls von Extern ein Zugriff auf die Active-X Schnittstelle erfolgt. Ich möchte das aber so haben, dass ich die Applikation manuell starten muss und erst dann der Zugriff auf die Daten über Active-X möglich sind. Wie muss ich das machen? Muss ich ein anderes Objekt als TAutoObject verwenden? welches?

Danke für Eure Hilfe
Tom
  Mit Zitat antworten Zitat
Benutzerbild von Memo
Memo

Registriert seit: 19. Aug 2003
509 Beiträge
 
Delphi 7 Enterprise
 
#2

Re: Welches Objekt für COM-Server mit AktivX-Schnittstelle v

  Alt 31. Mai 2005, 15:10
Zitat von tgoessi:
Nach dem Ende des Auslesens wird aber das TAutoIntfObject der Collection zerstört. Bei einem weiteren Zuggriff erhalte ich eine Exception.

Wie kann ich das machen, dass die Collection nach dem externen Zugriff nicht zerstört wird. Muss ich ein anderes Objekt verwenden?
Müsste über CoAddRefServerProcess funktionieren.
  Mit Zitat antworten Zitat
shmia

Registriert seit: 2. Mär 2004
5.508 Beiträge
 
Delphi 5 Professional
 
#3

Re: Welches Objekt für COM-Server mit AktivX-Schnittstelle v

  Alt 31. Mai 2005, 15:38
Zitat von tgoessi:
Wie kann ich das machen, dass die Collection nach dem externen Zugriff nicht zerstört wird. Muss ich ein anderes Objekt verwenden?
Du musst die Collection in einer Variablen zwischenspeichern.
Also angenommen, dein Haupt- oder Einstiegsinterface sieht so aus:
Delphi-Quellcode:
IApplication = interface(IDispatch)
    ['{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}']
   function GetMyCollection:IMyCollection;safecall;
end;
Dann sieht die Implementierung ungefähr so aus:
Delphi-Quellcode:
  T_Application = class(TAutoObject, IConnectionPointContainer, IApplication)
  private
     FMyCollection : IMyCollection;
  protected
   function GetMyCollection:IMyCollection;safecall;
  end;

function T_Application.GetMyCollection:IMyCollection;safecall;
begin
   // die Collection wird beim 1. Mal erzeugt und "lebt" dann weiter bis zum Ende
   // oder bis FMyCollection auf nil gesetzt wird
   if not Assigned(FMyCollection) then
      FMyCollection := TMyCollection.Create(ComServer.TypeLib, IMycollection);
   Result := FMyCollection;
end;
Zitat von tgoessi:
Eine Zusatzfrage:
Mit dem TAutoObject wird die Applikation automatisch gestartet, falls von Extern ein Zugriff auf die Active-X Schnittstelle erfolgt. Ich möchte das aber so haben, dass ich die Applikation manuell starten muss und erst dann der Zugriff auf die Daten über Active-X möglich sind. Wie muss ich das machen? Muss ich ein anderes Objekt als TAutoObject verwenden? welches?
Grundsätzlich gilt für Automatisierungsobjekte:
Objekte, die von Aussen erzeugt werden dürfen, haben in der TLB eine CoClass und werden durch TAutoObject repräsentiert.
Andere Objekte, die erst später erzeugt werden, werden durch TAutoIntfObject repräsentiert.
Wenn du nicht willst, dass dein Objekt von aussen erzeugt werden kann, gibt es 2 Möglichkeiten:
- CoClass in der TLB (und in der Projektdatei) löschen. TAutoIntfObject verwenden.
bei Initialization das TAutoObjectFactory.Create löschen
- in der TLB bei der CoClass das Flag "Erzeugen möglich" entfernen
Danach geht von "Aussen" aber zunächst gar nichts mehr.
Du musst nun dein Objekt in der Anwendung selbst erzeugen und in der ROT (Running Object Table) registrieren.
Der Client kann nun mit GetActiveOleObject() Zugriff auf dein Objekt erhalten; allerdings nur, wenn deine Anwendung schon läuft.
Andreas
  Mit Zitat antworten Zitat
tgoessi

Registriert seit: 31. Mai 2005
34 Beiträge
 
Delphi 5 Enterprise
 
#4

Re: Welches Objekt für COM-Server mit AktivX-Schnittstelle v

  Alt 31. Mai 2005, 17:46
Hallo

Danke für den Tip aber so funktioniert es bei mir auch nicht.

Die Collection ist bei mir schon in einer Variable zwischengespeichert, da sie an einem Hauptobjekt angebunden ist.
Der Typ des Hauptobjekts ist TAutoObject, welches automatisch erzeugt wird. Beim Initialisieren des Hauptobjekts (Initialize) wird die Collection vom Typ TAutoIntfObject erzeugt und in der internen Variablen FSetupData zwischengespeichert. Beim Aufruf von GetMyCollection wird nur die interne Variable FSetupData zurückgegeben.
Der Grund. In der Collection werden Konfigurationsdaten gespeichert, die beim Erzeugen des Hauptobjekts da hineingeschrieben werden. Wird die Collection nach einem Zugriff gelöscht, sind die Daten auch weg.

Liege ich hier falsch oder funktioniert das dynamisch, d.h. bei jedem Aufruf der Collection müssen die Konfigurationsdaten neu geladen werden?

Gruss
Tom



Du musst die Collection in einer Variablen zwischenspeichern.
Also angenommen, dein Haupt- oder Einstiegsinterface sieht so aus:
Delphi-Quellcode:
IApplication = interface(IDispatch)
    ['{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}']
   function GetMyCollection:IMyCollection;safecall;
end;
Dann sieht die Implementierung ungefähr so aus:
Delphi-Quellcode:
  T_Application = class(TAutoObject, IConnectionPointContainer, IApplication)
  private
     FMyCollection : IMyCollection;
  protected
   function GetMyCollection:IMyCollection;safecall;
  end;

function T_Application.GetMyCollection:IMyCollection;safecall;
begin
   // die Collection wird beim 1. Mal erzeugt und "lebt" dann weiter bis zum Ende
   // oder bis FMyCollection auf nil gesetzt wird
   if not Assigned(FMyCollection) then
      FMyCollection := TMyCollection.Create(ComServer.TypeLib, IMycollection);
   Result := FMyCollection;
end;
  Mit Zitat antworten Zitat
shmia

Registriert seit: 2. Mär 2004
5.508 Beiträge
 
Delphi 5 Professional
 
#5

Re: Welches Objekt für COM-Server mit AktivX-Schnittstelle v

  Alt 31. Mai 2005, 18:11
Zitat von tgoessi:
Die Collection ist bei mir schon in einer Variable zwischengespeichert, da sie an einem Hauptobjekt angebunden ist.
Der Typ des Hauptobjekts ist TAutoObject, welches automatisch erzeugt wird. Beim Initialisieren des Hauptobjekts (Initialize) wird die Collection vom Typ TAutoIntfObject erzeugt und in der internen Variablen FSetupData zwischengespeichert. Beim Aufruf von GetMyCollection wird nur die interne Variable FSetupData zurückgegeben.
Das ist soweit alles richtig.
Optional könnte man die Collection erst bei 1. Aufruf von GetMyCollection erzeugt und befüllen; muss man aber nicht.
Wichtig ist auch, dass die Variable FSetupData ein Interfacepointer ist, da nur so die Referenzzählung richtig funkt.
Delphi-Quellcode:
FSetupData : TMycollection; // Falsch, kein Interfacepointer
FSetupData : IMyCollection; // Richtig
Zitat von tgoessi:
Der Grund. In der Collection werden Konfigurationsdaten gespeichert, die beim Erzeugen des Hauptobjekts da hineingeschrieben werden. Wird die Collection nach einem Zugriff gelöscht, sind die Daten auch weg.

Liege ich hier falsch oder funktioniert das dynamisch, d.h. bei jedem Aufruf der Collection müssen die Konfigurationsdaten neu geladen werden?
Das Collection-Objekt wurde einaml erzeugt und sollte weiter leben; das Laden der Konfigurationsdaten
braucht nur einmal durchgeführt werden.
Jetzt muss man natürlich weiter in die Tiefe gehen.
Ich würde mal die Funktionen _AddRef und _Release ersetzen und so die Referenzzählung beobachten:
Delphi-Quellcode:
TMyCollection = class(TAutoIntfObject, IMyCollection)
....
    function _AddRef: Integer; stdcall;
    function _Release: Integer; stdcall;
end;

function TMyCollection._AddRef: Integer;
begin
   Result := InterlockedIncrement(FRefCount);
   OutputDebugString(PChar('TMyCollection._AddRef='+IntToStr(Result)));
end;

function TMyCollection._Release: Integer;
begin
  Result := InterlockedDecrement(FRefCount);
   OutputDebugString(PChar('TMyCollection._Release='+IntToStr(Result)));
  if Result = 0 then
    Destroy;
end;
Andreas
  Mit Zitat antworten Zitat
tgoessi

Registriert seit: 31. Mai 2005
34 Beiträge
 
Delphi 5 Enterprise
 
#6

Re: Welches Objekt für COM-Server mit AktivX-Schnittstelle v

  Alt 1. Jun 2005, 10:02
Danke, so funktioniert es mal richtig.
Nun hab ich aber das Problem, dass ich nicht mehr auf die Funkion SetConfig zugreifen kann, mit der ich das Objekt mit den Konfigurationsdaten befülle, da diese von intern befüllt und daher nicht über ein Interface verfügt.

Ich versuchte es mal so:
FSetupData : TMyCollection;
FISetupData : IMyCollection;

und Create
FISetupData := Create.MyCollection;

aber ich kann dann
FSetupData := FISetupData as TMyCollection nicht zuweisen.

und
FISetupData.SetConfig kennt der Compiter logischerweise nicht.
Im Prinzip müsste ich ja nur den Pointer des MyCollection Objekts an FSetupData zuweisen, aber da spielt mir die Compilereinschränkung einen Streich.

Natürlich könnte ich auch ein Interface für diese Funktion definieren, aber dies macht keinen Sinn, da die Funktion nicht von Extern aufgerufen werden soll.

Tom



Das ist soweit alles richtig.
Optional könnte man die Collection erst bei 1. Aufruf von GetMyCollection erzeugt und befüllen; muss man aber nicht.
Wichtig ist auch, dass die Variable FSetupData ein Interfacepointer ist, da nur so die Referenzzählung richtig funkt.
Delphi-Quellcode:
FSetupData : TMycollection; // Falsch, kein Interfacepointer
FSetupData : IMyCollection; // Richtig
Zitat von tgoessi:
Der Grund. In der Collection werden Konfigurationsdaten gespeichert, die beim Erzeugen des Hauptobjekts da hineingeschrieben werden. Wird die Collection nach einem Zugriff gelöscht, sind die Daten auch weg.

Liege ich hier falsch oder funktioniert das dynamisch, d.h. bei jedem Aufruf der Collection müssen die Konfigurationsdaten neu geladen werden?
  Mit Zitat antworten Zitat
shmia

Registriert seit: 2. Mär 2004
5.508 Beiträge
 
Delphi 5 Professional
 
#7

Re: Welches Objekt für COM-Server mit AktivX-Schnittstelle v

  Alt 1. Jun 2005, 10:34
Zitat von tgoessi:
Natürlich könnte ich auch ein Interface für diese Funktion definieren, aber dies macht keinen Sinn, da die Funktion nicht von Extern aufgerufen werden soll.
Doch, ein 2. Interface wäre der richtige Weg.
Dieses [private] Interface wird aber nicht im TLB-Editor, sondern direkt im Sourcecode deklariert:
Delphi-Quellcode:
IMyCollectionSetup = Interface(IUnknown)
['{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}']
   procedure SetConfig(const filename:string);
end;
Da dieses Interface von IUnknown abgeleitet ist, kannst alle Delphi-Datentypen benutzen und brauchst kein SafeCall.
Du solltest eine GUID im Interface angeben, damit die Umwandlung mit as klappt:
   (FISetupData as IMyCollectionSetup).SetConfig(...);
Andreas
  Mit Zitat antworten Zitat
tgoessi

Registriert seit: 31. Mai 2005
34 Beiträge
 
Delphi 5 Enterprise
 
#8

Re: Welches Objekt für COM-Server mit AktivX-Schnittstelle v

  Alt 1. Jun 2005, 11:13
Das Funktioniert bei mir nicht richtig. Ich erhalte einen EIntfCastError, Interface not supported.
Eine GUID habe ich allerdings beim Private-Interface angegeben.
Fehlt da noch etwas. Die Datentypen sollte ja kein Problem sein.

Tom

Zitat von shmia:
Zitat von tgoessi:
Natürlich könnte ich auch ein Interface für diese Funktion definieren, aber dies macht keinen Sinn, da die Funktion nicht von Extern aufgerufen werden soll.
Doch, ein 2. Interface wäre der richtige Weg.
Dieses [private] Interface wird aber nicht im TLB-Editor, sondern direkt im Sourcecode deklariert:
Delphi-Quellcode:
IMyCollectionSetup = Interface(IUnknown)
['{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}']
   procedure SetConfig(const filename:string);
end;
Da dieses Interface von IUnknown abgeleitet ist, kannst alle Delphi-Datentypen benutzen und brauchst kein SafeCall.
Du solltest eine GUID im Interface angeben, damit die Umwandlung mit as klappt:
   (FISetupData as IMyCollectionSetup).SetConfig(...);
  Mit Zitat antworten Zitat
shmia

Registriert seit: 2. Mär 2004
5.508 Beiträge
 
Delphi 5 Professional
 
#9

Re: Welches Objekt für COM-Server mit AktivX-Schnittstelle v

  Alt 1. Jun 2005, 11:58
Zitat von tgoessi:
Das Funktioniert bei mir nicht richtig. Ich erhalte einen EIntfCastError, Interface not supported.
Eine GUID habe ich allerdings beim Private-Interface angegeben.
Fehlt da noch etwas. Die Datentypen sollte ja kein Problem sein.
Es muss natürlich ein neue, noch nicht verwendete GUID sein.
(Shift+Strg+G innerhalb der Delphi-IDE drücken.)
Ausserdem muss das Interface auch implementiert werden:
TMyCollection = class(TAutoIntfObject, IMyCollection, IMyCollectionSetup)
Andreas
  Mit Zitat antworten Zitat
tgoessi

Registriert seit: 31. Mai 2005
34 Beiträge
 
Delphi 5 Enterprise
 
#10

Re: Welches Objekt für COM-Server mit AktivX-Schnittstelle v

  Alt 1. Jun 2005, 12:13
Danke, der Fehler war, dass ich das Interface nicht in der Class angegeben haben. Nun funktioniert's.
Danke für Deine Hilfe

Tom

Zitat von shmia:
Zitat von tgoessi:
Das Funktioniert bei mir nicht richtig. Ich erhalte einen EIntfCastError, Interface not supported.
Eine GUID habe ich allerdings beim Private-Interface angegeben.
Fehlt da noch etwas. Die Datentypen sollte ja kein Problem sein.
Es muss natürlich ein neue, noch nicht verwendete GUID sein.
(Shift+Strg+G innerhalb der Delphi-IDE drücken.)
Ausserdem muss das Interface auch implementiert werden:
TMyCollection = class(TAutoIntfObject, IMyCollection, IMyCollectionSetup)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 19:23 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz