Solved

Exploring a type library...

Posted on 2000-03-27
8
226 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

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

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

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

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 The parallel port is a very commonly known port, it was widely used to connect a printer to the PC, if you look at the back of your computer, for those who don't have newer computers, there will be a port with 25 pins and a small print…
Come and listen to Percona CEO Peter Zaitsev discuss what’s new in Percona open source software, including Percona Server for MySQL (https://www.percona.com/software/mysql-database/percona-server) and MongoDB (https://www.percona.com/software/mongo-…
NetCrunch network monitor is a highly extensive platform for network monitoring and alert generation. In this video you'll see a live demo of NetCrunch with most notable features explained in a walk-through manner. You'll also get to know the philos…

724 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