Solved

Exploring a type library...

Posted on 2000-03-27
8
224 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

Industry Leaders: 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

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…
Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
Attackers love to prey on accounts that have privileges. Reducing privileged accounts and protecting privileged accounts therefore is paramount. Users, groups, and service accounts need to be protected to help protect the entire Active Directory …
Are you ready to implement Active Directory best practices without reading 300+ pages? You're in luck. In this webinar hosted by Skyport Systems, you gain insight into Microsoft's latest comprehensive guide, with tips on the best and easiest way…

749 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