2016-06-17 36 views
6

Meine Delphi-Anwendung hat ein Formular, das das Acrobat Reader ActiveX-Steuerelement zum Anzeigen von PDFs verwendet. Wenn ich die Funktionen des Steuerelements (LoadFile, GotoNextPage, GotoPreviousPage, GotoFirstPage, GotoLastPage) verwende, dann schließe das Formular, ich bekomme den folgenden Fehler: "Zugriffsverletzung bei Adresse 6AF5703C. Lesen der Adresse 6AF5703C". Wenn ich die App ausführen, aber die Funktionen des Steuerelements nicht verwenden und das Formular dann schließe, wird die App ohne Fehler beendet.Acrobat Reader ActiveX-Zugriffsverletzung beim Schließen des Formulars

Wer kennt eine Lösung oder einen Workaround für dieses Problem?

Meine App wurde mit Delphi 5 (Legacy App) geschrieben. Ich habe Adobe Acrobat Reader DC v15.016.20045 installiert.

+1

Es ist Jahre her, dass ich das TPDF-Objekt (Import von PDFLib_Tlb.Pas) verwendet habe und ich kann es nicht unter Win10 ausführen, aber haben Sie versucht, das FIntf-Mitglied der TPDF-Instanz auf Nil zu setzen, bevor Sie Ihr Formular schließen? Das wäre das erste, was ich versuchen würde. Übrigens ist FIntf trotz des Präfix "F" ein öffentliches Mitglied. – MartynA

+1

ähnlich mit der modernen Version von Delphi (DX10 einschließlich). Ich verbrachte Stunden damit, eine Lösung zu finden, aber ohne Erfolg. Neuaufbau und Änderung der AdobeTlb-Datei hat nicht geholfen. Ich habe noch nicht versucht, Lösung von @MartynA :) bis jetzt mein Code für die Freigabe Adobe-Steuerelement in Versuch außer Block – Zam

+0

@Zam, installierte ich die aktuelle Version von Reader DC und bekomme das gleiche Problem, so weit w/o Lösung. Das Active X hat kein öffentliches FIntf-Mitglied mehr, also machen Sie sich keine Gedanken über meinen Vorschlag. – MartynA

Antwort

8

Wie ich in einem Kommentar zu Zam sagte, mit der aktuellen Version von Acrobat Reader DC, die ich heute heruntergeladen habe, bekomme ich genau den gleichen Fehler wie Sie.

Bitte versuchen Sie diesen Code und lassen Sie uns wissen, ob es den Fehler für Sie vermeidet, denn es funktioniert sicherlich für mich und es gibt kein AV, weder in der FormClose noch danach.

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

Das ist mein FormCreate, das meinen einzigen anderen Code enthält.

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; 

Ich habe absolut keine Ahnung, warum mein FormClose das AV-Problem vermeidet, und vor allen anderen so sagt, ja, es sieht für mich auch verrückt! Kaum etwas, das den Namen "Lösung" verdient, aber vielleicht schlägt es jemandem, der mehr über COM- und Ole-Steuerungen weiß als ich, eine angemessene Lösung vor.

ursprünglich enthielt ich die Ref := AcroPdf1._AddRef nur als ein Experiment. Ich bemerkte, dass danach Ref Wert 9 war. Nach AcroPdf1.Src := '', Aufruf AcroPdf1._Release im Debugger-Evaluator zurückgegeben einen Wert von 4. Ich war im Begriff zu sehen, wenn das AV vermieden wurde, indem RefCount durch wiederholtes Aufrufen _Release aber dann Presto !, es gab keine AV nach meiner ersten Spur in FormClose beendet.

Update: ich folgende erschöpfend nicht getestet, aber diese vereinfachte FormClose vermeidet auch das AV, auf meinem System auf jeden Fall:

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

Offensichtlich zu Ref die Zuordnung Weglassen nicht machen sollte jede Differenz.

Ich benutze Delphi 10 Seattle auf 64-Bit-Win10, BTW.

+0

Würde dies bei Instanzen von TAcroPdf zu einem Speicherverlust führen? Möglicherweise wird die inkrementierte Referenzzahl (_AddRef) der Schnittstelle beim Freigeben der Objektreferenz ignoriert. Rufen Sie _Release nicht auf, bevor Sie die Objektreferenz freigeben. Als ich das tat habe ich erneut die Zugriffsverletzung bekommen. – mcdon

+0

Das funktioniert perfekt auf meiner Delphi 6 Legacy App. In meinem Fall gibt es nur ein TAcroPDF-Objekt, das beim Start der App erstellt und beim Herunterfahren zerstört wird. – pacpinto

+0

Schön, +1. Der Aufruf '_AddRef()' behebt die Zugriffsverletzung auf Kosten des Acrobat Reader-Prozesses, der bis zur Beendigung des übergeordneten Prozesses (und dabei Speicher- und einige CPU-Zyklen belegt) bleibt. Dann wird das Betriebssystem alles aufräumen. – mghie