Donnerstag, 21. April 2016

PDFs über das olebrowser Control anzeigen / using the olebrowser control to display PDF files

Vor vielen Jahren stand ich vor der Aufgabe, eine PDF Datei innerhalb einer VFP Maske anzuzeigen. Gelöst habe ich dies über das Einbetten des olebrowser activeX Controls. Dieses Objekt bekam als Zielseite (über .Navigate ) einfach die anzuzeigende PDF Datei hinterlegt und fertig war die Laube.

Was passiert jedoch, wenn der Anwender auf die Idee kommt, die angezeigte Datei aus der VFP Anwendung heraus zu löschen? GENAU....es poppt eine Fehlermeldung auf, dass die Datei von einer anderen Applikation gesperrt wird....

Grund ist, dass das ole Control und der darin instanziierte PDF Reader die Datei zu diesem Zeitpunkt noch anzeigen und somit diese auch sperren, was das Löschen derselbigen unmöglich macht.

Um die Datei wieder frei zu bekommen genügt es leider nicht, dem Browser Control als neue anzuzeigende Seite "about:blank" zuzuweisen. Bis das Control hinter sich aufgeräumt hat, sprich der PDF Reader geschlossen wurde, dauert es leider ein paar Millisekunden. Ein einfaches WAIT WINDOW mit timeout und anschliessendem Löschen ist keine Option, denn je nach Systemauslastung ist die Aktion in kürzerer oder in längerer Zeit durchlaufen. Um auf Nummer sicher zu gehen muss eine Warteschleife mit Abprüfung der Control Eigenschaft '.ReadyState' her.

https://msdn.microsoft.com/en-us/library/bb268229%28v=vs.85%29.aspx

Wie im obigen Link nachzulesen ist, verfügt diese Eigenschaft über fünf Zustände

    READYSTATE_UNINITIALIZED = 0
    READYSTATE_LOADING = 1
    READYSTATE_LOADED = 2
    READYSTATE_INTERACTIVE = 3
    READYSTATE_COMPLETE = 4

von denen uns an dieser Stelle nur READYSTATE_COMPLETE = 4 interessiert.

Hier nun das notwendige Codesnippet:

?DeleteFileInBrowser( [c:\temp\myFile.pdf] )

FUNCTION DeleteFileInBrowser as Boolean
LPARAMETERS vFile as String

    LOCAL llReturn as Boolean
    llReturn = .F.
    
    IF FILE( vFile )

        DECLARE Sleep IN WIN32API INTEGER

        oBrowser = Thisform.oleBrowser
        oBrowser.Navigate( [about:blank] )
        DO WHILE oBrowser.ReadyState <> 4
                Sleep(200)                
        ENDDO 

        TRY 
            DELETE FILE ( vFile )
            llReturn = .T.
        CATCH 
            * Something went wrong
            * llReturn stays .F.
        ENDTRY 
        
    ENDIF 

    RETURN llReturn
    
ENDFUNC