You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用C#获取Windows「设备和打印机」中的设备名称

获取Windows「设备和打印机」中的非打印机设备名称

嘿,别着急,我完全理解你的困扰!要获取Windows「设备和打印机」里的那些非打印机设备名称(比如你的ATH-CKR35BT蓝牙耳机、ERGO M575鼠标这类),其实得找对Windows用来管理这些设备的逻辑——它们大多属于**设备容器(Device Container)**或者特定的外设接口类,我给你两种靠谱的方法:

方法1:通过WMI直接查询设备容器(最简便)

Windows的「设备和打印机」里显示的每个设备图标,本质对应一个设备容器(Device Container),WMI的Win32_DeviceContainer类直接提供了这些容器的名称,这是最直接的方式。

C#示例代码

using System;
using System.Collections.Generic;
using System.Management;

public class DeviceContainerHelper
{
    public static List<string> GetDeviceAndPrintersNames()
    {
        List<string> deviceNames = new List<string>();
        
        // 查询所有设备容器,Name属性就是「设备和打印机」里显示的名称
        string wmiQuery = "SELECT Name FROM Win32_DeviceContainer";
        
        using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(wmiQuery))
        {
            foreach (ManagementObject container in searcher.Get())
            {
                string deviceName = container["Name"]?.ToString().Trim();
                if (!string.IsNullOrEmpty(deviceName) && !deviceNames.Contains(deviceName))
                {
                    deviceNames.Add(deviceName);
                }
            }
        }
        
        return deviceNames;
    }
}

说明

  • Win32_DeviceContainer的Name属性就是你在「设备和打印机」里看到的设备名称,比如“Xperia Z5”、“ERGO M575”
  • 如果你想要过滤掉打印机(因为你已经会获取打印机了),可以在查询里加条件:WHERE NOT Name LIKE '%Printer%'(根据实际情况调整关键词)
  • 注意:需要以管理员权限运行程序,否则可能无法访问部分设备信息

方法2:使用Setup API枚举外设接口(更精准)

如果WMI的方法返回的结果不够精准,你可以用Windows原生的Setup API来枚举特定类的外设(比如蓝牙设备、HID输入设备、便携设备),然后获取它们的友好名称。

C#示例代码(P/Invoke调用Setup API)

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;

public class DeviceInterfaceHelper
{
    // 「设备和打印机」中常见的外设类GUID
    private static readonly Guid GUID_DEVINTERFACE_HID = new Guid("{4D1E55B2-F16F-11CF-88CB-001111000030}"); // 鼠标、键盘等HID设备
    private static readonly Guid GUID_BLUETOOTH_DEVICE = new Guid("{00001101-0000-1000-8000-00805F9B34FB}"); // 蓝牙设备
    private static readonly Guid GUID_DEVINTERFACE_PORTABLE_DEVICE = new Guid("{6AC27878-A6FA-4155-BA85-F98F491D4F33}"); // 便携设备(如手机)

    // Setup API所需的结构体
    [StructLayout(LayoutKind.Sequential)]
    private struct SP_DEVICE_INTERFACE_DATA
    {
        public int cbSize;
        public Guid InterfaceClassGuid;
        public int Flags;
        public IntPtr Reserved;
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct SP_DEVINFO_DATA
    {
        public int cbSize;
        public Guid ClassGuid;
        public int DevInst;
        public IntPtr Reserved;
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    private struct SP_DEVICE_INTERFACE_DETAIL_DATA
    {
        public int cbSize;
        [MarshalAs(UnmanagedType.LPWStr)]
        public string DevicePath;
    }

    // P/Invoke函数声明
    [DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    private static extern IntPtr SetupDiGetClassDevs(ref Guid ClassGuid, string Enumerator, IntPtr hwndParent, uint Flags);

    [DllImport("setupapi.dll", SetLastError = true)]
    private static extern bool SetupDiEnumDeviceInterfaces(IntPtr hDevInfo, IntPtr devInfo, ref Guid interfaceClassGuid, uint memberIndex, ref SP_DEVICE_INTERFACE_DATA deviceInterfaceData);

    [DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    private static extern bool SetupDiGetDeviceInterfaceDetail(IntPtr hDevInfo, ref SP_DEVICE_INTERFACE_DATA deviceInterfaceData, IntPtr deviceInterfaceDetailData, uint deviceInterfaceDetailDataSize, out uint requiredSize, ref SP_DEVINFO_DATA deviceInfoData);

    [DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    private static extern bool SetupDiGetDeviceRegistryProperty(IntPtr hDevInfo, ref SP_DEVINFO_DATA deviceInfoData, uint property, out uint propertyRegDataType, StringBuilder propertyBuffer, uint propertyBufferSize, out uint requiredSize);

    // 常量定义
    private const uint DIGCF_PRESENT = 0x00000002;
    private const uint DIGCF_DEVICEINTERFACE = 0x00000010;
    private const uint SPDRP_FRIENDLYNAME = 0x0000000C; // 设备友好名称

    public static List<string> GetPeripheralDeviceNames()
    {
        List<string> deviceNames = new List<string>();
        List<Guid> targetClasses = new List<Guid> { GUID_DEVINTERFACE_HID, GUID_BLUETOOTH_DEVICE, GUID_DEVINTERFACE_PORTABLE_DEVICE };

        foreach (Guid classGuid in targetClasses)
        {
            // 获取当前存在的设备接口集合
            IntPtr hDevInfo = SetupDiGetClassDevs(ref classGuid, null, IntPtr.Zero, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
            if (hDevInfo == IntPtr.Zero) continue;

            SP_DEVICE_INTERFACE_DATA interfaceData = new SP_DEVICE_INTERFACE_DATA();
            interfaceData.cbSize = Marshal.SizeOf(interfaceData);

            SP_DEVINFO_DATA devInfoData = new SP_DEVINFO_DATA();
            devInfoData.cbSize = Marshal.SizeOf(devInfoData);

            uint index = 0;
            while (SetupDiEnumDeviceInterfaces(hDevInfo, IntPtr.Zero, ref classGuid, index, ref interfaceData))
            {
                // 获取设备接口详情的缓冲区大小
                uint requiredSize = 0;
                SetupDiGetDeviceInterfaceDetail(hDevInfo, ref interfaceData, IntPtr.Zero, 0, out requiredSize, ref devInfoData);

                // 分配缓冲区并获取详情
                IntPtr detailPtr = Marshal.AllocHGlobal((int)requiredSize);
                Marshal.WriteInt32(detailPtr, IntPtr.Size == 8 ? 8 : 4); // 适配32/64位系统

                if (SetupDiGetDeviceInterfaceDetail(hDevInfo, ref interfaceData, detailPtr, requiredSize, out requiredSize, ref devInfoData))
                {
                    // 获取设备友好名称
                    StringBuilder friendlyName = new StringBuilder(256);
                    uint propType;
                    uint nameSize = 0;
                    if (SetupDiGetDeviceRegistryProperty(hDevInfo, ref devInfoData, SPDRP_FRIENDLYNAME, out propType, friendlyName, (uint)friendlyName.Capacity, out nameSize))
                    {
                        string name = friendlyName.ToString().Trim();
                        if (!string.IsNullOrEmpty(name) && !deviceNames.Contains(name))
                        {
                            deviceNames.Add(name);
                        }
                    }
                }

                Marshal.FreeHGlobal(detailPtr);
                index++;
            }

            Marshal.FreeHGlobal(hDevInfo);
        }

        return deviceNames;
    }
}

说明

  • 这段代码枚举了三类常见的外设:HID输入设备、蓝牙设备、便携设备,覆盖了「设备和打印机」里的大部分非打印机设备
  • SPDRP_FRIENDLYNAME属性就是设备在界面上显示的名称
  • 同样需要管理员权限运行,确保能访问所有设备信息

补充提示

  • 如果你用的是C++,逻辑和上面的Setup API方法一致,直接调用原生的Setup API函数即可
  • 两种方法都可以去重,避免重复的设备名称(比如同一个设备可能有多个接口,但显示同一个名称)

内容的提问来源于stack exchange,提问作者Shiranui

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 19:52:38