点击上方蓝字关注“汪宇杰博客”
导语
由于疫情的关系,很久没发文章了。今天终于稳定下来在家办公,抽空分享一个刚学会的技巧。最近在家办公的程序员可能避免不了要用远程桌面,那么问题来了,你的 .NET Core 程序有没有办法知道自己是否在 Windows 远程桌面环境下运行呢?
Windows Forms
如果你用的是 .NET Core 3.x 版本,并开发的是 Windows Forms 应用,那么恭喜你,.NET 自带了一个简单粗暴的方法。
SystemInformation.TerminalServerSession 即可返回当前会话是否在远程桌面下。
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
if (IsRemoteSession)
{
MessageBox.Show("Under RDP");
}
}
public static Boolean IsRemoteSession => SystemInformation.TerminalServerSession;
}
运行效果
去你的 WinForms?
Bing 不是人人都喜欢 WinForms,毕竟它代表落后、不思进取的拖控件程序员(即使他们下班时候天还亮着)。那么其他类型的 .NET Core 程序如何判断自己是否在 RDP 下运行呢?我们需要 P/Invoke 骚操作。
.NET Core 使用 P/Invoke 的姿势和 .NET Framework 几乎一致。只要一个 [DllImport] 标记即可。
根据田牌文档描述,Windows 本身就带有一个 Win32 API可以返回当前会话是否为远程桌面。即 User32.dll 上的 GetSystemMetrics( SM_REMOTESESSION ); 方法
文档传送门:https://docs.microsoft.com/en-us/windows/win32/termserv/detecting-the-terminal-services-environment
其中的 SM_REMOTESESSION 其实是个预定义的 int 值,在 C# 中可表示为 0x1000。使用 P/Invoke 判断一个 Console 程序是否运行在 RDP 下的代码如下:
static void Main(string[] args)
{
bool isRDP = GetSystemMetrics(SM_REMOTESESSION);
Console.WriteLine($"Running under RDP: {isRDP}");
Console.ReadKey();
}
const int SM_REMOTESESSION = 0x1000;
[DllImport("user32")]
static extern bool GetSystemMetrics(int index);
其中 user32 后面的 .dll 可以省略。.NET Core 在 Windows 上会自动去找 dll,在 Linux 上会去找 so (即使 Linux Bing 没有 RDP 这个东西也没有 user32 这个库)
运行效果
不过这种技巧大家平时正常写代码的时候一定要尽量避免,在 .NET 的托管环境下调用非托管代码不仅会导致程序和平台及系统版本耦合,还易爆,爆完还难以抓异常信息。有关 P/Invoke 的详细介绍,请参考微软文档:https://docs.microsoft.com/en-us/dotnet/standard/native-interop/pinvoke