检测远程桌面连接

56

有没有办法在程序中检测一个程序是否正在远程桌面会话中运行,或者该程序是否在.NET 2.0中正常运行?我试图创建一个时间钟应用程序,它将记录一个人的上下班打卡并跟踪。但是我怀疑这个特定的人正在从家里远程登录到他们工作的计算机上,然后打卡。

有什么想法可以解决这个问题(取消远程桌面访问不算选项)?我的想法是,如果有一种方法可以检测远程桌面会话的存在,那么我将简单地将其实现到程序中,并防止他们远程打卡。


1
哈哈,这是一个有趣的问题 :) - willem
4
这里面一个问题将会是不同远程工具的范围——MSTSC和VNC是主要竞争者,但是PCAnywhere、Live Mesh、GoToMyPC等等呢?更不用说像Live Meeting和Adobe Connect Pro这样的工具,它们都可以实现桌面远程操作。要做到稳健可靠,这可能会很困难。 - Marc Gravell
抱歉提问...我知道这不是主题。 但是客户端通过不同网络使用RDP连接到客户端,它是否通用? - gumuruh
9个回答

58

据称,

System.Windows.Forms.SystemInformation.TerminalServerSession

这将对远程桌面会话(或VNC会话)有效。

但我建议测试以确保它可行;-)


6
我很怀疑它能够捕获VNC会话,它可能只能检测到RDP。 - Spencer Ruport
1
我已经检查过了,与 %sessionname% 不同的是(其他答案),即使使用 /console 或 /admin 开关,这也可以正常工作。这似乎是MSTSC的最佳答案。 - Marc Gravell
好的VNC服务器插入图形驱动程序以提高性能。可能可以检测到这一点。 - Oliver Bock
在Windows远程桌面上运行良好。 - MCattle
@MarkRichman 你需要引用 Windows.Forms,但它应该可以工作。 - Judge2020
似乎一直工作得很好,直到两周前...也许是某个Windows更新引起的? - Daniel Dolz

19

如果你不想像上面建议的那样添加对System.Windows.Forms.dll的引用,那么你也可以直接通过PInvoke调用底层系统调用,像这样:

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

可以在PInvoke.net - SystemMetric找到SystemMetric枚举(但您可以直接使用值0x1000);而GetSystemMetrics的签名在PInvoke.net - GetSystemMetrics上。

我用RDP和VNC测试了一下 - 前者可以工作(也支持管理员/控制台模式),但后者无法检测到。


12

对于 Windows Store 应用程序,您可以使用以下内容:

Windows.System.RemoteDesktop.InteractiveSession.IsRemote

也适用于通用 Windows 平台 (UWP) 应用程序。谢谢! - Steve In CO

9

7
如果您使用 /console 开关(或者根据版本不同,使用 /admin),则会返回“Console”(我刚刚检查过;-p)。 - Marc Gravell
System.Environment.GetEnvironmentVariable("SESSIONNAME").StartsWith("RDP-"); 对我有用。 - RaoulRubin
它对我来说返回了RDP上的控制台。 - user1584245

8

4

几天前我遇到了类似的问题。我解决它的方法是利用一些远程桌面应用程序使用已知的默认端口,至少包括VNC和/或Microsoft远程桌面连接。因此,我创建了一个方法来检查端口是否正在使用,如下所示:

/* Libraries needed */
using System.Linq;
using System.Net.NetworkInformation;

/*....
  ....
  ....*/

private static bool IsPortBeingUsed(int port)
{
    return IPGlobalProperties.GetIPGlobalProperties().
                GetActiveTcpConnections().
                    Any(
                            tcpConnectionInformation => 
                            tcpConnectionInformation.LocalEndPoint.Port == port
                       );
}

请将 using 语句与库放在包含该方法的文件开头。例如,您只需传递一个参数,如默认远程桌面连接端口3389或VNC连接的默认端口5900。该方法使用C# 4.0特性创建,但也可以使用旧版本的C#.Net或Visual Basic完成。对我来说这很有用,因为我只需要检查之前提到的两个应用程序。希望这可以帮助您。

3

这里提醒一下,如果会话使用RemoteFX GPU虚拟化,则仅使用GetSystemMetrics(SystemMetric.SM_REMOTESESSION)已经不再可靠,针对Windows 8 / Server 2012及以上版本。

微软在此处描述了检测RDS的“官方”方法: 检测远程桌面服务环境 (最后更新于18年5月31日)。

该方法包括使用SystemMetrics调用注册表检查。

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

那篇文章中的代码示例仅限于C++,但考虑到它只是一个注册表查找,我认为人们不会觉得在其他语言中复制它太棘手。

我希望至少提到的一些.Net内置函数完全遵循这个,但是:

  • SystemParameters.IsRemoteSession在{{link1:此处注明}}为“映射到SM_REMOTESESSION。请参见GetSystemMetrics”,并且

  • SystemParameters.IsRemotelyControlled在{{link2:此处注明}}为相同,

所以我不抱太大希望。

我将尽快进行一些详细检查并发布结果。


这似乎是答案,更多信息请阅读https://learn.microsoft.com/en-us/windows/win32/termserv/detecting-the-terminal-services-environment - psulek

3
所有远程登录程序都需要在本地计算机上运行一个服务或程序。如果这些服务或程序允许在本地计算机上运行,则提问者只需要担心VNC及其克隆版本。对于远程桌面使用,它们是不必要的,并且所有操作系统都有远程桌面客户端。如果远程桌面正常工作,则不需要VNC服务器。
此外,除非您将VNC克隆版作为管理员安装在服务器计算机上,否则它们无法为您登录。只要您不让用户以其他用户身份运行进程,唯一的问题就是是否有其他员工以有问题的员工身份登录。如果是这种情况,任何技术解决方案都不足以解决问题。即使每个员工都有自己的卡片用于登录,有问题的员工仍然可以将他的卡片交给朋友使用。

2

如果您关心VNC,看起来可以使用netstat检查打开的TCP连接。在命令提示符中输入:

netstat -n -a -p tcp

检查端口5900是否处于"ESTABLISHED"状态。当然,5900是默认连接端口,因此取决于设置的端口。

从那里,我在CodeGuru的帖子中找到了如何在c#程序中使用netstat的说明:

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, ...)
}

1
一个小提示:看起来CodeGuru上发布的代码片段有一个拼写错误,即StandardOutput被拼错为StandartOutput - Adaline Simonian

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接