Link to home
Start Free TrialLog in
Avatar of andreamatt
andreamatt

asked on

AcroPdf Open File from Resource

Hi,

I need to open a PDF file with TAcroPdf activex object (unit AcroPDFLib_TLB with Delphi 7) but the file must stay in the Resource (.RES) not in some folders.

Thanx in advance
Avatar of Emmanuel PASQUIER
Emmanuel PASQUIER
Flag of France image

You can (probably must) save the resource in a temp file, open it and delete it.
Avatar of andreamatt
andreamatt

ASKER

Sorry, but I don't want to use the hard disk, devices or folders. Any type or folders.

You can can save the pdf as a resource but unfortunately, AcroPDF can not load pdf from stream. You have to save it to a temporary location or find a different PDF component that can load from stream
Yes, ewangoya, thank you to confirm that AcroPdf cannot load from a memory/stream.
There are effectively other PDF components, but finding the one that can load from memory will be some work... And it most probably won't be cheap

What is wrong with using a temp file ?
Thanks for the responses.

For security problems I don't want to save the PDF in a temp file.
I have search for other PDF component but the TAcroPDF has some advantages over other.
you probably can afford to save the PDF to a file, load it and delete it immediately after.
That would be an adequate solution until you find the PDF component of your dreams, that can do anything and that is cheap or even free...
Well, we have rights to dream no ?
If you find something that suits your needs, tell us so that it could help others
you are aware that someone competent enough to grab the file the few seconds it is available in your drive before you delete it, will be also capable of getting the file from the resource in the exe ? unless you also crypt that file in your resource and decrypt on the fly before using it
@epasquire
You are quite right. There are lots lousy pdf components out there that i dont think its worth wasting time on.
And sure enough, anything in the resource can be accessed.

A temp file is a good idea to me, but then thats me
I have make many test before asking this question.
If have tested the code for: save the PDF in a temp dir - load the PDF with TAcroPDF - delete the PDF but is it not secure at 100%.

If I save a crypted PDF and after decrypt it on the fly I must save it on a temp folder before load with TAcroPDF... and I have the same problem. Or you have a solution for this?
What is the main security concern?, You do not want people to copy or view the document unless from your application

If we know this, we may be able to design a solution for it
No, there is no solution, except spending more and more time to look for the perfect PDF component that does what you want, if it exists.
Know that there is NO 100% secure solution, that just doesn't exists whatever the problem is. A "secured" solution is then what is enough to avoid the vast majority of the cases.
If the PDF is not that big, then the Acrobat activeX will not take much time to load it. So you can delete it very quickly, and there is not that many people around that will know how to grab it on the fly.
And those people would first have to know what you are doing, and really want to bypass your security. Is your file so sensitive ?
I only talked about crypted file to make you understand that the real security concern in your system is not the temp file, but the resource in the exe. IF you don't crypt that resource.
So no need to talk hours about the temp file if you don't have already secured the biggest problem
Yes ewangoya, this is my problem. What solution you have?
I'm talking of ways to have the file encrypted in the resource and when saved to a temp file, somehow lock that file so it cant be opened or copied by any other process
For epasquier. Thanks for your long response.
My resource file is also encrypted in the .exe.
I know the problem for "many people around" but the document must be protected for special people. I know also that this is very difficult (and in some cases impossible like you write) but the system to use a temp file PDF is so simple.
For a big PDF (100Mbytes) that stay in a slow device like a USB Flash Drive the time to copy-load-delete is not very quickly.
For ewangoya.

> I'm talking of ways to have the file encrypted in the resource and when saved to a temp file, somehow lock that file so it cant be opened or copied by any other process

Ok, but if the file is encrypted I can't open it with TAcroPDF!
> For a big PDF (100Mbytes) that stay in a slow device like a USB Flash Drive
> the time to copy-load-delete is not very quickly.
Only an idiot would set a USB flash Drive for his system TEMP folder. Aside from being real slow, it murders the poor flash drive which have a very limited nb of rewrite longevity (~10.000 cycles)
Or use C:\WINDOWS\TEMP, I don't think Windows can be installed in USB flash drive

Ewangoya idea is to lock the temp file for other operations. That is a good idea. The first thing would be to set that file as Hidden. Then use whatever technique to give exclusive access to your application for this file, even blocking reading access for other process. That is probably possible, but is that really needed ?

Sorry Epasquier but for your:
"Only an idiot would set a USB flash Drive for his system TEMP folder"
I have not set the USB Flash Drive for a temp folder! I have the .EXE in the flash Drive. But when I try to extract the .RES in a folder like C:\TEMP is very slow... because if you know... the process to read data in a USB Flash Drive is very slow.

Also sorry for the hidden file solution but is so simple to see for an expert.
ah, but if that is the reading part that is slow, then that is easily fixed : you load the resource in memory, THEN only :
- save to temp file
* hide/lock the file and other techniques
- load the file in PDF componnent
* unlock the file
- delete it

so the file is only on your hard drive the time the PDF component load from hard drive. And besides, since it just has been written, it should be in the system cache so loading time should be just a flash

Here is an Object with two methods to lock and unlock the file.
You save the file to a temporary folder then Load it with AcroPDF
(You can create a temporary folder at runtime and later remove it, this way you can always create a folder with a unique name)
Lock the file
when you are done viewing the file,unlock it and delete it

//

private
  FFileLocker: TFileLock;

procedure LoadPDF(const AFileName: string);
begin
  //load to AcroPDF
.....
   FFileLocker.Lock(AFileName);
end;

procedure UnLoadPDF;
begin
   //close AcroPDF
  FileLock.UnLock;
 
  //delete file
end;


type
  TFileLock = class(TObject)
  private
    FFileHandle: THandle;
    FFileName: string;
    FFileSize: Longint;
  public
    function Lock(const AFileName: string): Boolean;
    procedure UnLock;
  end;

implementation

{ TFileLock }

function TFileLock.Lock(const AFileName: string): Boolean;
begin
  FFileName := AFileName;
  FFileHandle := CreateFile(PChar(AFileName), GENERIC_READ or GENERIC_WRITE, 0, nil, OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL, 0);
  Result := FFileHandle <> INVALID_HANDLE_VALUE;
  if Result then
  begin
    FFileSize := GetFileSize(FFileHandle, nil);
    Result := LockFile(FFileHandle, 0, 0, FFileSize, 0);
    if not Result then
    begin
      CloseHandle(FFileHandle);
      FFileHandle := 0;
      FFileSize := 0;
    end;
  end;
end;

procedure TFileLock.UnLock;
begin
  if FFileHandle > 0 then
  begin
    UnlockFile(FFileHandle, 0, 0, FFileSize, 0);
    CloseHandle(FFileHandle);
    FFileHandle := 0;
    FFileSize := 0;
  end;
end;

Open in new window

I do not know how you managed to compile 100 MB PDF file in .res, I tried even 63 MB with no success.

Let's assume you managed to do that, it is not advisable to have such huge exe file.

If you still insist on having the 100 MB PDF in the exe and you want to open it without extracting to the hard disk, you can use the OleContainer.

First you must set the required security options to your pdf file (disable printing, changing the document, content copying, ... etc) then load it in the OleContainer and when you want to open the file just write in onbuttonclick or onFormCreate:

OleContainer.Run;
OleContainer.DoVerb(ovPrimary);
OleContainer.DoVerb(ovInPlaceActivate);
OleContainer.DoVerb(ovshow);

Please note, it will open the file with the associate default PDF (external application) but from your exe without copying the file to the hard disk.

ewangoya : excellent job, you only have to add Hidden parameters to further trouble the average guy

JimiX : I have not used OleContainer since a while, are you sure you can first load a PDF from a stream in there ? If that is the case, that is even better than using TAcroPDF at all. A bit more complex during initialization, but then I think you can access the activeX interface of Acrobat from the OleContainer directly, and do whatever is needed
a simpler solution would be to drop a webbrowser onto the form then point the browser to the resource using the res:// protocol --
see if attached example works for you.
damn filter
doesn't like my zip

go get example here

http://www.lorenzomonti.it/listing/respdf.zip
Thanks for every solutions.

For ewangoya:
This can be a particular solution. But for me is very important to not use a temp dir and to load the file in memory.

For jimyX
The OleContainer is a good solution. The problem is that I have the PDF in another new window. I don't have find a solution to view the PDF inside the main Form. Do you have a solution for this?

For lomo74
Thanks for the code. The problem for the TWebBrowser is this: after the view, is it possible to find the PDF file in the cache of Windows. Also... I don't have find a solution for this...


>> The problem for the TWebBrowser is this: after the view, is it possible to find the PDF file
>> in the cache of Windows.
Most probably, yes...
what about rendering PDF directly with e.g. ghostscript.
you feed data to ghostscript through pipe (or maybe use DLL version of ghostscript), use the "display" device and receive back raster... have some examples if you are interested.
rather complicated though, and heavy CPU and memory consuming since you have to store all PDF in memory as raster images... don't know if this is acceptable for you
Thanks Iomo74 but I prefere to use the TAcroPDF.
> are you sure you can first load a PDF from a stream in there ?

Although the OleContainer has LoadFromStream method but the PDF file should be loaded directly in the OleContainer by browsing and locating it to be embedded in the exe.

solution to view the PDF inside the main Form.

You can implement the function from the link below which will enable your program to load the Acrobat Reader first in your form and then ask the OleContainer to open the file in it.

https://www.experts-exchange.com/questions/20682510/how-open-programa-in-delphi-form-area.html#8950787

I tried this method successfully with Adobe Acrobat 8 Professional. However it did not load the Acrobat Reader version 9.
If Acrobat in OleContainer cannot load from a stream, then there is no gain compared to AcroPDF
andreamatt, I'm starting to really believe you have no choice but implement a hidden+locked temp file solution.
Thanxs jimyX but it is essential that the code works with any version of the Adobe Reader as well as with any operating system (XP, Vista, Seven).
Hi ewangoya
I hav try your code in ID: 34202694 but I have an EAccessViolation at
FFileName := AFileName;

Do you have a full functional example?

ASKER CERTIFIED SOLUTION
Avatar of Ephraim Wangoya
Ephraim Wangoya
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
After some testing, if I have understand this are the steps:

1) Creation protect folder
2) Save the PDF file that stay in resource to file in the folder protect
3) Load file in TAcroPDF
4) Lock file
5) Unlock file
6) Delete file and protect folder


The problem is to lock the file during the 2-3 step not after.

This is a very good code but this not solve the problem. Right?
If you lock the file before loading it, then you will not be able to load it at all.
Yes... this is the problem.
If no answers come in the comings days, I will give you the 500 points.