[Delphi] functies op DCOM server/ AppServer aanroepen

Pagina: 1
Acties:
  • 142 views sinds 30-01-2008
  • Reageer

  • Tomatoman
  • Registratie: November 2000
  • Laatst online: 17:51

Tomatoman

Fulltime prutser

Topicstarter
Al eerder is er een topic geweest over het aanroepen van functies op een DCOM server. De theorie is me duidelijk, maar de praktijk blijkt lastig. Het is me al gelukt om functies aan de IAppServer interface van mijn DCOM server toe te voegen met de type library editor. Die functies waren ook nog aan te roepen op de client, maar niet probleemloos.

Ten eerste lukt het me niet om aan een functie parameters met een [in, out] of [out] specifier toe te voegen, ongeacht het parametertype. De type library editor begint dan steevast te klagen dat hij alleen [out] parameters van een pointer type toestaat in een automation server. Dat zegt me weinig.

Ten tweede krijg ik een access violation op de client als een een functie op de server aanroep die een WideString (in de type library een BSTR) als functieresultaat retourneert. Functies die een OleEnum retourneren werken probleemloos. En ook [in] parameters van het type WideString worden probleemloos doorgegeven. Wat gaat hier mis?

Ten derde lukt het me niet om de DCOM server te benaderen (gebruikmakend van TDCOMConnection.AppServer) via early binding, want de compiler ligt dwars. Alleen via de dispinterface lukt het me:
with IMijnAppServerDisp(IDispatch(DCOMConnection.AppServer) do …
Hoe bewerkstellig ik early binding via DCOMConnection.AppServer?

Kan iemand me op weg helpen? Ik werk trouwens met Delphi 7 Enterprise.

Een goede grap mag vrienden kosten.


  • Tomatoman
  • Registratie: November 2000
  • Laatst online: 17:51

Tomatoman

Fulltime prutser

Topicstarter
* kick *

Een goede grap mag vrienden kosten.


  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

Je moet de typen met het * er achter hebben (de pointers). Dus long * ipv long. Maar het is makkelijker als je de typelib editor op Pascal zet ipv IDL. Menu -> Tools -> Environment -> Type Library -> Language = Pascal.

Makkelijker als de typelib editor gebruiken om 1 functie toe te voegen is gewoon rechtermuistoets op de classe declaratie van de RemoteDataModule in de Code Editor en Add To Interface kiezen. Daar kan je de declaratie van je functie geven die dan aan de interface wordt toegevoegd....

Early binding aan de client kant krijg je door m te typecasten zoals jij al doet, maar m dan ook in een var op te slaan van dat type. En niet de Disp interface gebruiken op die manier. Als je een interface in een Variant stopt gebruikt Delphi automatisch de disp interface.
Delphi:
1
2
3
4
5
var MijnAppServer: IMijnAppServer;
begin
  MijnAppServer := DCOMConnection.AppServer as IMijnAppServer;  // is het niet GetServer?
  MijnAppServer.JouwFunctie;
end;

We adore chaos because we like to restore order - M.C. Escher


  • Tomatoman
  • Registratie: November 2000
  • Laatst online: 17:51

Tomatoman

Fulltime prutser

Topicstarter
Je moet de typen met het * er achter hebben (de pointers). Dus long * ipv long. Maar het is makkelijker als je de typelib editor op Pascal zet ipv IDL. Menu -> Tools -> Environment -> Type Library -> Language = Pascal.
Eerder werkte dat niet. Blijkbaar had ik eerst mijn project moeten sluiten voor ik omschakelde naar Pascal.
Makkelijker als de typelib editor gebruiken om 1 functie toe te voegen is gewoon rechtermuistoets op de classe declaratie van de RemoteDataModule in de Code Editor en Add To Interface kiezen. Daar kan je de declaratie van je functie geven die dan aan de interface wordt toegevoegd....
Dat was ik allang weer vergeten. Thanks!
// is het niet GetServer?
Ja dus :o. Ik had al een paar uur gefrustreerd zitten klooien en had blijkbaar de frisse blik van iemand anders nodig.

* Tomatoman draagt LordLarry voor om een lintje te krijgen.

Een goede grap mag vrienden kosten.


  • jelmervos
  • Registratie: Oktober 2000
  • Niet online

jelmervos

Simple user

Ik herinner mij plots dat ik dit ook eens heb gemaakt: [rml][ Delphi] DCOM server met een fuction?[/rml]

"The shell stopped unexpectedly and Explorer.exe was restarted."


  • cimbom
  • Registratie: Juni 2001
  • Laatst online: 26-04-2024

cimbom

Just Kidding

Ik zal dit even kicken, want er zijn geen andere topics eigenlijk.

Nou ik gebruik dus early binding omdat ik het moet. Want met late binding kan ik geen records ,die in Type library zijn gedefineerd, als parameter aan de dcom functies meegeven.

Het probleem met early binding is dat er in registry van client de path naar de sever ook opgenomwen wordt. BV: C:\Appserver\MijnServer.exe. En die MijnServer.exe moet wel benaderbaar zijn voor cleint andeers krijg je error "interface not supported". Client start die MijnServer.exe niet, maar moet toch door client benaderbaar zijn.

Mijn vraag kan dit omgezeild worden door nog steeds early binding te gebruiken?
Of kan ik met een trucje ook records als parameter geven aan DCOM functies met latebinding.

  • Tomatoman
  • Registratie: November 2000
  • Laatst online: 17:51

Tomatoman

Fulltime prutser

Topicstarter
Client start die MijnServer.exe niet, maar moet toch door client benaderbaar zijn.
Geen probleem, dat regelt DCOM voor je. Een keer de server starten op de remote machine en alles is in order. Helaas moet je meestal nog wel de DCOM-instellingen voor het serverprogramma aanpassen met dcomcnfg.exe

Voor wat betreft die records: je kunt de recordstructuren vervangen door OLE arrays, waarbij je ieder array-element gebruikt als een member van de record. Dat is de oplossing die ook in veel boeken wordt aangegeven.

Een goede grap mag vrienden kosten.


  • cimbom
  • Registratie: Juni 2001
  • Laatst online: 26-04-2024

cimbom

Just Kidding

tomatoman schreef op 18 July 2003 @ 13:24:
[...]
Geen probleem, dat regelt DCOM voor je. Een keer de server starten op de remote machine en alles is in order. Helaas moet je meestal nog wel de DCOM-instellingen voor het serverprogramma aanpassen met dcomcnfg.exe
Ik bedoelde eigenlijk dat voor client applicatie moet de fysieke exe file benaderbaar zijn.
Het hoeft niet hetzelfde dir te zijn als bij remote machine. Maar alleen registeren is niet genoeg op client. Die exe file moet dus benaderbaar (want ik het register staat het wel opgenomen, path naar exe file)zijn.

  • Tomatoman
  • Registratie: November 2000
  • Laatst online: 17:51

Tomatoman

Fulltime prutser

Topicstarter
Voor zover ik weet hoeft de exe van de server niet fysiek bereikbaar te zijn vanaf de client. Natuurlijk staat op de computer met de server wel een link in het register naar de plaats waar de executable van de server staat, want dat is waar COM en DCOM hun informatie vinden over hoe ze de server moeten starten. Die registerinformatie is bedoeld voor (D)COM en niet voor de client.

Een goede grap mag vrienden kosten.


  • cimbom
  • Registratie: Juni 2001
  • Laatst online: 26-04-2024

cimbom

Just Kidding

tomatoman schreef op 18 July 2003 @ 14:18:
Voor zover ik weet hoeft de exe van de server niet fysiek bereikbaar te zijn vanaf de client. ................
Ja, met early binding moet het dus. Anders krijg je error 'Interface not supported'.

  • Tomatoman
  • Registratie: November 2000
  • Laatst online: 17:51

Tomatoman

Fulltime prutser

Topicstarter
'Interface not supported' krijg je als de server niet netjes is geregisteerd door COM. Dat heeft er niets mee te maken of de server-executable toegankelijk is vanaf de client. COM start immers de server, niet de client.

Een goede grap mag vrienden kosten.


  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

cimbom schreef op 18 July 2003 @ 14:45:
Ja, met early binding moet het dus. Anders krijg je error 'Interface not supported'.
Uh? Late binding bedoel je dan denk ik....

Wat je client moet weten is hoe de interface er van de service er uit ziet. Als je late binding gebruikt omzeil je dat omdat je dan nooit echt weet met welke interface je aan het praten bent. Als je toch gewoon lekker, veilig en snel early binding wilt gebruiken zal je er voor moeten zorgen dat de tlb van de server op de client wordt geregistreerd. Dat kan heel bot door je server ook op de client te registreren, maar das wel een beetje zonde. Dit betekend overgens niet dat dan ook altijd je server op je client wordt gebruikt. Je kan ook alleen de tlb gebruiken die in de dll zit. Je kan beter gewoon alleen de server tlb registreren mbv 'tregsvr -t myserver.tlb'. Je kan ook met wat meer moeite die tlb van de server als resource in je client stoppen en m zelf in de lucht laden zodra je client start.

Kortom: Het maakt de client niet uit waar de server staat en kan dit zelfs niet eens weten. Wat de client wel moet weten bij early binding is hoe de interface er van de server uit ziet. Dit staan in de tlb. Die moet dus wel geregistreerd zijn op de client. Via de originele server.dll of alleen de server.tlb.

[ Voor 37% gewijzigd door LordLarry op 18-07-2003 15:06 . Reden: quote ]

We adore chaos because we like to restore order - M.C. Escher


  • cimbom
  • Registratie: Juni 2001
  • Laatst online: 26-04-2024

cimbom

Just Kidding

LordLarry schreef op 18 July 2003 @ 15:02:
[...]

Uh? Late binding bedoel je dan denk ik....

Je kan ook alleen de tlb gebruiken die in de dll zit. Je kan beter gewoon alleen de server tlb registreren mbv 'tregsvr -t myserver.tlb'.
Nee early binding..

Onze appservers zijn gewoon exe files. Wat wij moesten doen was die appservers ook op client registreren omdat we early binding moeten gebruiken wegens die records.
Ik heb net zoals je zei op client 'tregsvr -t myserver.tlb' geregistreerd. p zich is dit hetzelfde met wat we doen, maar dan wordt het i.p.v. verwijzing naar de exe file(appserver) komt er verwijzing naar die tlb bestand. Dus die tlb bestand moet wel benaderbaar zijn op client. 9Dus hetzelfde probleem wat ik had0. Dit is wel minder erg omdat niet het hele exe file op client hoeft. Maar ik denk dat we zoals je zei die tlb bestand als resource in client executable zetten zodat we geen extra deployment hebben.

Maar het is dus wel zo bij early binding moet tlb bestand (als je 'tregsvr -t myserver.tlb' gebruikt) beschikbaar zijn op client. Omdat we appserver via myserver.exe hebben geregistreerd moest de myserver.exe file beschikbaar zijn op client (op de een of andere manier haalt client mischien tlb bestand uit de exe?
).

Maar in ieder geval bedankt voor tip/help. Ik weet nu beter hoe ik ermee om mot gaan.

PS: Tomaten je krijgt echt wel 'interface not supported' error hoor. Ik registreerde myserver.exe op client (dit moest wegens early binding) en verwijder die myserver.exe of verander folder naam waarin hij staat dan krijg je die error.


edit:
Voor zover ik weet hoeft de exe van de server niet fysiek bereikbaar te zijn
Het was mischien niet duidelijk maar, wat op client staat is ook niet verwijzing naar server waar mijn echte appserver staat, maar een copie van appserver voor registratie zeg maar.

[ Voor 10% gewijzigd door cimbom op 18-07-2003 16:10 ]


  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

Waarom jij early binding MOET gebruiken kan ik me niet voorstellen, late binding is juist veel soepeler, maar het lijkt me zo ie zo de meest gewenste optie.

Ja, de tlb moet te vinden zijn voor windows. Waar die te vinden is staat in het registry. Of hij staat in de ActiveX Server zelf (de server exe in jouw geval). Of hij staat als .tlb bestand ergens op de schijf. Of hij staat in de client zoals mijn laatste voorstel. In alle gevallen moeten die verwijzingen naar de tlb voor de client te berijken zijn.

Ik zie niet waar jij een probleem ziet. Het is gewoon zoals het moet en dus is er geen probleem. :) Hoogstens iets wat je niet verwacht had of niet gewenst vind.

We adore chaos because we like to restore order - M.C. Escher

Pagina: 1