Acrobat Reader ActiveX Access Violation on form close
Asked Answered
F

2

9

My Delphi application has a form that uses the Acrobat Reader ActiveX control for viewing pdfs. When I use the control's functions (LoadFile, gotoNextPage, gotoPreviousPage, gotoFirstPage, gotoLastPage), then close the form, I get the following error: "Access violation at address 6AF5703C. Read of address 6AF5703C". When I run the app, but do not use the control's functions, and then close the form, the app will exit without error.

Anyone know of a fix or workaround for this issue?

My app is written using Delphi 5 (legacy app). I have Adobe Acrobat Reader DC v15.016.20045 installed.

Foret answered 17/6, 2016 at 16:0 Comment(3)
It's years since I used the TPDF object (import of PDFLib_Tlb.Pas) and I can't get it to run under Win10, but have you tried setting the FIntf member of the TPDF instance to Nil before you close your form? That would be the first thing I'd try. Btw despite the "F" prefix, FIntf is a public member.Quadripartite
similar with modern version of Delphi (DX10 including). i spent hours trying to find solution, but without success. rebuilding and modifying AdobeTlb file didn't help. i didn't try solution from @Quadripartite yet :) so far my code for release Adobe control in try except blockNonobservance
@Zam, I installed the current version of Reader DC and am getting the same problem, so far w/o solution. The Active X no longer has a public FIntf member, so don't bother with my suggestion.Quadripartite
Q
16

As I said in a comment to Zam, with the current version downloaded today of Acrobat Reader DC , I get the exact same error as you.

Please try this code and let us know whether it avoids the error for you, because it certainly works for me and there is no AV, either in the FormClose or afterwards.

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

This is my FormCreate, which contains my only other code.

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;

I have absolutely no idea why my FormClose avoids the AV problem, and before anybody else says so, yes, it looks mad to me, too! Hardly something that deserves the name "solution", but maybe it will suggest a proper solution to someone who knows more about COM and Ole controls than I do.

I originally included the Ref := AcroPdf1._AddRef just as an experiment. I noticed that after it, Ref's value was 9. After AcroPdf1.Src := '', calling AcroPdf1._Release in the debugger evaluator returned a value of 4. I was about to see if the AV was avoided by forcing the RefCount down by repeatedly calling _Release but then Presto!, there was no AV after my first trace into FormClose exited.

Update: I have not tested the following exhaustively, but this simplified FormClose also avoids the AV, on my system at any rate:

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

Obviously, omitting the assignment to Ref shouldn't make any difference.

I'm using Delphi 10 Seattle on 64-bit Win10, btw.

Quadripartite answered 17/6, 2016 at 19:51 Comment(5)
Would this cause a memory leak with instances of TAcroPdf? Maybe the interface's incremented reference count (_AddRef) is ignored when freeing the object reference. Don't call _Release prior to freeing the object reference. When I did I again got the access violation.Foret
This works perfectly on my Delphi 6 legacy app. In my case there is only one TAcroPDF object, created on app startup and destroyed on shutdown.Nonpareil
Nice, +1. The _AddRef() call fixes the access violation at the cost of the Acrobat Reader process sticking around (and consuming memory and some CPU cycles) until the termination of the parent process. Then the operating system will clean everything up.Monegasque
Thanks, Worked perfectlyWant
You save my day. Thanks !Lillie
M
4

The better solution is to edit the TPDF Object in "AcroPDFLib_Tlb.pas"

Just add the proper destructor to the Code to free the OLE Object:

Declaration

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

Implementation

destructor TAcroPDF.Destroy;
begin
 FIntf := NIL;
 inherited;
end;
Merchant answered 9/5, 2018 at 9:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.