表单关闭时 Acrobat Reader ActiveX 访问冲突
Posted
技术标签:
【中文标题】表单关闭时 Acrobat Reader ActiveX 访问冲突【英文标题】:Acrobat Reader ActiveX Access Violation on form close 【发布时间】:2016-06-17 16:00:57 【问题描述】:我的 Delphi 应用程序有一个使用 Acrobat Reader ActiveX 控件查看 pdf 的表单。当我使用控件的功能(LoadFile、gotoNextPage、gotoPreviousPage、gotoFirstPage、gotoLastPage),然后关闭表单时,我收到以下错误:“地址 6AF5703C 的访问冲突。读取地址 6AF5703C”。当我运行应用程序,但不使用控件的功能,然后关闭窗体,应用程序将退出而没有错误。
有人知道此问题的修复或解决方法吗?
我的应用是使用 Delphi 5(旧版应用)编写的。我已安装 Adobe Acrobat Reader DC v15.016.20045。
【问题讨论】:
自从我使用 TPDF 对象(PDFLib_Tlb.Pas 的导入)以来已经有好几年了,我无法让它在 Win10 下运行,但是您之前是否尝试过将 TPDF 实例的 FIntf 成员设置为 Nil你关闭你的表格?那将是我要尝试的第一件事。顺便说一句,尽管有“F”前缀,但 FIntf 是公共成员。 与现代版 Delphi(包括 DX10)类似。我花了几个小时试图找到解决方案,但没有成功。重建和修改 AdobeTlb 文件没有帮助。我还没有尝试来自@MartynA 的解决方案 :) 到目前为止,我在 try except 块中发布 Adobe 控件的代码 @Zam,我安装了当前版本的 Reader DC 并且遇到了同样的问题,到目前为止没有解决方案。 Active X 不再有公开的 FIntf 成员,所以不要理会我的建议。 【参考方案1】:正如我在对 Zam 的评论中所说,使用今天下载的 Acrobat Reader DC 的当前版本,我遇到了与您完全相同的错误。
请尝试此代码并让我们知道它是否可以为您避免错误,因为它确实对我有用,并且在 FormClose
或之后没有 AV。
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 问题,而且在其他人这么说之前,是的,我也觉得它很生气!几乎没有什么值得称为“解决方案”的东西,但也许它会为比我更了解 COM 和 Ole 控件的人提供一个合适的解决方案。
我最初包含Ref := AcroPdf1._AddRef
只是作为一个实验。我注意到在它之后,Ref
的值是 9。在 AcroPdf1.Src := ''
之后,在调试器评估器中调用 AcroPdf1._Release
返回值 4。我正要查看是否通过强制 RefCount 向下来避免 AV反复调用_Release
,然后是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。
【讨论】:
这会导致 TAcroPdf 实例的内存泄漏吗?释放对象引用时,可能会忽略接口的递增引用计数 (_AddRef)。在释放对象引用之前不要调用 _Release。当我这样做时,我再次遇到访问冲突。 这在我的 Delphi 6 旧版应用程序上完美运行。就我而言,只有一个 TAcroPDF 对象,在应用启动时创建并在关闭时销毁。 很好,+1。_AddRef()
调用以 Acrobat Reader 进程停留(并消耗内存和一些 CPU 周期)直到父进程终止为代价来修复访问冲突。然后操作系统将清理所有内容。
谢谢,完美运行
你拯救了我的一天。谢谢!【参考方案2】:
更好的解决方案是在“AcroPDFLib_Tlb.pas”中编辑 TPDF 对象
只需在代码中添加适当的析构函数即可释放 OLE 对象:
声明
Type
TAcroPDF = class(TOleControl)
...
public
destructor Destroy; override; // <- New Line
...
end;
实施
destructor TAcroPDF.Destroy;
begin
FIntf := NIL;
inherited;
end;
【讨论】:
以上是关于表单关闭时 Acrobat Reader ActiveX 访问冲突的主要内容,如果未能解决你的问题,请参考以下文章
Adobe Reader自动更新成Adobe Acrobat Reader DC下载的安装文件存放在哪里的?
Adobe acrobat reader 的最新版本是啥 win7 64位的
Adobe Reader来填写的表单无法保存,我怎么做pdf表单才能使别人可以用Adobe Reader来填写的表单能保存