Delphi TOpenDialog作为远程桌面应用程序运行时挂在Windows 2008中

我有一个delphi2010年exe文件启动第二个exe文件。 在第二个exe中,有一个调用openDialog.execute的对话框。 当它在远程桌面下的Windows 2008 Enterprise R2下运行 ,它按预期方式运行, 但作为远程应用程序运行时 ,只要文件对话框popup,应用程序就会挂起,将所有应用程序窗口变成白色。 摆脱它的唯一方法是终止应用程序。 我尝试用TFileOpenDialogreplaceTOpenDialog,结果是一样的。 我已经研究了修改启动主应用程序的RDP文件,但是看不到任何参数会有所作为。 有没有人见过这种行为?


2010.07.13更新

这是一个简单的例子可重复使用。 在这个例子中有两个可执行文件。 第一个是文件启动器,名为m_module.exe,它包含一个编辑,一个button和下面的代码。 在单击启动button之前,我将编辑中的可执行文件的名称更改为匹配第二个可执行文件:

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; 

第二个可执行文件包含一个button和下面的代码:

 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更改为pipe理员组具有相同的结果(将它们复制到应用程序目录正在改变所有权和权限,我认为)

为了证实这一点,我validation了如果我将所有权和权限级别从pipe理员组更改回TrustedInstaller,错误再次出现。

所以这似乎是某种访问问题。 也许这将有助于发现问题的原因。

2010.07.18更新

一些可能有用的附加信息(由Embarcadero提供):

此MSDN文章的GetWindowsDirectory http://msdn.microsoft.com/en-us/library/ms724454%28VS.85%29.aspx文件在terminal服务下运行的应用程序的一些有趣的行为。 虽然不直接调用GetWindowsDirectory,但每个用户的Windows系统目录的沙箱可能会导致某种问题。 也许在GetOpenFileNameA的调用链中的一个DLL试图引用实际的系统目录中的实际DLL而不是沙盒,从而导致权限冲突。 这只是猜测,但值得深入研究。 如果您能够在服务器上运行SysInternals Process Monitor或Process Explorer,则应该能够看到加载的堆栈跟踪中的commdlg32和其他DLL。

所有传统应用程序(即,不是为terminal服务或远程桌面服务创build的所有应用程序)都在应用程序兼容层下运行。 看到这个MSDN文章http://msdn.microsoft.com/en-us/library/cc834995%28VS.85%29.aspx 。 Windows.PAS中定义了IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE标志。 出于testing目的,您可以通过将Windows添加到您的应用程序的USES部分,并将其添加到您的应用程序的PE标头,并将其添加到用户部分:

{$ SetPEOptFlags IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE}

这将导致您的应用程序绕过兼容层。 我目前正在调查产生的进程(例如你的第二个exe)是否保留了在RDS下定义的应用程序的所有权利和设置。

Windows报告thumbcache.dll模块中的AV(c0000005)。

我认为thumbcache.dll有关建立/缓存文件的缩略图。 构建缩略图可能意味着使用资源管理器的第三方扩展,这可能无法与RDP很好地配合。

尝试在干净的系统上。 使用VMWare或类似的虚拟机来设置测试配置。

PS另请参阅此文章: 如何调试应用程序的挂起? 但是我认为这只是你的情况的另一个问题的结果。

FWIW,我们也有类似的情况,但这是由安全需求驱动的,而不是崩溃。 当我们的应用程序通过Citrix运行时,我们被禁止显示常规窗口“打开”或“另存为”对话框。 所以我们推出了自己的。 它有一个驱动器号(仅限本地驱动器),文件夹选择器(限于批准的驱动器),文件名选择器和文件名编辑框的组合。

对于我们来说,这可以解决任何活动目录问题,并保持安全。 它使用户不会尝试将文件放入我们的文件系统,或者看到他们不应该看到的东西。

如果他们没有在沙箱中运行,我们将显示常规的Windows文件对话框。 封装函数允许我们从任何地方调用它,并将“沙盒与窗口”决定放在一个地方。

我建议您使用Process Explorer工具来查看您的流程的属性。 检查在这两种情况下加载了哪些DLL(可以通过选择进程并在模块视图中打开较低窗格来完成)。

您还可以使用进程监视器工具来监视进程启动(再次:在这两种情况下),并查看任何有关DLL的引用。

您似乎已经将问题缩小到某种访问问题,所以下面的解释可能无法帮助您。 但是在RemoteApp上弹出窗口似乎存在问题,我可以想象它可能会导致(至少在理论上)类似的问题,这就是为什么我想提到它: http : //social.technet.microsoft.com /论坛/ EN-US / winserverTS /线程/ 0a88919f-2d72-4340-abd7-fbe0e9545f25 /

显然,使用RemoteApp时,窗口的Z顺序并不总是正确的。 在你的情况下,TOpenDialog应该是一个模式弹出窗口。 由于这个错误,我可以想象,TOpenDialog可能出现在后台。 您的主窗口将保持在前台,但将被禁用,因为TOpenDialog是模态的。 Windows可能不知道如何重新绘制一个禁用的窗口,只需画一个白色框。

我们在OpenDialog.Execute上遇到了问题,但是只在一台电脑上出现了问题 – 这似乎是随机的,我发现在Windows DEP中添加exe文件可能会解决这个问题,因为改变它之后我们没有任何问题

这里是链接如何更改窗口DEP设置http://www.itechtalk.com/thread3591.html

这是一个解决方法 – 如果有人知道如何保持DEP高兴,请在下面添加注释

它的Z顺序是不正确的(我经常在Citrix中看到,如果没有正确的修复),你仍然可以用ctrl-F4或者alt-f4来关闭窗体。 此外,应用程序不会是“没有回应”。 有时候,在任务之间切换时,订单会自行更正