如何区分物理D3D适配器与远程桌面协议(RDP)虚拟适配器?
区分物理D3D适配器与RDP虚拟适配器的方法
在RDP会话中出现的同名虚拟适配器,可以通过以下几种可靠方式区分:
1. 使用DXGI扩展适配器描述(推荐方案)
从Direct3D 11开始,IDXGIAdapter1接口提供的GetDesc1方法,能返回包含Flags字段的DXGI_ADAPTER_DESC1结构体,其中DXGI_ADAPTER_FLAG_REMOTE(值为0x4)标志专门用于标记该适配器是远程桌面会话的虚拟适配器。
C#实现思路
通过COM互操作调用DXGI接口完成判断:
- 获取
IDXGIFactory1实例; - 枚举所有
IDXGIAdapter1适配器; - 调用
GetDesc1获取适配器描述,检查Flags是否包含DXGI_ADAPTER_FLAG_REMOTE。
示例代码片段:
using System; using System.Runtime.InteropServices; [ComImport] [Guid("25008864-C843-413D-9617-689635AEBA6B")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IDXGIAdapter1 { // 省略继承的基础方法 void GetDesc1(out DXGI_ADAPTER_DESC1 desc); } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] public struct DXGI_ADAPTER_DESC1 { public ulong VendorId; public ulong DeviceId; public ulong SubSysId; public ulong Revision; public ulong DedicatedVideoMemory; public ulong DedicatedSystemMemory; public ulong SharedSystemMemory; public IntPtr AdapterLuid; public uint Flags; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] public string Description; } public const uint DXGI_ADAPTER_FLAG_REMOTE = 0x4; // 枚举适配器时的过滤逻辑 foreach (var adapter in EnumerateAdapters()) { DXGI_ADAPTER_DESC1 desc; ((IDXGIAdapter1)adapter).GetDesc1(out desc); bool isRemoteAdapter = (desc.Flags & DXGI_ADAPTER_FLAG_REMOTE) != 0; if (isRemoteAdapter) { // 跳过RDP虚拟适配器 continue; } // 将物理适配器添加到用户选择列表 }
2. 通过LUID关联会话判断
适配器的LUID(本地唯一标识符)与Windows会话绑定:
- 本地会话ID通常为0,远程会话ID大于0;
- 提取LUID的高32位可获取所属会话ID;
- 若适配器会话ID与当前活跃会话ID不一致,且当前处于远程会话中,则该适配器为RDP虚拟适配器。
3. 辅助过滤软件渲染适配器
先通过DXGI_ADAPTER_FLAG_SOFTWARE过滤掉Microsoft Basic Render Driver这类纯软件适配器,再结合上述方法区分物理与RDP虚拟适配器,能进一步精简列表。
内容的提问来源于stack exchange,提问作者rustak
相关产品推荐
相关产品推荐

