Acrobat Reader 表单关闭时出现 ActiveX 访问冲突

Acrobat Reader ActiveX Access Violation on form close

我的 Delphi 应用程序有一个使用 Acrobat Reader ActiveX 控件查看 pdf 的表单。当我使用控件的函数(LoadFile、gotoNextPage、gotoPreviousPage、gotoFirstPage、gotoLastPage)然后关闭窗体时,出现以下错误:"Access violation at address 6AF5703C. Read of address 6AF5703C"。当我运行应用程序,但不使用控件的功能,然后关闭窗体时,应用程序将正常退出。

有人知道此问题的修复或解决方法吗?

我的应用程序是使用 Delphi 5(旧版应用程序)编写的。我安装了 Adob​​e Acrobat Reader DC v15.016.20045。

正如我在对 Zam 的评论中所说,今天下载了 Acrobat Reader DC 的当前版本,我遇到了与您完全相同的错误。

请尝试此代码,让我们知道它是否为您避免了错误,因为它对我来说确实有效,而且没有 AV,无论是在 FormClose 还是之后。

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
var
  Ref : Integer;
begin
  Ref := AcroPdf1.ControlInterface._AddRef;
  AcroPdf1.Src := '';
  AcroPdf1.Free;
  AcroPdf1 := Nil;
end;

这是我的 FormCreate,其中包含我唯一的其他代码。

procedure TForm1.FormCreate(Sender: TObject);
begin
  AFileName := 'd:\aaad7\pdf\printed.pdf';
  AcroPdf1.src := AFileName;
  AcroPdf1.setZoom(200);  // <- this line is to exercise the
    // ControlInterface to provoke the AV on shutdown
end;

我完全不知道为什么我的 FormClose 避免了 AV 问题,而且在其他人这么说之前,是的,我也觉得它很疯狂!几乎没有什么值得这个名字的东西 "solution",但也许它会向那些比我更了解 COM 和 Ole 控件的人建议一个合适的解决方案。

我最初包括 Ref := AcroPdf1._AddRef 只是作为一个实验。我注意到在它之后,Ref的值为9。在AcroPdf1.Src := ''之后,在调试器评估器中调用AcroPdf1._Release返回值为4。我正要查看是否避免了AV通过反复调用 _Release 强制 RefCount 下降,然后 Presto!,在我第一次跟踪 FormClose 退出后没有 AV。

更新: 我没有详尽地测试以下内容,但是这个简化的 FormClose 也避免了 AV,无论如何在我的系统上:

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
var
  Ref : Integer;
begin
  Ref := AcroPdf1.ControlInterface._AddRef;
end;

显然,省略对 Ref 的赋值应该没有任何区别。

我在 64 位 Win10 上使用 Delphi 10 Seattle,顺便说一句。

更好的解决办法是编辑 "AcroPDFLib_Tlb.pas"

中的 TPDF 对象

只需将适当的析构函数添加到代码中即可释放 OLE 对象:

声明

Type
  TAcroPDF = class(TOleControl)
  ...
  public
    destructor Destroy; override; // <- New Line
  ...
  end;

实施

destructor TAcroPDF.Destroy;
begin
 FIntf := NIL;
 inherited;
end;