Solved

Exploring a type library...

Posted on 2000-03-27
8
220 Views
Last Modified: 2010-05-18
Hi everyone...

I want to write a tool, which can examine a COM objects type library and display it's methods, propertys and needed parameters. How would I start with that? Is there any API function to retrieve this information? IDispatch doesn't seem to useful to me.

Regards, Jonny...
0
Comment
Question by:jonnyfive
  • 3
  • 2
  • 2
  • +1
8 Comments
 
LVL 12

Expert Comment

by:rwilson032697
Comment Utility
Well, you already have one!

When Delphi imports a type library it constructs a .TLB file, basically an interface unit describing all the interfaces, methods and parameters etc.

If you then open that _TLB.Pas file you will be able to use the explorer view to do what you want.

If you already knew this and want to write a new tool to do this from scratch ignore this comment :-)

Cheers,

Raymond.
0
 

Expert Comment

by:Carpathia
Comment Utility
Im presuming you want to explore third part OCX's without access to the TLB file that Delphi generates.

I wrote a routine to get the classname, interfaces, and guids out of any library. I cant remember the exact implementation, i'll post it on monday.

In the meantime, i recall that it involved using the ITypeInfo interface, and the PTypeAttr type, and calling GetDocumentation. There are other methods to explore interfaces and enums.
I maybe even used ITypeLib, not sure if it exists.






0
 

Accepted Solution

by:
ShadowFax earned 100 total points
Comment Utility
Hi Jonny,

Here's some code from an app I wrote:

procedure TForm1.FormCreate(Sender: TObject);
begin
      if ParamCount > 0 then
  begin
            OleCheck(LoadTypeLib(PWideChar(WideString(paramstr(1))), FLib)) ;
    LoadTypeLibrary ;
  end;
end;

procedure TForm1.LoadTypeLibrary;
var
      LibAttr: PTLibAttr ;
  TypeInfo: ITypeInfo ;
  TypeLibIndex: Integer ;
  AName: WideString ;
  ADocString: WideString ;
  AHelpContext: LongInt ;
  AHelpFile: WideString ;
  TypeAttr: PTypeAttr ;
  RootNode: TTreeNode ;
begin
      Screen.Cursor := crHourGlass ;
  try
    TreeView1.Items.BeginUpdate ;
    try
      TreeView1.Items.Clear ;
      FLib.GetDocumentation(-1, @AName, @ADocString, @AHelpContext, @AHelpFile) ;
      RootNode := TreeView1.Items.AddChild(nil, AName) ;
      OleCheck(FLib.GetLibAttr(LibAttr)) ;
      try
        TreeView1.Items.AddChild(RootNode, GUIDToString(LibAttr.guid)) ;
        TreeView1.Items.AddChild(RootNode, 'Version ' + IntToStr(LibAttr.wMajorVerNum) + '.' +
              IntToStr(LibAttr.wMinorVerNum)) ;
        TreeView1.Items.AddChild(RootNode, 'LCID: ' + IntToStr(LibAttr.lcid)) ;
      finally
                        FLib.ReleaseTLibAttr(LibAttr) ;
      end;
      if ADocString <> '' then
            TreeView1.Items.AddChild(RootNode, 'Help string: ' + ADocString) ;
      if AHelpContext <> 0 then
            TreeView1.Items.AddChild(RootNode, 'Help context: ' + IntToStr(AHelpContext)) ;
      if AHelpFile <> '' then
            TreeView1.Items.AddChild(RootNode, 'Help file: ' + AHelpFile) ;
      FEnemRoot := TreeView1.Items.AddChild(RootNode, 'Enum') ;
      FDispatchRoot := TreeView1.Items.AddChild(RootNode, 'Displatch') ;
      FInterfaceRoot := TreeView1.Items.AddChild(RootNode, 'Interface') ;
      FCoClassRoot := TreeView1.Items.AddChild(RootNode, 'CoClass') ;
      FUnknownRoot := TreeView1.Items.AddChild(RootNode, 'Unknown') ;
      for TypeLibIndex := 0 to FLib.GetTypeInfoCount -1 do
      begin
                        FLib.GetTypeInfo(TypeLibIndex, TypeInfo) ;
        OleCheck(TypeInfo.GetTypeAttr(TypeAttr)) ;
        try
          case TypeAttr.typekind of
                TKIND_ENUM :
                  LoadEnum(TypeInfo, TypeAttr) ;
            TKIND_DISPATCH, TKIND_INTERFACE :
                  LoadInterface(TypeInfo, TypeAttr) ;
            TKIND_COCLASS :
                  LoadCoClass(TypeInfo, TypeAttr) ;
            else
                  TreeView1.Items.AddChild(FUnknownRoot, 'Unrecognized type: ' +
                    IntToStr(TypeAttr.typekind)) ;
          end;
        finally
                              TypeInfo.ReleaseTypeAttr(TypeAttr) ;
        end;
      end;
                  RootNode.Expand(False) ;
    finally
                  TreeView1.Items.EndUpdate ;
    end;
  finally
            Screen.Cursor := crDefault ;
  end;
end;

procedure TForm1.LoadCoClass(TypeInfo: ITypeInfo; TypeAttr: PTypeAttr);
var
      TypeLibNode: TTreeNode ;
  AName: WideString ;
  ADocString: WideString ;
  AHelpContext: LongInt ;
  FunctionsNode: TTreeNode ;
  FuncIndex: Integer ;
  RefType: Cardinal ;
  TypeInfo2: ITypeInfo ;
begin
      TypeInfo.GetDocumentation(-1, @AName, @ADocString, @HelpContext, nil) ;
  TypeLibNode := TreeView1.Items.AddChild(FCoClassRoot, AName) ;
  TreeView1.Items.AddChild(TypeLibNode, GUIDToString(TypeAttr.GUID)) ;
  if ADocString <> '' then
        TreeView1.Items.AddChild(TypeLibNode, 'Help string: ' + ADocString) ;
  if AHelpContext <> 0 then
        TreeView1.Items.AddChild(TypeLibNode, 'Help context: ' + IntToStr(AHelpContext)) ;
  FunctionsNode := TreeView1.Items.AddChild(TypeLibNode, 'Implements') ;
  for FuncIndex := 0 to TypeAttr.cImplTypes -1 do
  begin
            TypeInfo.GetRefTypeOfImplType(FuncIndex, RefType) ;
    TypeInfo.GetRefTypeInfo(RefType, TypeInfo2) ;
    TypeInfo2.GetDocumentation(-1, @AName, nil, nil, nil) ;
    TreeView1.Items.AddChild(FunctionsNode, AName) ;
  end;
end;

procedure TForm1.LoadEnum(TypeInfo: ITypeInfo; TypeAttr: PTypeAttr);
var
      TypeLibNode: TTreeNode ;
  AName: WideString ;
      ADocString: WideString ;
  AHelpContext: LongInt ;
  ValuesNode: TTreeNode ;
  ValueNode: TTreeNode ;
  ValueIndex: Integer ;
  VarDesc: PVarDesc ;
begin
      TypeInfo.GetDocumentation(-1, @AName, @ADocString, @AHelpContext, nil) ;
  TypeLibNode := TreeView1.Items.AddChild(FEnemRoot, AName) ;

  TreeView1.Items.AddChild(TypeLibNode, 'Version ' + IntToStr(TypeAttr.wMajorVerNum)
        + '.' + IntToStr(TypeAttr.wMinorVerNum)) ;
  if ADocString <> '' then
        TreeView1.Items.AddChild(TypeLibNode, 'Help String: ' + ADocString) ;
  if AHelpContext <> 0 then
        TreeView1.Items.AddChild(TypeLibNode, 'Help Context: ' + IntToStr(AHelpContext)) ;

  ValuesNode := TreeView1.Items.AddChild(TypeLibNode, 'Values') ;
  for ValueIndex := 0 to TypeAttr.cVars -1 do
  begin
            TypeInfo.GetVarDesc(ValueIndex, VarDesc) ;
    try
      TypeInfo.GetDocumentation(VarDesc.memid, @AName, @ADocString, @AHelpContext, nil) ;
      ValueNode := TreeView1.Items.AddChild(ValuesNode, AName) ;
      if ADocString <> '' then
            TreeView1.Items.AddChild(ValueNode, 'Help String: ' + ADocString) ;
      if AHelpContext <> 0 then
            TreeView1.Items.AddChild(ValueNode, 'Help Context: ' + IntToStr(AHelpContext)) ;
    finally
                  TypeInfo.ReleaseVarDesc(VarDesc) ;
    end;

  end;
end;

procedure TForm1.LoadInterface(TypeInfo: ITypeInfo; TypeAttr: PTypeAttr);
var
      TypeLibNode: TTreeNode ;
  AName: WideString ;
  ADocString: WideString ;
  AHelpContext: LongInt ;
  FunctionsNode: TTreeNode ;
  FunctionNode: TTreeNode ;
  FuncIndex: Integer ;
  FuncDesc: PFuncDesc ;
  ParametersNode: TTreeNode ;
  ParamIndex: Integer ;
  Names: PBStrList ;
  cNames: Integer ;
begin
      TypeInfo.GetDocumentation(-1, @AName, @ADocString, @AHelpContext, nil) ;
  if TypeAttr.typekind = TKIND_DISPATCH then
        TypeLibNode := TreeView1.Items.AddChild(FDispatchRoot, AName)
  else
        TypeLibNode := TreeView1.Items.AddChild(FInterfaceRoot, AName) ;
  TreeView1.Items.AddChild(TypeLibNode, GUIDToString(TypeAttr.GUID)) ;
  TreeView1.Items.AddChild(TypeLibNode, 'Version ' + IntToStr(TypeAttr.wMajorVerNum) + '.' +
        IntToStr(TypeAttr.wMinorVerNum)) ;
  if ADocString <> '' then
        TreeView1.Items.AddChild(TypeLibNode, 'Help string: ' + ADocString) ;
  if AHelpContext <> 0 then
        TreeView1.Items.AddChild(TypeLibNode, 'Help context: ' + IntToStr(AHelpContext)) ;
  New(Names) ;
  try
    FunctionsNode := TreeView1.Items.AddChild(TypeLibNode, 'Functions') ;
    for FuncIndex := 0 to TypeAttr.cFuncs -1 do
    begin
                  TypeInfo.GetFuncDesc(FuncIndex, FuncDesc) ;
      try
        TypeInfo.GetDocumentation(FuncDesc.memid, @AName, @ADocString, @AHelpContext, nil) ;
        FunctionNode := TreeView1.Items.AddChild(FunctionsNode, AName) ;
        if ADocString <> '' then
              TreeView1.Items.AddChild(FunctionNode, 'Help string: ' + ADocString) ;
        if AHelpContext <> 0 then
              TreeView1.Items.AddChild(FunctionNode, 'Help context: ' + IntToStr(AHelpContext)) ;
        if FuncDesc.cParams > 0 then
        begin
              ParametersNode := TreeView1.Items.AddChild(FunctionNode, 'Parameters') ;
              TypeInfo.GetNames(FuncDesc.memid, Names, sizeof(TBStrList), cNames) ;
          for ParamIndex := 1 to FuncDesc.cParams do
                TreeView1.Items.AddChild(ParametersNode, Names[ParamIndex]) ;
        end;
      finally
            TypeInfo.ReleaseFuncDesc(FuncDesc) ;
      end;
    end;
  finally
            Dispose(Names) ;
  end;

end;

HTH

Gavin
0
 

Expert Comment

by:Carpathia
Comment Utility
You did NOT write this.

Its ripped from the Delphi COM Programming book (Eric Harmon).
0
What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

 

Author Comment

by:jonnyfive
Comment Utility
Well, I suppose I will accept this answer. I just bought the "Delphi COM Programming" book my self and find it very useful. Since Gavin just copy-pasted existing code (leave alone claiming it as his own) without any further explaination or comments, I will rate this with D.

Regards, Jonny
0
 

Expert Comment

by:ShadowFax
Comment Utility
I suppose the fact that I typed the whole app out from the book deserves no commendation yet makes it my own.

0
 

Author Comment

by:jonnyfive
Comment Utility
:-) I just say one thing: www.newriders.com/delphi

Have fun... Jonny...
0
 

Expert Comment

by:Carpathia
Comment Utility
HEH.

Nice try Shadow :-)
0

Featured Post

What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

Join & Write a Comment

This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
This video shows how to remove a single email address from the Outlook 2010 Auto Suggestion memory. NOTE: For Outlook 2016 and 2013 perform the exact same steps. Open a new email: Click the New email button in Outlook. Start typing the address: …
This video demonstrates how to create an example email signature rule for a department in a company using CodeTwo Exchange Rules. The signature will be inserted beneath users' latest emails in conversations and will be displayed in users' Sent Items…

772 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

14 Experts available now in Live!

Get 1:1 Help Now