Adobe X在启动时启用保护模式 - 通过代码禁用

时间:2011-03-28 21:22:58

标签: delphi windows-7 windows-vista adobe-reader

我们的应用程序,用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阅读器 - Adob​​e阅读器然后给我“访问被拒绝”错误消息。双击同一个文件可以正常工作。

新信息 - 30/03/2011 - 下午2:50 - 新西兰时间

我对代码进行了更改,只是为了测试应用程序本身和虚拟应用程序之间的唯一区别。 它不是自动获取文件路径和文件名,而是打开一个OpenDialog - opendialog的Filename属性用作ShellExecute的参数(作为Ken应答状态后的注释) - 它可以工作。为什么,当你从一个打开的对话框中获取文件名时,它可以工作 - 注意我没有从对话框中打开文件 - 我得到了文件名,并将其用作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

2 个答案:

答案 0 :(得分:3)

我认为你不能在代码中完全禁用它;如果可以,它将破坏保护模式的整个目的(防止恶意软件利用.pdf文件关联)。不过,您可能能够以合法的方式解决这个问题。 :)

我怀疑它与您使用open时使用的ShellExecute动词有关。您假设(可能不正确){8}保护模式中的open动词与之前版本的Adobe Reader和Windows上的保护模式相同。 (注意:我的系统上没有安装该版本的Acrobat;这是所有推测。)

我要尝试的第一件事是将呼叫更改为ShellExecute,如下所示:

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

第一个更改是将nil作为第二个参数传递。这告诉Windows您希望发生什么默认操作。例如,这可能是view而不是open

我也将文件名后的两个参数更改为nil。这比使用空字符串('')更具可读性。

最后一项更改是在最后一个参数中;我通常使用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 Value Pane

(跟我一起 - 我们差不多了。我保证。)

通过检查默认值,您可以看到双击的不同之处(单击左侧窗格中的Shell,然后在右侧查看设置为(Default)的内容。然后检查命令-line(在上面的第二张图片中,它是Open),看看有什么开关传递到Acrobat Reader应用程序。(如果你不知道哪一个是默认的,右键单击.pdf文件在Windows资源管理器中,查看上下文菜单中的粗体项目。)

如果传递了"%1"以外的参数,则需要将相同的参数添加到提供给ShellExecute的命令行中。例如,如果参数为/v,则您将对ShellExcute的调用修改为以下内容:

ShellExecute(0, nil, PChar(pdfFile), PChar('/v'), nil, SW_NORMAL);

答案 1 :(得分:1)

我把它留下了,但现在我有时间回去尝试解决问题。

我发现,客户端应用程序正在使用GetEnvironmentVariable(&#39; USERPROFILE&#39;)来获取报告所在文件夹的一部分。这给了我类似&c; \ users \ user_name \&#39;在Windows 7上 - 然后添加一个类似&#34; My Documents \ CompanyFolder \ ProductFolder&#34;的常量。

在win XP下,这工作正常,但在Win 7下,看起来UAC不会允许您出于某种原因直接并特别引用&#34;我的文档&#34; - 相反,您需要使用&#34; Documents&#34;。

我已更改常量以删除&#34;我的文档&#34;部分并添加了一个函数,使用参数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回答是其他人的正确答案。