Detecting remote desktop connection

Viewed 50095

Is there anyway, in a program, to detect if a program is being run from inside a remote desktop session or if the program is being run normal in .NET 2.0? What I'm trying to do is, I create a timeclock application which will clock a person in and out and keep track. But this particular person, I suspect, is remoting into their computer at work, from home, and clocking in and out.

Any ideas how I can solve this issue (and taking away remote desktop access is not an option)? My idea is, if there is a way to detect remote desktop sessions, I will simply implement this into the progam and prevent them from clocking in remotely.

9 Answers

allegedly,

System.Windows.Forms.SystemInformation.TerminalServerSession

will be true for a remote desktop session (or VNC session)

but i'd test it to be sure ;-)

If you don't want to add a reference to System.Windows.Forms.dll just for this (as suggested above), then you can also call the underlying system call directly via PInvoke, like this:

    int result = GetSystemMetrics(SystemMetric.SM_REMOTESESSION);
    bool isRemoteSession = (result != 0);

The SystemMetric enumeration can be found at PInvoke.net - SystemMetric (but you can just use the value of 0x1000); while the signature for GetSystemMetrics at PInvoke.net - GetSystemMetrics.

I tested this with RDP and VNC - works with the former (admin/console mode also), does not detect the latter.

For Windows Store apps, you can use this:

Windows.System.RemoteDesktop.InteractiveSession.IsRemote

For WPF applications there is System.Windows.SystemParameters.IsRemoteSession and System.Windows.SystemParameters.IsRemotelyControlled.

Just a note to say that using GetSystemMetrics(SystemMetric.SM_REMOTESESSION) on its own has stopped being reliable for Windows 8 / Server 2012 onwards if the session is using RemoteFX virtualisation of the GPU.

The "official" method of detecting RDS is described by Microsoft here: Detecting the Remote Desktop Services environment (Last updated 31 May 18).

It consists of using the SystemMetrics call and a registry check at

HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Terminal Server\GlassSessionId

The code samples in that article are C++ only, but given that it's just a registry lookup, I don't think folks will find it too tricksty to replicate in other languages.

I'd like to hope that at least some of the .Net built in functions mentioned upthread are following this in full, but :

  • SystemParameters.IsRemoteSession is noted here as "Maps to SM_REMOTESESSION. See GetSystemMetrics", and

  • SystemParameters.IsRemotelyControlled is noted here as the same,

so I'm not optimistic.

I'll try to do some detailed checks shortly and post the results.

If you're concerned about VNC, it looks like it would be possible to check open TCP connections with netstat. In a command prompt, type:

netstat -n -a -p tcp

and check to see if the port 5900 is "ESTABLISHED". Of course, 5900 is the default connection port, so it would be dependent on what port is set.

From there, I found this post at CodeGuru that explains how to use netstat in your c# program:

string sCommand = "netstat";
string sArgs = "";
System.Diagnostics.ProcessStartInfo psi = new System.Diagnostics.ProcessStartInfo (sCommand, sArgs);

psi.UseShellExecute = false;
psi.RedirectStandartOutput = true;

System.Diagnostics.Process proc = null;
proc = System.Diagnostics.Process.Start(psi);
proc.WaitForExit();

// Read the first 4 lines. They don't contain any information we need to get
for (int i = 0; i < 4; i++)
    proc.StandardOutput.ReadLine();

while (true)
{
    string strLine = proc.StandardOutput.ReadLine();
    if (strLine == null)
        break;

    // Analyze the line 
    // Line is in following structure:
    // Protocol (TCP/UDP)   Local Address(host:port) Foreign Address(host:port) State(ESTABLISHED, ...)
}
Related