Solved

Exploring a type library...

Posted on 2000-03-27
8
222 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
ID: 2661774
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
ID: 2676599
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
ID: 2683966
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
Use Case: Protecting a Hybrid Cloud Infrastructure

Microsoft Azure is rapidly becoming the norm in dynamic IT environments. This document describes the challenges that organizations face when protecting data in a hybrid cloud IT environment and presents a use case to demonstrate how Acronis Backup protects all data.

 

Expert Comment

by:Carpathia
ID: 2684242
You did NOT write this.

Its ripped from the Delphi COM Programming book (Eric Harmon).
0
 

Author Comment

by:jonnyfive
ID: 2684839
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
ID: 2686560
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
ID: 2686776
:-) I just say one thing: www.newriders.com/delphi

Have fun... Jonny...
0
 

Expert Comment

by:Carpathia
ID: 2687882
HEH.

Nice try Shadow :-)
0

Featured Post

Netscaler Common Configuration How To guides

If you use NetScaler you will want to see these guides. The NetScaler How To Guides show administrators how to get NetScaler up and configured by providing instructions for common scenarios and some not so common ones.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
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…
This video shows how to use Hyena, from SystemTools Software, to bulk import 100 user accounts from an external text file. View in 1080p for best video quality.

823 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