Adobe X Включить защищенный режим при запуске — отключить с помощью кода

Наше приложение, написанное на Delphi, генерирует серию отчетов, большинство из которых в формате PDF, которые автоматически открываются при создании. Adobe X представила функцию, которая включена по умолчанию, «Включить защищенный режим при запуске». PDF-файлы отчета открываются с помощью «ShelExecute».

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

Из-за этой новой новой настройки Adobe Reader в Win 7 или Vista мы получаем сообщение об ошибке при открытии документа. Двойной щелчок по документу, чтобы открыть его, не вызывает никаких проблем. Есть ли способ отключить защищенный метод или другой способ открыть документ без получения ошибки (обходной путь)?

*Дополнительная информация *

Файл PDF создается в нашем серверном приложении, передается клиенту, а клиент генерирует pdf (используя Write). Сначала я подумал, что это может быть проблемой, но опять же, почему двойной щелчок работает нормально.

Я создал фиктивное приложение, которое ничего не делает, но использует тот же код выше, чтобы открыть pdf, и оно работает. Я проверил привилегии приложения - все то же самое - разница только в том, что тот, который не работает, устанавливается в ОС с помощью правильного установщика - другой (пустой) я просто создал и закинул его туда.

Один из комментариев спрашивает об ассоциации файлов - это не должно быть проблемой, поскольку приложению удается запустить Adobe Reader - затем Adobe Reader выдает мне сообщение об ошибке «отказано в доступе». Двойной щелчок по тому же файлу работает нормально.

Новая информация — 30 марта 2011 г., 14:50 (по новозеландскому времени)

Я внес изменения в код только для того, чтобы проверить единственное различие между самим приложением и фиктивным приложением. Вместо того, чтобы автоматически получать путь к файлу и имя файла, теперь он открывает OpenDialog — свойство Filename в opendialog используется в качестве параметра для ShellExecute (как указано в комментарии после ответа Кена) — это работает. Почему, когда вы получаете имя файла из открытого диалогового окна, оно работает — обратите внимание, что я не открываю файл из диалогового окна — я получаю имя файла и использую его в качестве параметра для ShellExecute.

Обновленный пример кода

Когда пользователь нажимает кнопку «Создать отчет», отчет открывается автоматически после его создания. Кроме того, есть сетка, показывающая все сгенерированные отчеты для этого пользователя — это код двойного щелчка для этой сетки:

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;

Мое первое предположение о работе Opendialog заключается в том, что открытый диалог изменяет CurrentDir. Поэтому я уже пробовал SetCurrentDir и ChDir, чтобы изменить текущий каталог на тот, где находятся файлы. Нет успеха.

В Win 7 путь к файлу преобразуется в C:\Users\Ronaldo\Documents\CompanyName\AppName.


person ronaldosantana    schedule 28.03.2011    source источник
comment
При открытии этого документа произошла ошибка. Доступ закрыт.   -  person ronaldosantana    schedule 29.03.2011
comment
можете ли вы добавить предложение ShelExecute, которое вы используете, чтобы открыть документ?   -  person RRUZ    schedule 29.03.2011
comment
var pdfFile: строка; begin pdfFile := 'C:\Users\Ronaldo\Documents\appName\reports\file.pdf'; ShellExecute(0, 'открыть', PChar(pdfFile), '', '', SW_SHOW);   -  person ronaldosantana    schedule 29.03.2011
comment
Извините, как я могу отформатировать код под комментариями? Является ли это возможным?   -  person ronaldosantana    schedule 29.03.2011
comment
@Ronaldo, попробуйте отредактировать свой вопрос и добавить код.   -  person RRUZ    schedule 29.03.2011
comment
@Ronaldo Я редактирую ваш вопрос, чтобы добавить соответствующий код.   -  person RRUZ    schedule 29.03.2011
comment
@RRUZ - спасибо за это.   -  person ronaldosantana    schedule 29.03.2011
comment
@Ronaldo В комментариях вы можете отформатировать код, заключив его в обратные кавычки: `. Например, A := 1; На клавиатурах США обратная кавычка обычно находится вверху слева в сочетании с тильдой ~ над клавишей табуляции.   -  person Marjan Venema    schedule 29.03.2011
comment
Вы изучали, чем отличается ассоциация файлов?   -  person David Heffernan    schedule 29.03.2011
comment
@David Heferman: Что вы подразумеваете под разницей в ассоциации файлов? Я ожидаю, что это будет работать так же, как двойной щелчок... или нет??   -  person ronaldosantana    schedule 29.03.2011
comment
Двойной щелчок использует ассоциацию файлов, чтобы открыть его. Как это удается? Что он делает по-другому?   -  person David Heffernan    schedule 29.03.2011


Ответы (2)


Я не думаю, что вы можете полностью отключить его в коде; если бы вы могли, это разрушило бы всю цель защищенного режима (предотвращение использования вредоносными программами ассоциации файлов .pdf). Хотя, возможно, вы сможете обойти это законным путем. :)

Я подозреваю, что это связано с глаголом open, который вы используете с ShellExecute. Вы предполагаете (возможно, неправильно), что глагол open делает то же самое в защищенном режиме на Win7, как и в предыдущих версиях Adobe Reader и Windows. (ПРИМЕЧАНИЕ: эта версия Acrobat не установлена ​​в моей системе; это все предположения.)

Первое, что я бы попробовал, это изменить вызов на ShellExecute следующим образом:

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

Первое изменение заключается в передаче nil в качестве второго параметра. Это сообщает Windows, что вы хотите, чтобы произошло действие по умолчанию. Например, это может быть view вместо open.

Я также изменил два параметра после имени файла на ноль. Это более читабельно, чем использование пустой строки ('').

Окончательное изменение в последнем параметре; Я обычно использую SW_NORMAL вместо SW_SHOW просто потому, что это говорит Windows показывать его в любом размере и положении по умолчанию; это может быть что-то, сохраненное приложением, и оно будет действовать в соответствии с предпочтениями пользователя (если таковые имеются).

Если это не сработает, пора порыться (осторожно!!) в реестре Windows. Откройте regedit в элементе управления «Поиск» в меню «Пуск» и перейдите к HKEY_CLASSES_ROOT. Прокрутите расширения файлов вниз, пока не найдете запись для .pdf, и дважды щелкните эту ветвь. Вы увидите Default, то есть (по крайней мере, в моей системе) AcroExch.Document с Content Type из application/pdf.

Продолжайте движение вниз по дереву на левой панели, пока не найдете AcroExch.Document, и разверните его. Там вы увидите несколько значений (опять же, с моей машины), как вы можете видеть на изображении ниже. Разверните ветку Shell, и вы увидите определенные глаголы, а также связанные с ними команды. На моей машине (опять же) у меня есть один глагол Open, команда которого установлена ​​на "C:\Program Files (x86)\Adobe\Reader 9.0\Reader\AcroRd32.exe" "%1".

RegEdit Left PaneПанель значений RegEdit

(Потерпите меня — мы почти у цели. Обещаю.)

Вы можете увидеть, что двойной щелчок делает по-другому, изучив значение по умолчанию (нажмите Shell на левой панели, а затем посмотрите, что установлено как (Default) на правом. Затем изучите командную строку (на втором изображении выше это Open). ), чтобы увидеть, какие переключатели передаются приложению Acrobat Reader, если они есть (если вы не можете понять, какой из них используется по умолчанию, щелкните правой кнопкой мыши файл .pdf в проводнике Windows и посмотрите, какой элемент выделен жирным шрифтом в контекстном меню. )

Если передан параметр, отличный от "%1", вам необходимо добавить тот же параметр в командную строку, предоставленную для ShellExecute. Например, если параметр равен /v, вы должны изменить вызов ShellExcute примерно так:

ShellExecute(0, nil, PChar(pdfFile), PChar('/v'), nil, SW_NORMAL);
person Ken White    schedule 29.03.2011
comment
Эй, @Ken White, спасибо, что нашли время для длинного объяснения. Пробовал оба подхода - безуспешно. Я внес изменение в код - когда пользователь выбирает отчет для создания или выбирает его из сетки сгенерированного отчета, система автоматически захватывает путь к файлу PDF и имя файла PDF и выполняет команду. Что я сделал: теперь пользователю нужно выбрать файл для открытия из opendialog - затем я получаю OpenDialog.FileName и использую его в качестве параметра для ShellExecute - это работает. Почему это????? - person ronaldosantana; 30.03.2011
comment
@ Роналду: я не знаю. Можете ли вы отредактировать исходный вопрос, чтобы показать больше кода? Здесь что-то происходит с правами пользователя или что-то непонятное из того, что вы сказали до сих пор. - person Ken White; 30.03.2011
comment
Если вы получите имя файла OpenDialog и передадите его в ShellExecute и это единственная разница, то следующее, что нужно сделать, это сравнить два полных пути и имена файлов. Некоторые неожиданные вещи могут иногда вызывать ошибки - я только что исправил ошибку, из-за которой путь типа c:\foo\.\bar.txt (обратите внимание на `\.`) вызывал ошибку в стандартном диалоговом окне сохранения Vista. - person David; 30.03.2011
comment
Я не знаю, слежу ли я за вами, но выделенный жирным шрифтом пункт для открытия PDF — «Открыть с помощью Adobe Reader X» — это то, что я поставил в четвертом параметре. Насчет пути то же самое - у меня сейчас нет идей... - person ronaldosantana; 30.03.2011
comment
@Ronaldo: Теперь посмотрите на реестр, как я объяснил, и посмотрите, как выглядит командная строка Open. Передает ли он какой-либо тип параметров, кроме %1 для имени файла? - person Ken White; 30.03.2011
comment
@Ken White - я обнаружил, что параметр /u - но даже при его использовании он не работает. - person ronaldosantana; 31.03.2011

Я оставил это позади, но теперь у меня есть время, и я вернулся, чтобы попытаться решить проблему.

Я узнал, что клиентское приложение использует GetEnvironmentVariable('USERPROFILE') для получения части папки, в которой находятся отчеты. Это дает мне что-то вроде «c:\users\user_name\» в Windows 7, а затем добавляет константу с чем-то вроде «Мои документы\CompanyFolder\ProductFolder».

Под Win XP это работало нормально, но под Win 7 похоже, что UAC по какой-то причине не позволит вам направлять и конкретно ссылаться на «Мои документы» - вместо этого вам нужно использовать «Документы».

Я изменил константу, чтобы удалить часть «Мои документы», и добавил функцию для извлечения личной папки документов пользователя с использованием параметра CSIDL_Personal и функции:

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;

и вызов такой функции, как GetSpecialFolderPath(CSIDL_Personal).

Спасибо всем за то, что уделили время комментариям и ответам.

Просто хочу добавить, что этот ответ является правильным ответом в моем случае. Возможно, ответ @Ken White является правильным ответом для кого-то другого.

person ronaldosantana    schedule 04.05.2011
comment
Рад, что ты разобрался. Эти типы проблем действительно раздражают, пока они длятся. :) - person Ken White; 06.05.2011