如何获得所有的接口,这是支持的 Delphi 示例,可从IDispatch访问?

bwntbbo3  于 2023-03-29  发布在  其他
关注(0)|答案(1)|浏览(175)

动机:我得到了IDispatch指针作为我的努力的结果,我已经描述了我的前一个问题How to access workbooks from the ExcelApplication Delphi COM reference, currently there is no any?-试图访问所有打开的Excel示例从 Delphi 应用程序。
问题:现在我猜IDispatch点可以给予对一些非常有用的接口的访问-可能是ActiveX ExcelApplication,可能是Workbook,Worksheet或其他一些接口。

我尝试使用以下代码检查IDispatch指针:

IDisp: IDispatch;
  Report: TStringList;
  TypeInfo: ITypeInfo;
  TypeAttr: PTypeAttr;
  ii: Integer;
  RefTypeInfoCard: Cardinal;
  RefTypeInfo: ITypeInfo;
  RefTypeInfoAttr: PTypeAttr;
begin

  //...
  if Succeeded(IDisp.GetTypeInfo(0, 0, TypeInfo)) then begin
        // Get the TYPEATTR structure for the interface
        if Succeeded(TypeInfo.GetTypeAttr(TypeAttr)) then
        begin
          try
            // Loop through all of the supported interfaces and print their GUIDs
            for ii := 0 to TypeAttr.cImplTypes - 1 do
            begin
              if Succeeded(TypeInfo.GetRefTypeOfImplType(ii, RefTypeInfoCard)) then
              begin
                if Succeeded(TypeInfo.GetRefTypeInfo(RefTypeInfoCard, RefTypeInfo)) then
                begin
                  if Succeeded(RefTypeInfo.GetTypeAttr(RefTypeInfoAttr)) then
                  begin
                    Report.Add('     '+GUIDToString(RefTypeInfoAttr.guid));
                  end;
                end;
              end;
            end;
          finally
            TypeInfo.ReleaseTypeAttr(TypeAttr);
          end;
        end;
      end; 
end;

因此,我从IDisp阅读TypeInfo,并获得所有已实现的接口和每个接口的读取TypeInfor,最后我获得了它们的guid。
真是令人惊讶,但只有可访问的接口是GUID {00020400-0000-0000-C000-000000000046},这是IDispatch接口本身,如https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-oaut/58504586-e4af-44a3-be04-f1dc281b7429中所述。

我的问题是-我如何重写代码以读取给定的IDisapatch接口指针可访问的所有接口?

我使用的是 Delphi 6和Delphi 2009,但我猜在最近的Delphi版本中情况也是类似的。

olhwl3o2

olhwl3o21#

最有可能的是,我在问题中提供的代码已经可以工作了。
我添加了以下检查,在GUIDToString(TypeAttr.guid)等于{000208DA-0000-0000-C000-000000000046}的情况下执行:

IIWB: _Workbook;
begin
  //...
  IIWB:=nil;
  try
    Moniker.BindToObject(BindCtx, nil, IID__Workbook, IIWB);
    if IIWB=nil then begin
      //...
    end else begin
      //Do something important with Workbook, like IIWB.Close etc.
    end;
  except
    on E: Exception do begin
      //just in case...
    end;
  end;
  //...
end;

因此,我假设,我的代码中的基本类型信息(TypeInfoTypeAttr)是IDispatch,并且我应该从RefTypeInfoRepTypeInfoAttr中获得更精细(继承)的接口。我的假设是错误的,因为TypeInfo属性化返回的GUID等于以下内容:

Excel_TLB
IID__Workbook: TGUID = '{000208DA-0000-0000-C000-000000000046}';

所以,我的问题中的代码很可能是正确的,但最浅的TypeInfo指的是最幼稚的类型,而不是最基本的类型。

相关问题