Solved

Exploring a type library...

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

Expert Comment

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

Its ripped from the Delphi COM Programming book (Eric Harmon).
0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 

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

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

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

Suggested Solutions

Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
In my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy re…
A short film showing how OnPage and Connectwise integration works.
Delivering innovative fully-managed cloud services for mission-critical applications requires expertise in multiple areas plus vision and commitment. Meet a few of the people behind the quality services of Concerto.

929 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

10 Experts available now in Live!

Get 1:1 Help Now