Adobe X Enable Protected Mode at Startup - disable via code
Asked Answered
I

2

6

Our application, write in Delphi, generates a series of reports, most of then in PDF format, that opens automatically when it is generated. Adobe X introduced a feature that is enabled by default "Enable Protected Mode at Startup". The report pdf files are opened using "ShelExecute".

var 
  pdfFile: string; 
begin 
  pdfFile := 'C:\Users\Ronaldo\Documents\appName\reports\file.pdf'; 
  ShellExecute(0, 'open', PChar(pdfFile), '', '', SW_SHOW);
  // 
end;

Because of this new Adobe Reader new setting, under Win 7 or Vista, we are getting an error message when opening the document. Double clicking the document to open it does not give any problem. Is there a way to disable the protected method - or another way to open the document without getting the error (a workaround)?

*Some more information *

The PDF file is being generated on our server application, streamed to the client and the client generates the pdf (using Write) - First I though that could be the problem - but again, why the double click works fine.

I have create a dummy app that do nothing but use the same above code to open the pdf, and it works. I have checked the privileges of the application - all the same - the only difference is that the one that is not working is being installed on the OS using a proper installer - the other (the dummy one) I just created and dropped it there.

One of the comments ask about the file association - this should not be an issue since the application succeed in launching Adobe reader - Adobe reader then gives me the "access denied" error message. A double click on the same file works fine.

New info - 30/03/2011 - 2:50pm - New Zealand time

I have made a change to the code just to test the only one difference between the app itself and the dummy app. Instead of getting the file path and file name automatically, it now opens a OpenDialog - the Filename property of the opendialog is used as parameter to ShellExecute (as the comment after Ken answer states) - it works. Why is it that, when you get the file name from an open dialog, it works - note that I am not openning the file from the dialog - I'm getting the filename, and using it as a parameter to ShellExecute.

Updated code sample

When the user clicks the "generate report" button, the report is opened automatically after it is generated. Apart from that, there is a grid, showing all the generated reports so far, for that user - this is the code on the double click for that grid:

if GetSelectedReport <> nil then // this will check if the user selected an report
  if TReportItemState(GetSelectedReport.State)  in [risGenerated,risViewed] then // checks if the report selected is in the correct state to be displayed.
  begin
    fileName := TClientReportManager.Singleton.Directory+'\'+GetSelectedReport.Filename; // a string with the filePath + fileName
    ShellExecute(0, 'open', pchar(fileName), '','', SW_MAXIMIZE); // command to open the file
  end;

My first guess with the Opendialog working is that, the open dialog changes the CurrentDir - So I tried already the SetCurrentDir and ChDir to change the current directory to the one where the files are. No success.

Under Win 7, the file path is translated to C:\Users\Ronaldo\Documents\CompanyName\AppName

Interceptor answered 28/3, 2011 at 21:22 Comment(10)
There was an error opening this document. Access denied.Interceptor
can you add the ShelExecute sentence which your use to open the document?Micelle
var pdfFile: string; begin pdfFile := 'C:\Users\Ronaldo\Documents\appName\reports\file.pdf'; ShellExecute(0, 'open', PChar(pdfFile), '', '', SW_SHOW);Interceptor
Sorry - how can I format the code under comments? Is it possible?Interceptor
@Ronaldo, try editing your question and adding the code.Micelle
@Ronaldo I edit your question to add the related code.Micelle
@Ronaldo In comments you can format code by enclosing it in "back quote" symbols: `. For example A := 1; On US keyboards the back quote is usually at the top left combined with the tilde ~ above the tab key.Garrygarson
Have you looked into what the file association does that is different?Wristlet
@David Heferman: What you mean by file association difference? I would expect it would work the same way a double click does... or not??Interceptor
The double click uses the file association to open it. How does it succeed? What does it do different?Wristlet
I
1

I have left this behind but now I got time I went back to try to solve the problem.

I found out that, the client application is using GetEnvironmentVariable('USERPROFILE') to get part of the folder where the reports are. This give me something like 'c:\users\user_name\' on Windows 7 - and then adding a constant with something like "My Documents\CompanyFolder\ProductFolder".

Under win XP this was working fine, but under Win 7, it looks like UAC will not allow you, for some reason, to direct and specifically refer to "My Documents" - instead you need to use the "Documents".

I have changed the constant to remove the "My Documents" part and have added a function to retrieve the private user document folder using the parameter CSIDL_Personal and the function:

function GetSpecialFolderPath(folder : integer) : string;
const
  SHGFP_TYPE_CURRENT = 0;
var
  path: array [0..MAX_PATH] of char;
begin
  if SUCCEEDED(SHGetFolderPath(0,folder,0,SHGFP_TYPE_CURRENT,@path[0])) then
    Result := path
  else
    Result := '';
end;

and calling the function like GetSpecialFolderPath(CSIDL_Personal).

Thanks all for the time you got to post comments and answers.

Just want to add that this answer is the right answer in my case. It could be the case @Ken White answer is the right answer for someone else.

Interceptor answered 4/5, 2011 at 2:59 Comment(1)
Glad you got it sorted out. Those types of problems are really annoying while they last. :)Tjirebon
T
3

I don't think you can totally disable it in code; if you could, it would defeat the whole purpose of the Protected Mode (preventing malware from exploiting the .pdf file association). You may be able to work around it in a legal way, though. :)

I suspect it has to do with the open verb you're using with ShellExecute. You're assuming (maybe incorrectly) that the open verb does the same in Protected Mode on Win7 as it did on prior versions of Adobe Reader and Windows. (NOTE: I don't have that version of Acrobat installed on my system; this is all speculation.)

The first thing I'd try is changing the call to ShellExecute as follows:

ShellExecute(0, nil, PChar(pdfFile), nil, nil, SW_NORMAL);

The first change is to pass nil as the second parameter. This tells Windows you want whatever the default action is to occur. This may, for example, be view instead of open.

I also changed the two parameters after the filename to nil as well. This is more readable than using the empty string ('').

The final change is in the last parameter; I typically use SW_NORMAL instead of SW_SHOW, simply because this tells Windows to show it at whatever the default size and position would be; this may be something saved by the application and will take into effect the user's preferences (if any).

If this doesn't work, it's time to prowl around (carefully!!) in the Windows registry. Open regedit in the Start Menu's Search control, and navigate to HKEY_CLASSES_ROOT. Scroll down the file extensions until you find the entry for .pdf, and double-click that branch. You'll see the Default, which is (on my system, anyway) AcroExch.Document with a Content Type of application/pdf.

Continue down the tree in the left pane until you find AcroExch.Document, and expand it. You'll see a few values there (again, from my machine), as you can see in the image below. Expand the Shell branch, and you'll see the defined verbs, as well as the command associated with them. On my machine (again), I have a single Open verb, whose command is set to "C:\Program Files (x86)\Adobe\Reader 9.0\Reader\AcroRd32.exe" "%1".

RegEdit Left PaneRegEdit Value Pane

(Bear with me - we're almost there. I promise.)

You can see what the double-click is doing differently by examining the default value (click Shell in the left pane, and then see what's set as (Default) in the right. Then examine the command-line (in the second image above, it's Open) to see what switches if any are passed to the Acrobat Reader app. (If you can't figure out which one's the default, right-click a .pdf file in Windows Explorer and see what the bolded item is in the context menu.)

If there's a parameter other than "%1" passed, you'll need to add the same parameter to the command line provided to ShellExecute. For instance, if the parameter is /v, you'd modify your call to ShellExcute to something like this:

ShellExecute(0, nil, PChar(pdfFile), PChar('/v'), nil, SW_NORMAL);
Tjirebon answered 29/3, 2011 at 23:23 Comment(6)
Hey @Ken White, Thanks for take the time for the long explanation. I tried both approaches - no success. I have make a change on the code - when the user selects a report to be generated or select it from a grid of generated report, the system automatically grabs the path of the pdf file and the pdf file name, and executes the command. What I did: the user now needs to chose the file to open from an opendialog - then I get the OpenDialog.FileName and use it as a parameter to the ShellExecute - it works. Why is it?????Interceptor
@Ronaldo: I don't know. Can you edit your original question to show more code? There's something going on here with user rights or something that isn't clear from what you've said so far.Tjirebon
If you get the OpenDialog's FileName and pass it to ShellExecute and that's the only difference then the next thing to do is compare the two full path-and-filenames. Some surprising things can cause errors sometimes - I just fixed a bug where a path like c:\foo\.\bar.txt (note the `\.`) caused an error in Vista's standard Save dialog.Niveous
I don't know if I'm following you - but the bold item for open a PDF is "Open with Adobe Reader X" - that what I put on the fourth parameter. Regarding the path, it is the same - I'm right now out of ideas...Interceptor
@Ronaldo: Now look at the registry as I explained, and see what the Open command line looks like. Does it pass any type of parameters other than "%1" for the filename?Tjirebon
@Ken White - I found the parameter to be /u - but even using that, it does not work.Interceptor
I
1

I have left this behind but now I got time I went back to try to solve the problem.

I found out that, the client application is using GetEnvironmentVariable('USERPROFILE') to get part of the folder where the reports are. This give me something like 'c:\users\user_name\' on Windows 7 - and then adding a constant with something like "My Documents\CompanyFolder\ProductFolder".

Under win XP this was working fine, but under Win 7, it looks like UAC will not allow you, for some reason, to direct and specifically refer to "My Documents" - instead you need to use the "Documents".

I have changed the constant to remove the "My Documents" part and have added a function to retrieve the private user document folder using the parameter CSIDL_Personal and the function:

function GetSpecialFolderPath(folder : integer) : string;
const
  SHGFP_TYPE_CURRENT = 0;
var
  path: array [0..MAX_PATH] of char;
begin
  if SUCCEEDED(SHGetFolderPath(0,folder,0,SHGFP_TYPE_CURRENT,@path[0])) then
    Result := path
  else
    Result := '';
end;

and calling the function like GetSpecialFolderPath(CSIDL_Personal).

Thanks all for the time you got to post comments and answers.

Just want to add that this answer is the right answer in my case. It could be the case @Ken White answer is the right answer for someone else.

Interceptor answered 4/5, 2011 at 2:59 Comment(1)
Glad you got it sorted out. Those types of problems are really annoying while they last. :)Tjirebon

© 2022 - 2024 — McMap. All rights reserved.