我们的应用程序,用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阅读器 - Adobe阅读器然后给我“访问被拒绝”错误消息。双击同一个文件可以正常工作。
新信息 - 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
答案 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"
。
(跟我一起 - 我们差不多了。我保证。)
通过检查默认值,您可以看到双击的不同之处(单击左侧窗格中的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回答是其他人的正确答案。