为了"支持"远程桌面服务,应用程序必须做什么?

mmm*_*mmm 13 delphi terminal-services

我有一个需要通过远程桌面服务运行的Delphi程序.我应该注意什么会阻止它正常运行?

Dav*_*nan 19

Andreas在针脚双缓冲方面是正确的.这是我所知道的最重要的考虑因素.

作为一个温和的反击点,我一般不喜欢双缓冲,因为它很难做到正确.许多组件都没有成功.我在考虑VCL下拉列表框,它们不能在Windows Basic下绘制.还有其他人!

但有些控件确实需要双缓冲以避免闪烁,那么你做什么?当用户在本地连接时,您希望获得双缓冲的好处,但是当您远程时,您不希望使用网络带宽对它们征税.

所以,这就是我的工作:

procedure WMWTSSessionChange(var Message: TMessage); message WM_WTSSESSION_CHANGE;

procedure TBaseForm.WMWTSSessionChange(var Message: TMessage);
begin
  case Message.WParam of
  WTS_CONSOLE_DISCONNECT,WTS_REMOTE_DISCONNECT,
  WTS_SESSION_LOCK,WTS_SESSION_LOGOFF:
    SessionDisconnected;
  WTS_CONSOLE_CONNECT,WTS_REMOTE_CONNECT,
  WTS_SESSION_UNLOCK,WTS_SESSION_LOGON:
    SessionConnected;
  end;
  inherited;
end;

function WTSRegisterSessionNotification(hWnd: HWND; dwFlags: DWORD): BOOL; stdcall; external 'Wtsapi32.dll';
function WTSUnRegisterSessionNotification(hWnd: HWND): BOOL; stdcall; external 'Wtsapi32.dll';

const
  NOTIFY_FOR_THIS_SESSION = 0;
  NOTIFY_FOR_ALL_SESSIONS = 1;

procedure TBaseForm.CreateWnd;
begin
  inherited;
  WTSRegisterSessionNotification(WindowHandle, NOTIFY_FOR_THIS_SESSION);
end;

procedure TBaseForm.DestroyWnd;
begin
  WTSUnRegisterSessionNotification(WindowHandle);
  inherited;
end;
Run Code Online (Sandbox Code Playgroud)

我的应用程序中的所有表单都来自于TBaseForm,因此继承了此行为.这些SessionConnectedSessionDisconnected方法是virtual如此,个别形式可以采取特定的行动.

特别是,我的所有表格都称之为UpdateDoubleBuffered:

function InRemoteSession: Boolean;
begin
  Result := Windows.GetSystemMetrics(SM_REMOTESESSION)<>0;
end;

class procedure TBaseForm.UpdateDoubleBuffered(Control: TWinControl);
var
  DoubleBuffered: Boolean;
begin
  if InRemoteSession then begin
    //see The Old New Thing, Taxes: Remote Desktop Connection and painting
    DoubleBuffered := False;
  end else begin
    DoubleBuffered := (Control is TCustomListView) 
                   or (Control is TCustomStatusBar);
    //TCustomListView flickers when updating without double buffering
    //TCustomStatusBar has drawing infidelities without double buffering in my app
  end;
  Control.DoubleBuffered := DoubleBuffered;
end;

procedure TBaseForm.UpdateDoubleBuffered;
var
  Control: TControl;
begin
  for Control in ControlEnumerator(TWinControl) do begin
    UpdateDoubleBuffered(TWinControl(Control));
  end;
end;
Run Code Online (Sandbox Code Playgroud)

ControlEnumerator 是一个遍历组件子级的枚举器.

Old New Thing参考文章是一篇名为Taxes:Remote Desktop Connection and painting的文章,这是我对这段代码的大部分启发.

我确信还有其他与远程桌面相关的问题,但双缓冲肯定是更重要的问题之一.


And*_*and 10

双缓冲是这样的事情.

通常双缓冲是一件好事,我一直都在使用它.例如,参见我的组件(1),(2)(3).它们都是双缓冲的,因此完全没有闪烁(并且易于实现),但是如果你远程运行它,你必须发送位图而不是GDI命令,所以它可能相当慢(并且不经济).


Rem*_*mko 7

除了上面的答案,请参阅我对这个问题的回答:有没有人知道Citrix和Delphi 2007应用程序之间的问题?(也许还有其他开发语言?)

编辑:在我的博客上,我有一个关于应用程序兼容性问题的知识,它们是在RDS/Citrix上表现不佳的应用程序的真实故事.可能有用的检查:http://www.remkoweijnen.nl/blog/topics/application-compatibility/

其他可能感兴趣的类别是http://www.remkoweijnen.nl/blog/topics/citrix/http://www.remkoweijnen.nl/blog/topics/terminalserver/,但并非所有类别都可能适用于您的问题.

第二次编辑:您可以使用Microsoft的标准用户分析器工具来检查您的应用程序是否适合普通用户运行(MS专注于UAC,但在典型的RDS或Citrix服务器上,只有低权限用户).http://technet.microsoft.com/en-us/library/cc765948(WS.10).aspx