Jump to content
pyscripter

Remote desktop friendly

Recommended Posts

Delphi 10.4.2 is advertised to be "Remote desktop friendly".   Does anyone know what it takes to make Delphi applications remote desktop friendly?

Edited by pyscripter

Share this post


Link to post

We have been using our inhouse Delphi (2007, XE and lately 10.2) applications almost exclusively via remote Desktop since the start of the Corona pandemic without any problems at all.

 

There is a bug in the Delphi 2007 VCL which can cause an AV when switching between local display and Remote Desktop. After I found and fixed it several years ago (don't remember the specifics), everything just worked.

 

Also, I have been using Delphi 2007, XE2 and 10.2 (and sometimes other versions) via Remote Desktop for years. No problem either.

 

So, my guess would be that this is just marketing.

 

If I had to guess: A Remote Desktop friendly program does not create too many redraws. So: Use double buffering.

Share this post


Link to post
18 minutes ago, dummzeuch said:

If I had to guess: A Remote Desktop friendly program does not create too many redraws. So: Use double buffering.

RDP is a kind of a double buffering, do not use double buffering with RDP

  • Like 1

Share this post


Link to post

The IDE has (or had?) terrible problems with resolution changes, like changing the size of your remote desktop window which also includes connections to Hyper-V VMs. It often got stuck for a minute or completely locked up.

 

It seems they have fixed that with 10.4.2:

Quote

Sometimes, the IDE did not handle the resolution change caused by Remote Desktop and became unresponsive. That thankfully is a thing of the past.

Delphi 10.4.2: Improvements for Microsoft Remote Desktop sessions – FlixEngineering LLC

  • Like 1

Share this post


Link to post
3 hours ago, Attila Kovacs said:

RDP is a kind of a double buffering, do not use double buffering with RDP

Double buffering is absolutely one of the things that you don't do when over RDP. Because then you give up app the benefit of transmitting the logical drawing instructions and instead have to send raster images. 

 

But I wouldn't say RDP is double buffering. You don't draw to off screen bitmap and the flip it or blit it. If you want to draw text, you send the text and instructions of where to draw it, and then the actual rendering happens at the other side. 

 

But yeah, advice to double buffer is wrong. Correct advice is the opposite. Don't ever double buffer in a remote session. 

 

More on that here: https://devblogs.microsoft.com/oldnewthing/20060103-12/?p=32793

 

This may come as a shock to a lot of Delphi devs for whom the standard reaction to flicker seems to be to enabled DoubleBuffered on the form/control. 

Edited by David Heffernan
  • Like 1
  • Thanks 1

Share this post


Link to post
17 minutes ago, David Heffernan said:

This may come as a shock to a lot of Delphi devs for whom the standard reaction to flicker seems to be to enabled DoubleBuffered on the form/control. 

So what should the standard reaction be? I code my custom controls using my own double buffering and ignore the vcl's double buffering, which tends to be rather buggy and variable (different implementations of it throughout the vcl) - especially when vcl themes are enabled. 

  • Like 1

Share this post


Link to post
Guest

Not to mention that Embarcadero is constantly correcting its own corrections ... patch patches!
Until the engineers become aware that the only possible solution is a complete remastering of the system, which I think would only happen if a hacker broke into the servers (including the backups), encrypted everything, asked for an unpayable ransom, forcing the company to break for good.

But we know, that in fact, it will not happen ... so, fix the fix!

 

hug

Share this post


Link to post

@David MillingtonMaybe you could enlighten us as to the nature of the changes that made the Delphi IDE behave better with RD.  Are there any lessons to be learnt by Delphi developers?

Edited by pyscripter
  • Like 1

Share this post


Link to post
Guest

hey @Darian Miller,

just a good ransom-ware, it would be nice don't you think?
New matrix, new bugs! new RSP!!!

 

Then, no one could say that something is not being done there.

 

hug

Share this post


Link to post
1 hour ago, emailx45 said:

it would be nice don't you think?

 

Um... no.  To be "nicer", all the replacement code would have to be better than the existing Delphi code.  At least much of the current Delphi code is stable.

 

Rewrite your biggest project in a hurry and see if it's better.  :classic_biggrin:  

 

  • Like 1
  • Haha 1

Share this post


Link to post
Guest

I don't know how is this relevant as i didn't see the last few IDE's, but the most impactful thing in Microsoft RDP protocol and its image RLE (Run-Length Encoding) that does affect speed and CPU usage is gradient colors, less color means faster performance and responsiveness, more color or less long sequence of pixels of the same colors means more traffic and more CPU usage on both side, Delphi 2009 have the worst performance over RDP (for me at least).

 

Also may be the RDP shared drives feature may be have a some tweaks, never used it with an IDE, always copied folders and accessed them locally.

Share this post


Link to post
15 hours ago, emailx45 said:

would only happen if a hacker broke into the servers (including the backups), encrypted everything, asked for an unpayable ransom, forcing the company to break for good.

They would abandon Delphi for good in that case. There is no way Embarcadero would start that tool from scratch.

Share this post


Link to post
Guest
57 minutes ago, dummzeuch said:

There is no way Embarcadero would start that tool from scratch.

for sure, not for short time... but, just call Elon Musk and all it's solved! A new company in 0day!  :classic_biggrin: :classic_cheerleader:

 

hug

Share this post


Link to post
On 3/6/2021 at 1:31 AM, pyscripter said:

@David MillingtonMaybe you could enlighten us as to the nature of the changes that made the Delphi IDE behave better with RD.  Are there any lessons to be learnt by Delphi developers?

We were thinking of writing a blog post about it, I'll ping the person who was looking at doing so. For more detail I'll need to ask our engineers. My level of oversight here was to ask we fix RD bugs, I did not dig into the details of what changes we made or why.

  • Like 1

Share this post


Link to post
1 hour ago, David Millington said:

We were thinking of writing a blog post about it

Looking forward to reading it!

Share this post


Link to post
On 3/5/2021 at 8:43 PM, pyscripter said:

Does anyone know what it takes to make Delphi applications remote desktop friendly?

F.ex., my 10.3 is veeery lazy on scrolling via RDP.

Share this post


Link to post

Good subject BTW - I learned GetSystemMetrics(SM_REMOTESESSION) and redesigned DoubleBuffered usage in my apps that are running on remote PC's

Edited by Fr0sT.Brutal
  • Like 1

Share this post


Link to post
2 hours ago, Stephen Ball said:

As @David Millington mentioned, we have been working with the R&D team to share tips learned to help speed up VCL applications under remote desktop - to read about it, including a code sample see:

https://blogs.embarcadero.com/how-to-speed-up-remote-desktop-applications/ 

@Stephen BallThank you very much!

 

Is there a need to have a separate window to receive the notifications?   Isn't the code below equivalent to yours?

type
  TForm1 = class(TForm)
    procedure FormDestroy(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure WMWTSSessionChange (var Message: TMessage); message WM_WTSSESSION_CHANGE ;
  private
    { Private declarations }
  public
    { Public declarations }
  end;
var
  Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormDestroy(Sender: TObject);
begin
    WTSUnRegisterSessionNotification(Handle);
end;

procedure TForm1.WMWTSSessionChange(var Message: TMessage);
begin
  inherited;
  case Message.wParam of
    WTS_SESSION_LOCK,
    WTS_REMOTE_DISCONNECT: Application.UpdateMetricSettings := False;
    WTS_REMOTE_CONNECT,
    WTS_SESSION_UNLOCK:
      TThread.ForceQueue(nil, procedure
      begin
        Application.UpdateMetricSettings := True;
      end, 30000);
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  WTSRegisterSessionNotification(Handle, NOTIFY_FOR_THIS_SESSION);
end;

 

Edited by pyscripter

Share this post


Link to post
43 minutes ago, pyscripter said:

@Stephen BallThank you very much!

 

Is there a need to have a separate window to receive the notifications?   Isn't the code below equivalent to yours?


type
  TForm1 = class(TForm)
    procedure FormDestroy(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure WMWTSSessionChange (var Message: TMessage); message WM_WTSSESSION_CHANGE ;
  private
    { Private declarations }
  public
    { Public declarations }
  end;
var
  Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormDestroy(Sender: TObject);
begin
    WTSUnRegisterSessionNotification(Handle);
end;

procedure TForm1.WMWTSSessionChange(var Message: TMessage);
begin
  inherited;
  case Message.wParam of
    WTS_SESSION_LOCK,
    WTS_REMOTE_DISCONNECT: Application.UpdateMetricSettings := False;
    WTS_REMOTE_CONNECT,
    WTS_SESSION_UNLOCK:
      TThread.ForceQueue(nil, procedure
      begin
        Application.UpdateMetricSettings := True;
      end, 30000);
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  WTSRegisterSessionNotification(Handle, NOTIFY_FOR_THIS_SESSION);
end;

 

This code fails under VCL window recreation. Hence the Emba code. 

 

My answer to this old SO question presents a different way that may be simpler in the long run. 

 

https://stackoverflow.com/q/4854534/505088

  • Thanks 1

Share this post


Link to post
36 minutes ago, David Heffernan said:

My answer to this old SO question presents a different way that may be simpler in the long run. 

Thanks!  DestroyWnd is not called when the application exits.  Is this an issue here?   You could call the WTSUnRegisterSessionNotification at the WM_DESTROY handler instead. 

Share this post


Link to post
18 minutes ago, pyscripter said:

DestroyWnd is not called when the application exits.

Really? That's upsetting. Although it rings some bells. But it won't matter here because process termination will lead to the system tidying up.

 

Ill have a look tomorrow. 

Share this post


Link to post

In light of @David Heffernan remarks here is a shorter version of @Stephen Ball code:


 

type
  TForm1 = class(TForm)
    procedure CreateWnd; override;
    procedure WMWTSSessionChange (var Message: TMessage); message WM_WTSSESSION_CHANGE ;
    procedure WMDestroy(var Message: TWMDestroy); message WM_DESTROY;
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.WMDestroy(var Message: TWMDestroy);
begin
  inherited;
  WTSUnRegisterSessionNotification(Handle);
end;

procedure TForm1.WMWTSSessionChange(var Message: TMessage);
begin
  case Message.wParam of
    WTS_SESSION_LOCK,
    WTS_REMOTE_DISCONNECT: Application.UpdateMetricSettings := False;
    WTS_REMOTE_CONNECT,
    WTS_SESSION_UNLOCK:
      TThread.ForceQueue(nil, procedure
      begin
        Application.UpdateMetricSettings := True;
      end, 30000);
  end;
end;

procedure TForm1.CreateWnd;
begin
  inherited;
  WTSRegisterSessionNotification(Handle, NOTIFY_FOR_THIS_SESSION);
end;

Instead of CreateWnd you could override the CreateWindowHandle method.

Edited by pyscripter

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×