Что приложение должно сделать для того, чтобы «поддерживать» службы удаленных рабочих столов? - PullRequest
13 голосов
/ 31 января 2011

У меня есть программа Delphi, которую необходимо запустить через службы удаленных рабочих столов. На что мне обратить внимание, чтобы он не работал нормально?

Ответы [ 7 ]

19 голосов
/ 31 января 2011

Андреас прав в буферизации двойной буферизации. Это самый важный аспект, о котором я должен знать.

Как мягкий контрапункт, мне не нравится двойная буферизация вообще, потому что очень трудно сделать это правильно. Многие компоненты не имеют успеха. Я думаю о выпадающих списках 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;

Все формы в моем приложении происходят от TBaseForm и поэтому наследуют это поведение. Методы SessionConnected и SessionDisconnected являются 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;

ControlEnumerator - это перечислитель, который обходит дочерние элементы компонента.

Ссылка "Старая новая вещь" относится к статье под названием Налоги: подключение к удаленному рабочему столу и рисование , которая послужила моим вдохновением для большей части этого кода.

Я уверен, что существуют другие проблемы, связанные с удаленным рабочим столом, но двойная буферизация, безусловно, является одной из наиболее важных.

10 голосов
/ 31 января 2011

Двойная буферизация - одна из таких вещей.

Вообще, двойная буферизация - отличная вещь, и я использую ее постоянно. Смотри, например, мои компоненты (1) , (2) и (3) . Все они имеют двойную буферизацию и поэтому полностью свободны от мерцания (и просты в реализации), но если вы запускаете это удаленно, вам нужно отправлять битовые карты, а не команды GDI, поэтому это может быть довольно медленно (и неэкономично).

7 голосов
/ 01 февраля 2011

В дополнение к ответам выше см. Также мой ответ на этот вопрос: Кто-нибудь знает о проблемах между приложениями Citrix и Delphi 2007? (А может и другие языки разработки?)

РЕДАКТИРОВАТЬ: В моем блоге у меня есть caterogy для проблем совместимости приложений, это реальные истории приложений, которые плохо работают на RDS / Citrix. Может быть полезно проверить это: http://www.remkoweijnen.nl/blog/topics/application-compatibility/

Другие категории, которые могут представлять интерес: http://www.remkoweijnen.nl/blog/topics/citrix/ и http://www.remkoweijnen.nl/blog/topics/terminalserver/, хотя не все могут применяться к вашему вопросу.

2-е РЕДАКТИРОВАНИЕ: Вы можете использовать инструмент Standard User Analyzer от Microsoft, чтобы проверить, подходит ли ваше приложение для запуска обычным пользователем (MS фокусируется на UAC, но на типичном сервере RDS или Citrix там). только пользователи с низкими привилегиями). http://technet.microsoft.com/en-us/library/cc765948(WS.10).aspx

4 голосов
/ 01 февраля 2011

Если это корпоративное или веб-приложение, которое запускают сотни или тысячи пользователей, обратите особое внимание на глубину цвета, градиенты и легкомысленную анимацию. Особенно последний. Вращающийся значок синхронизации 16x16 не потребляет слишком много трафика, но большие объекты могут генерировать большой трафик. Градиенты выглядят дрянно, когда уровень цвета снижается, и они плохо сжимаются. Цветовые уровни снижаются, когда сетевым / системным администраторам нужно выжать больше из сети. Возможно, вы не сможете это контролировать. Эти проблемы также относятся к приложениям Citrix, которые обычно работают без полноценного рабочего стола. Еще одно соображение заключается в том, что пользователи не будут видеть область уведомлений в системном трее.

4 голосов
/ 31 января 2011

Формы альфа-прозрачности плохо поддерживаются IME (ни клиентами, ни серверами, в зависимости от их версий).

Вам также нужно беспокоиться о цветах, большинство удаленных рабочих столов работают в 16-битных цветах или даже просто в 256 цветах. Если у вас чистый современный пользовательский интерфейс, вам, возможно, придется перевести его в «уродливый» режим, чтобы все было гарантированно будет читабельным.
В том же духе, остерегайтесь сглаженного текста, который является обязательным для любого современного пользовательского интерфейса, но может привести к нечитаемым размытым символам на низкоцветном RDP.

Могут быть и другие проблемы с пузырьками уведомлений и другими эффектами на основе оболочки, поэтому вам, вероятно, захочется обрабатывать их самостоятельно, в обычных формах, а не полагаться на функциональность Windows API.

Говоря графически, двойная буферизация может быть обоюдоострым мечом, в некоторых случаях (сдержанная графика) может быть полезно отключить его, но если у вас более продвинутые рендеры (градиенты, прозрачные растровые изображения, масштабированные растровые изображения) Причудливые шрифты, сглаженные линии и т. д.) с двойной буферизацией можно улучшить внешний вид и скорость, поскольку небольшая задержка может быть лучше, чем при интерактивном рисовании с мерцанием.
Также некоторые растровые изображения могут проходить быстрее, чем другие, обычные быстрые сжатия, используемые в RDP, предпочитают вертикальные градиенты по сравнению с горизонтальными градиентами f.i.

Другая проблема будет с правами на файлы, если ваше приложение никогда не запускалось под учетной записью обычного пользователя. Кроме того, специальные папки (например, temp) и ключи реестра могут иметь разные (динамические) расположения и ограничения. Но если ваше приложение уже запущено под ограниченной учетной записью пользователя, у вас уже должно быть все покрыто.

3 голосов
/ 01 февраля 2011

С Citrix у нас были проблемы с принтерами. Иногда для подключения используются принтеры, которые клиент определил на своем компьютере, иногда принтеры из сеансов других пользователей, а в других случаях принтер по умолчанию находится в совершенно другом месте, недоступном для нашего пользователя.

0 голосов
/ 01 февраля 2011

У меня было много проблем с вещами, которые мерцали так сильно, что их нельзя было использовать через удаленный рабочий стол. Это было потому, что я обновлял такие вещи, как подписи или панели статуса, много раз в секунду. Я изменил весь свой код обновления пользовательского интерфейса, чтобы проверить, действительно ли изменилась подпись:

  if Str<>WeirdControl.Property1 then
      WeirdControl.Property1 := Str; // minimize number of invalidates in case the control doesn't have it.

Наряду с другими вещами, упомянутыми в других ответах, это сделало мои приложения снова применимыми в ситуациях удаленного рабочего стола.

...