![]() |
Wie ermitteln, ob ein COM-Objekt eine bestimmte Methode hat?
Also:
Ich habe einen Interfacezeige X mit 'late binding'. Vielleicht implementiert der eine Methode namens 'Foo', vielleicht aber auch nicht. Ich will soetwas schreiben:
Delphi-Quellcode:
Frage: Wie geht sowas?
If InterfaceImplementsMethod (X,'Foo') Then
X.Foo |
Re: Wie ermitteln, ob ein COM-Objekt eine bestimmte Methode
mit .GetIDsOfNames() geht dies. Ist schon länger her das ich das benutzt habe. Dein COM Object steht ja in einem Variant. Delphi erzeugt nun Code beim Aufruf einer Methode der im Codesegement den Namen der Methode als String ablegt, ebenso Paramater usw.
Falls du den Source für ComObj Delphi5 hast sieht das so aus:
Delphi-Quellcode:
hoffe ich mache mich nicht strafbar ?
{ Call GetIDsOfNames method on the given IDispatch interface }
procedure GetIDsOfNames(const Dispatch: IDispatch; Names: PChar; NameCount: Integer; DispIDs: PDispIDList); procedure RaiseNameException; begin raise EOleError.CreateResFmt(@SNoMethod, [Names]); end; type PNamesArray = ^TNamesArray; TNamesArray = array[0..0] of PWideChar; var N, SrcLen, DestLen: Integer; Src: PChar; Dest: PWideChar; NameRefs: PNamesArray; StackTop: Pointer; Temp: Integer; begin Src := Names; N := 0; asm MOV StackTop, ESP MOV EAX, NameCount INC EAX SHL EAX, 2 // sizeof pointer = 4 SUB ESP, EAX LEA EAX, NameRefs MOV [EAX], ESP end; repeat SrcLen := StrLen(Src); DestLen := MultiByteToWideChar(0, 0, Src, SrcLen, nil, 0) + 1; asm MOV EAX, DestLen ADD EAX, EAX ADD EAX, 3 // round up to 4 byte boundary AND EAX, not 3 SUB ESP, EAX LEA EAX, Dest MOV [EAX], ESP end; if N = 0 then NameRefs[0] := Dest else NameRefs[NameCount - N] := Dest; MultiByteToWideChar(0, 0, Src, SrcLen, Dest, DestLen); Dest[DestLen-1] := #0; Inc(Src, SrcLen+1); Inc(N); until N = NameCount; Temp := Dispatch.GetIDsOfNames(GUID_NULL, NameRefs, NameCount, GetThreadLocale, DispIDs); if Temp = Integer(DISP_E_UNKNOWNNAME) then RaiseNameException else OleCheck(Temp); asm MOV ESP, StackTop end; end; { Central call dispatcher } procedure VarDispInvoke(Result: PVariant; const Instance: Variant; CallDesc: PCallDesc; Params: Pointer); cdecl; procedure RaiseException; begin raise EOleError.CreateRes(@SVarNotObject); end; var Dispatch: Pointer; DispIDs: array[0..MaxDispArgs - 1] of Integer; begin if TVarData(Instance).VType = varDispatch then Dispatch := TVarData(Instance).VDispatch else if TVarData(Instance).VType = (varDispatch or varByRef) then Dispatch := Pointer(TVarData(Instance).VPointer^) else RaiseException; GetIDsOfNames(IDispatch(Dispatch), @CallDesc^.ArgTypes[CallDesc^.ArgCount], CallDesc^.NamedArgCount + 1, @DispIDs); if Result <> nil then VarClear(Result^); DispatchInvoke(IDispatch(Dispatch), CallDesc, @DispIDs, @Params, Result); end; Bei einem Source wie
Delphi-Quellcode:
legt der Compiler quasi sowas an
var
Obj: Variant; // OleVariant begin Obj := CreateCOMObject(); // oder ähnliches Obj.Print('Test'); end;
Delphi-Quellcode:
Das ist jetzt aber eine sehr abstrahierte Umschreibung.
const codesegemnt
sProcName = 'Print'#0; const BSS sParam = 'Test'; var Obj: Variant; // OleVariant Result: Variant; begin Obj := CreateCOMObject(); // oder ähnliches VarDispInvoke(Result, Obj, sProcName, sParams); if Result then ; end; Es könnte durchaus sein das es auch schon eine entsprechend einfachere Funktion in neueren Delphi Versionen dafür gibt. Eines steht fest, späte Bindung funktioniert nur mit IDispatch abgeleiteten Interfaces und diese haben auch meistens eine ITypeLib. Über diese werden die DispIDs, Parameter und Namen hinterlegt. Gruß Hagen |
Re: Wie ermitteln, ob ein COM-Objekt eine bestimmte Methode
Ansonsten könntest du auch mit einem try except Block arbeiten (erinnert mich an den anderen Thread ;) ).
Aber schön ist das wirklich nicht, ich halte es eher so wie du und würde auch versuchen sowas vorher abzufangen. Allerdings beudetet das noch längst nicht das dann keine Exceptions merh ausgelösst werden. Also wenn man weis ob eine Methode mit Namen XYZ in einer Variante existent ist. Denn die Parameter müssen ja auch noch stimmen. Schöner wäre es eine globale Funktion wie TryVarDispInvoke() zu haben mit einem globalen Exceptionhandler und Return Result. Gruß Hagen |
Re: Wie ermitteln, ob ein COM-Objekt eine bestimmte Methode
Hi Hagen,
Ich wusste doch, das es geht... Sieht aber ziemlich pervers aus. Das mit den Parametern ist schon ok, wenn es die Funktion gibt, dann weiss ich auch, wie man sie verwendet. Es geht um eine neue Version eines Interfaces. Die Autoren haben eine neue Funktion eingebaut, die aber erst demnächst installiert wird. Ich muss aber heute schon den Client entsprechend anpassen. Also muss ich soetwas wie 'Kannst Du das schon?' implementieren. Derzeit ist natürlich die Try...Except-Geschichte implementiert, aber neee. :kotz: Dann lieber die perverse Lösung. Ich checke gleich mal, wie das so geht. Danke. |
Re: Wie ermitteln, ob ein COM-Objekt eine bestimmte Methode
Zitat:
|
Re: Wie ermitteln, ob ein COM-Objekt eine bestimmte Methode
Jupp, große Firma voll mit Deppen.
|
Re: Wie ermitteln, ob ein COM-Objekt eine bestimmte Methode
Hier die Lösung:
Delphi-Quellcode:
Und ein Danke an Hagen und OregonGhost. Ich werd mich mal in der Firma beschweren gehen.
Function InterfaceSupportsMember (anInterface : IDispatch; Const aMembername : WideString) : Boolean;
Var iDispID : TDispId; Res : Integer; Begin Res :=anInterface.GetIDsOfNames(GUID_NULL, @aMembername, 1, LOCALE_SYSTEM_DEFAULT, @iDispID); Result := Res <> Integer(DISP_E_UNKNOWNNAME) End; [edit] Const vor aMembername gesetzt [/edit] |
Re: Wie ermitteln, ob ein COM-Objekt eine bestimmte Methode
Zitat:
Normalerweise holt man sich ein Interface (z.B. IHTMLElement) und prüft dann ob z.B. das Interface IHTMLElement2 verfügbar ist (in Delphi macht man das mit der Supports()-Funktion). Bei später Bindung gibt es diese Möglichkeit in aller Regel nicht. Dort ist man gezwungen immer auf dem gleichen Interface zu arbeiten. |
Re: Wie ermitteln, ob ein COM-Objekt eine bestimmte Methode
Zitat:
Gruß hagen |
Re: Wie ermitteln, ob ein COM-Objekt eine bestimmte Methode
Jawoll!
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:43 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz