Get COM object members through Delphi Olevariant type

Is it possible to get a list of members (properties, functions, procedures) for a COM object through the OleVariant type?

For example,

var wscript: Olevariant; begin wscript := CreateOleObject("WScript.Shell"); ... end; 

and I'm especially interested in getting a list of features like WScript.Echo, WScript.Quit, etc.

I want to have this function because it is good to implement automatic code completion.

+7
delphi com
source share
2 answers

You can use the GetTypeInfo and ITypeInfo methods.

Try this sample code (not complete, but you can use it as a starting point)

 {$APPTYPE CONSOLE} uses SysUtils, ActiveX, ComObj, Variants; //http://spec.winprog.org/typeinfo/ //http://spec.winprog.org/typeinf2/ //http://spec.winprog.org/typeinf3/ function GetTypeStr(tdesc : TTypeDesc; Context : ActiveX.ITypeinfo):string; var tinfo : ActiveX.ITypeInfo; bstrName : WideString; begin case tdesc.vt of VT_PTR : Result:=GetTypeStr(tdesc.ptdesc^,Context); VT_ARRAY : Result:=Format('Array of %s',[GetTypeStr(tdesc.padesc^.tdescElem,Context)]); VT_USERDEFINED : begin context.GetRefTypeInfo(tdesc.hreftype, tinfo); tinfo.GetDocumentation(-1, @bstrName, nil, nil, nil); Result:=bstrName; end else Result:=VarTypeAsText(tdesc.vt); end; end; //http://msdn.microsoft.com/en-us/magazine/dd347981.aspx Procedure InspectCOMOnbject(const ClassName: string); Var ComObject : OleVariant; Dispatch : IDispatch; Count : Integer; i,j,k : Integer; Typeinfo : ActiveX.ITypeinfo; ptypeattr : ActiveX.PTypeAttr; pfuncdesc : ActiveX.PFuncDesc;//http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.vswizard.tagfuncdesc.aspx rgbstrNames : TBStrList; cNames : Integer; bstrName : WideString; bstrDocString : WideString; sValue : string; sinvkind : string; begin ComObject := CreateOleObject(ClassName); Dispatch := IUnknown(ComObject) as IDispatch; OleCheck(Dispatch.GetTypeInfoCount(Count)); for i := 0 to Count-1 do begin OleCheck(Dispatch.GetTypeInfo(i,0,Typeinfo)); OleCheck(Typeinfo.GetTypeAttr(ptypeattr)); try case ptypeattr^.typekind of TKIND_INTERFACE, TKIND_DISPATCH : begin for j:=0 to ptypeattr^.cFuncs-1 do begin OleCheck(Typeinfo.GetFuncDesc(j, pfuncdesc)); try OleCheck(Typeinfo.GetNames(pfuncdesc.memid, @rgbstrNames, pfuncdesc.cParams + 1, cNames)); OleCheck(Typeinfo.GetDocumentation(pfuncdesc.memid,@bstrName,@bstrDocString,nil,nil)); if 1=1 then //pfuncdesc.elemdescFunc.tdesc.vt<>$0018 then begin //pfuncdesc.elemdescFunc.paramdesc case pfuncdesc.invkind of INVOKE_FUNC : if pfuncdesc.elemdescFunc.tdesc.vt = VT_VOID then sinvkind :='procedure' else sinvkind :='function'; INVOKE_PROPERTYGET : sinvkind :='get property'; INVOKE_PROPERTYPUT : sinvkind :='put property'; INVOKE_PROPERTYPUTREF : sinvkind :='ref property'; else sinvkind :='unknow'; end; { if bstrDocString<>'' then Writeln(Format('// %s',[bstrDocString])); } if pfuncdesc.cParams<=1 then begin if pfuncdesc.elemdescFunc.tdesc.vt = VT_VOID then Writeln(Format('%s %s;',[sinvkind,bstrName])) else Writeln(Format('%s %s : %s;',[sinvkind,bstrName,GetTypeStr(pfuncdesc.elemdescFunc.tdesc, Typeinfo)])); end else begin sValue:=''; for k := 1 to pfuncdesc.cParams do begin //Writeln(Format('%s : %d',[rgbstrNames[k], pfuncdesc.lprgelemdescParam[k-1].tdesc.vt])); sValue:= sValue + Format('%s : %s',[rgbstrNames[k], GetTypeStr(pfuncdesc.lprgelemdescParam[k-1].tdesc,Typeinfo)]); if k<pfuncdesc.cParams then sValue:=sValue+';'; end; if pfuncdesc.elemdescFunc.tdesc.vt = VT_VOID then Writeln(Format('%s %s (%s);',[sinvkind, bstrName, sValue])) else Writeln(Format('%s %s (%s) : %s;',[sinvkind, bstrName,SValue,GetTypeStr(pfuncdesc.elemdescFunc.tdesc, Typeinfo)])) end; //Writeln(pfuncdesc.elemdescFunc.tdesc.vt); end; finally Typeinfo.ReleaseFuncDesc(pfuncdesc); end; end; end; end; finally Typeinfo.ReleaseTypeAttr(ptypeattr); end; end; end; begin try CoInitialize(nil); try //InspectCOMOnbject('WbemScripting.SWbemLocator'); InspectCOMOnbject('Excel.Application'); //InspectCOMOnbject('Schedule.Service'); //InspectCOMOnbject('WScript.Shell'); finally CoUninitialize; end; except on E:EOleException do Writeln(Format('EOleException %s %x', [E.Message,E.ErrorCode])); on E:Exception do Writeln(E.Classname, ':', E.Message); end; Writeln('Press Enter to exit'); Readln; end. 
+7
source share

An object can implement IDispatchEx , then you can use GetNextDispID to list all members and GetMemberName and GetMemberProperties to find some (minimal) information about each member.

Or the object can implement IDispatch and, in particular, IDispatch::GetTypeInfo , then you can (with some difficulty) extract information about your members from the ITypeInfo object.

Before you ask, I do not know how to do this in Delphi.

If all else fails, you can read the documentation .

+2
source share

All Articles