3

我们正在使用一些旧代码(由 Binh Ly 创建的 ComLib.pas),因此我们可以在 (OleVariant) 对象上使用枚举接口:

type
  TDispNewEnum = dispinterface
    ['{97079E31-6957-11D2-9154-0000B4552A26}'] // dummy
    property _NewEnum: IUnknown readonly dispid -4; // DISPID_NEWENUM
    function _NewEnumFunc: IUnknown; dispid -4; // DISPID_NEWENUM
  end;

procedure TEnumVariant.AttachUnknown (const Unk: IUnknown);
var
  pDisp: IDispatch;
  _NewEnumPropFailed: boolean;
  Unknown: IUnknown;
begin
  Detach;
  Unknown := Unk;
  { extract IEnumVariant }
  if (Unknown <> nil) then
  begin
    { try IEnumVariant }
    if not (Succeeded (Unknown.QueryInterface (IEnumVariant, FEnumVariant))) then
    begin
      FEnumVariant := nil;  // safety!

      { test _NewEnum prop and _NewEnum func }
      if (Succeeded (Unknown.QueryInterface (IDispatch, pDisp))) then
      begin
        _NewEnumPropFailed := False;
        try
          //property _NewEnum
          Unknown:=TDispNewEnum(pDisp)._NewEnum; // <---- RAISES EXCEPTION -----
          if not (Succeeded(Unknown.QueryInterface(IEnumVariant, FEnumVariant))) then
            FEnumVariant := nil;  // safety!
        except
          _NewEnumPropFailed := True;
        end;  { except }

此代码适用于 Delphi 2010 和 2007,但不适用于 XE2。在上面标记的行(带有注释“RAISES EXCEPTION”),我们得到一个异常:

项目 x.exe 引发异常类 $C0000005,并带有消息“0xbaadf00d 处的访问冲突:读取地址 0xbaadf00d”。

传入的对象确实具有 TDispNewEnum 接口,因此不应引发异常(如 Delphi 2010 和 2007 的情况)。

建议?谢谢。

4

1 回答 1

5

内存地址是一个伪内存地址,意思是“ 0xbaadf00dBAD FOOD”(查看十六进制字符)。当您请求无效接口或调用时,通常由代码使用。

如果将行更改为:

pDisp: TDispNewEnum;
...
if (Succeeded (Unknown.QueryInterface (IDispatch, pDisp))) then
begin
   _NewEnumPropFailed := False;
   try
     //property _NewEnum
     Unknown:= pDisp._NewEnum; 
...

这对我来说更有意义。

注意到XE2 接口绑定中有一些未记录的更改。可能正因为如此,先前带有强制类型转换 ( TDispNewEnum(pDisp)) 的代码不再起作用。

于 2011-10-24T12:42:18.497 回答