我有一个启动第二个 exe 的 Delphi 2010 exe。在第二个 exe 中,有一个调用 openDialog.execute 的对话框。当它在远程桌面下的Windows 2008 Enterprise R2下运行时,它按预期运行,但是当作为远程应用程序运行时,一旦弹出文件对话框,应用程序就会挂起,将所有应用程序窗口变为白色。摆脱它的唯一方法是终止应用程序。我尝试用 TFileOpenDialog 替换 TOpenDialog,结果是一样的。我已经研究过修改启动主应用程序的 RDP 文件,但在那里看不到任何会产生影响的参数。有没有人见过这种行为?
2010.07.13 更新
这可以通过一个简单的例子重现。示例中有两个可执行文件。第一个是一个名为 m_module.exe 的文件启动器,它包含一个编辑、一个按钮和下面的代码。在单击启动按钮之前,我在编辑中更改了可执行文件的名称以匹配第二个可执行文件:
procedure TForm1.Button1Click(Sender: TObject);
begin
ShellExecute(Handle, 'open', stringToOLEstr(edit1.text) , nil, nil, SW_SHOWNORMAL) ;
end;
procedure TForm1.FormShow(Sender: TObject);
begin
edit1.text:=application.exename;
end;
第二个可执行文件包含一个按钮和以下代码:
procedure TForm1.Button1Click(Sender: TObject);
begin
OpenDialog1.execute;
end;
第一个模块从 RDP 文件启动。
2010.07.14 更新
我发现如果我复制以下 dll:
thumbcache.dll
dtsh.dll
wkscli.dll
从 \Windows\System32 文件夹到应用程序文件夹,问题就解决了。
我进一步发现将 \Windows\System32 文件夹中这些 dll 的所有权和权限级别从 TrustedInstaller 更改为管理员组具有相同的结果(我认为将它们复制到应用程序目录正在更改所有权和权限)
为了确认这一点,我验证了如果我将所有权和权限级别从管理员组更改回 TrustedInstaller,错误会再次出现。
因此,这似乎是某种访问问题。也许这将有助于发现问题的原因。
2010.07.18 更新
一些可能有用的附加信息(由 Embarcadero 提供):
GetWindowsDirectory 的这篇 MSDN 文章http://msdn.microsoft.com/en-us/library/ms724454%28VS.85%29.aspx记录了在终端服务下运行的应用程序的一些有趣行为。虽然没有直接调用 GetWindowsDirectory,但每个用户的 Windows 系统目录的沙盒化可能会导致某种问题。可能 GetOpenFileNameA 调用链中的 DLL 之一试图引用真实系统目录中的真实 DLL,而不是沙盒中的 DLL,从而导致权限冲突。这只是猜测,但值得研究。如果您能够让 SysInternals Process Monitor 或 Process Explorer 在服务器上工作,您应该能够看到 commdlg32 和堆栈跟踪中的其他 DLL 正在加载。
所有遗留应用程序(即不是为终端服务或远程桌面服务创建的所有应用程序)都在应用程序兼容层下运行。请参阅此 MSDN 文章http://msdn.microsoft.com/en-us/library/cc834995%28VS.85%29.aspx。IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE 标志在 Windows.PAS 中定义。出于测试目的,您可以通过将 Windows 添加到应用程序的使用部分并在使用部分的正下方将其添加到应用程序的 PE 标头中:
{$SetPEOptFlags IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE}
这将导致您的应用程序绕过兼容层。我目前正在调查生成的进程(例如您的第二个 exe)是否保留在 RDS 下定义的应用程序的所有权利和设置。