当作为远程桌面应用程序运行时,Delphi TOpenDialog在Windows 2008中挂起 [英] Delphi TOpenDialog hangs in windows 2008 when run as remote desktop application

查看:124
本文介绍了当作为远程桌面应用程序运行时,Delphi TOpenDialog在Windows 2008中挂起的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Delphi 2010 exe,可以启动第二个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更改为管理员组具有相同的结果(将它们复制到应用程序目录正在更改所有权和权限)./p>

为确认这一点,如果将所有权和权限级别从管理员组更改回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下定义的应用程序的所有权限和设置.

解决方案

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

对于我们来说,这可以解决任何活动目录问题,并确保安全性.而且,它可以防止用户尝试将文件拖放到我们的文件系统中或查看他们不应该看到的内容.

如果它们不在沙盒中运行,我们将显示常规的Windows文件对话框.包装函数使我们可以从任何地方调用它,并将沙盒与窗口"决定留在一个地方.

I have a Delphi 2010 exe that launches a second exe. In the second exe, there is a dialog that calls openDialog.execute. When this runs under Windows 2008 Enterprise R2 under a remote desktop, it runs as expected, but when run as a remote application, as soon as the file dialog pops up, the application hangs, turning all of the application windows white. The only way to get out of it is to terminate the application. I tried replacing TOpenDialog with TFileOpenDialog, the results are the same. I've looked into modifying the RDP file that launches the main application, but cannot see any parameters there that would make a difference. Has anyone ever seen this kind of behavior before?


2010.07.13 Updated

This is reproducable using a simple example. There are two executable files in the example. The first is a file launcher, called m_module.exe, which contains one edit, one button, and the code below. I change the name of the executable file in the edit to match the second executable before I click the launch 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;

The second executable contains a button and the code below:

procedure TForm1.Button1Click(Sender: TObject);
begin
     OpenDialog1.execute;
end;

The first module is launched from an RDP file.

2010.07.14 Updated

I have discovered that if I copy the following dlls:

thumbcache.dll 
dtsh.dll 
wkscli.dll 

from the \Windows\System32 folder into the application folder, the problem is eliminated.

I've further discovered that changing ownership and permission levels of these dlls in the \Windows\System32 folder from TrustedInstaller to the Administrator's group has the same result (Copying them to the application directory is changing ownership and permission I think)

To confirm this, I verified that the errors reappeared if I changed the ownership and permission levels back to TrustedInstaller away from the Administrator's group.

So it appears that this is an access issue of some kind. Perhaps this will help in discovering the cause of the issue.

2010.07.18 Updated

Some additional information that might be helpful (provided by Embarcadero):

This MSDN article for GetWindowsDirectory http://msdn.microsoft.com/en-us/library/ms724454%28VS.85%29.aspx documents some interesting behavior of applications running under Terminal Services. While GetWindowsDirectory is not being called directly the sandboxing of the Windows System directory per user could be causing some sort of problem. Perhaps one of the DLLs in the calling chain to GetOpenFileNameA is trying to reference the real DLL in the real System directory instead of the sandboxed one thus causing a rights violation. It is just speculation but it is worth investigating. If you were able to get the SysInternals Process Monitor or Process Explorer working on the server you should be able to see commdlg32 and the other DLLs in the stack trace being loaded.

All legacy applications (i.e. all applications not created for Terminal Services or Remote Desktop Services) run under an Application Compatibility Layer. See this MSDN article http://msdn.microsoft.com/en-us/library/cc834995%28VS.85%29.aspx . The IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE flag is defined in Windows.PAS. For testing purposes you can add it to your application's PE header by adding Windows to your application's USES section and right under the USES section put:

{$SetPEOptFlags IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE}

This will cause your application to bypass the compatibility layer. I am currently investigating if spawned processes (e.g. your second exe) retain all of the rights and settings of the application defined under RDS.

解决方案

FWIW, we have a similar situation, but it's driven by a security need, and not a crash. When our app runs via Citrix, we are forbidden to ever show the regular windows "open" or "save as" dialogs. So we rolled our own. It's got a combo of drive letters (local drives only), folder selector (restricted to the approved drives), filename selector, and filename edit box.

For us, this gets around any active directory issues, and keeps security happy. And it keeps the users from trying to drop files into our filesystem or see things they shouldn't.

If they're not running in the sandbox, we show the regular windows file dialogs. A wrapper function allows us to call it from anywhere and leave the "sandboxed vs windows" decision in one spot.

这篇关于当作为远程桌面应用程序运行时,Delphi TOpenDialog在Windows 2008中挂起的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆