C#中如何检查与USB集线器USB端口以及所使用的控制器? [英] C# How do I check USB Ports with USB Hub and used Controller?

查看:323
本文介绍了C#中如何检查与USB集线器USB端口以及所使用的控制器?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在扫描与USB集线器的所有USB端口(检查它是否是根与否)和哪个控制器他们connectet。



若要更明显的:

  USB端口1(没有插入) - > USB HUB1 | |  - >控制器1 
USB端口2(键盘插入) - > | - > USB根集线器| - >控制器2
USB端口3(没有插入) - > USB HUB2 | |
USB端口4(没有插入) - > | - > USB根集线器| - > Controller3(主板)



我想告诉用户所有的端口和连接集线器为一棵树。而如果其控制器中的USB接口都在使用与否。



我希望你们能理解我试图来形容。如果你可以给我一些关键词,甚至代码片段,我将不胜感激。



PS:对不起,我英文不好。



下面是到目前为止的代码(我用的是.NetFramework 4.5.x):



USBPortScanner类:

 使用系统; 
使用System.Collections.Generic;
使用System.Linq的;
使用System.Text;使用System.Threading.Tasks
;
使用System.Management;使用System.IO.Ports
;

命名空间USBPortScanner

{
类USBPortScanner
{
静态无效的主要(字串[] args)
{
变种usbDevices = GetUSBDevices();
的foreach(在usbDevices VAR usbDevice)
{
//打印所有定义调性质,他们需要在USBDeviceInfo.cs被定义!
Console.WriteLine(名称:{0} \r\\\
Caption:{1} \r\\\
Error代码:{2} \r\\\
Device ID:{3} \r\\ \
System名称:{4} \r\\\
Status:{5},
usbDevice.Name,usbDevice.Caption,usbDevice.ConfigManagerErrorCode,usbDevice.DeviceID,usbDevice.SystemName,usbDevice.Status);
Console.WriteLine();
}

Console.Read();
}
//设置该设备的变量
静态列表<属性; USBDeviceInfo> GetUSBDevices()
{
名单,LT; USBDeviceInfo>设备=新的List< USBDeviceInfo>();

//利用扫描所有USBHubs与WMI
使用(ManagementObjectCollection集合(VAR搜索=新ManagementObjectSearcher(@SELECT * FROM Win32_USBHub))
{
= searcher.Get())
{
的foreach(的ManagementObject设备集合)
{

//要显示所有可用的数据
//控制台。的WriteLine(device.Path);

//的foreach(在device.Properties PropertyData丙)
// {
// Console.WriteLine(prop.Name +:+ prop.Value);
//}

//Console.WriteLine();

//添加属性,将设备
devices.Add(新USBDeviceInfo(设备));
}
}
}

返回装置;
}
}
}



USBDeviceInfo类:使用系统

 ; 
使用System.Collections.Generic;
使用System.Linq的;
使用System.Text;使用System.Threading.Tasks
;
使用System.Management;

命名空间USBPortScanner
{

类USBDeviceInfo
{
公共USBDeviceInfo(的ManagementObject设备)
{
本。名称= device.GetPropertyValue(姓名)的ToString()。
this.Caption = device.GetPropertyValue(标题)的ToString();

如果(device.GetPropertyValue(ConfigManagerErrorCode)!= NULL)
{
this.ConfigManagerErrorCode =(错误码)device.GetPropertyValue(ConfigManagerErrorCode);
}
,否则
{
this.ConfigManagerErrorCode = ErrorCode.Device_is_not_present_not_working_properly_or_does_not_have_all_of_its_drivers_installed;
}

this.DeviceID = device.GetPropertyValue(的DeviceID)的ToString()。
this.SystemName = device.GetPropertyValue(的SystemName)的ToString()。
this.Status = device.GetPropertyValue(状态)的ToString()。
}

//设置上述可使用的变量我们在Program.cs的
公共字符串名称{宗旨得到;私人集; }
公共字符串字幕{搞定;私人集; }
公共错误码ConfigManagerErrorCode {搞定;私人集; }
公共字符串的DeviceID {搞定;私人集; }
公共字符串的SystemName {搞定;私人集; }
公共字符串状态{搞定;私人集; }
}
枚举错误码:UINT
{
Device_is_working_properly = 0,
Device_is_not_configured_correctly = 1,
Windows_cannot_load_the_driver_for_this_device = 2,
Driver_for_this_device_might_be_corrupted_or_the_system_may_be_low_on_memory_or_other_resources = 3 ,
Device_is_not_working_properly_One_of_its_drivers_or_the_registry_might_be_corrupted = 4,
Driver_for_the_device_requires_a_resource_that_Windows_cannot_manage = 5,
Boot_configuration_for_the_device_conflicts_with_other_devices = 6,
Cannot_filter = 7,
Driver_loader_for_the_device_is_missing = 8,
Device_is_not_working_properly_The_controlling_firmware_is_incorrectly_reporting_the_resources_for_the_device = 9,
Device_cannot_start = 10,
Device_failed = 11,
Device_cannot_find_enough_free_resources_to_use = 12,
Windows_cannot_verify_the_device_resources = 13,
Device_cannot_work_properly_until_the_computer_is_restarted = 14,
Device_is_not_working_properly_due_to_a_possible_reenumeration_problem = 15,
Windows_cannot_identify_all_of_the_resources_that_the_device_uses = 16,
Device_is_requesting_an_unknown_resource_type = 17,
Device_drivers_must_be_reinstalled = 18,
Failure_using_the_VxD_loader = 19,
Registry_might_be_corrupted = 20,
System_failure_If_changing_the_device_driver_is_ineffective_see_the_hardware_documentation_Windows_is_removing_the_device = 21,
Device_is_disabled = 22,
System_failure_If_changing_the_device_driver_is_ineffective_see_the_hardware_documentation = 23,
Device_is_not_present_not_working_properly_or_does_not_have_all_of_its_drivers_installed = 24,
Windows_is_still_setting_up_the_device = 25 | 26,
Device_does_not_have_valid_log_configuration = 27,
Device_drivers_are_not_installed = 28,
Device_is_disabled_The_device_firmware_did_not_provide_the_required_resources = 29,
Device_is_using_an_IRQ_resource_that_another_device_is_using = 30,
Device_is_not_working_properly_Windows_cannot_load_the_required_device_drivers = 31,

}
}


解决方案

我已经找到了解自己。最关键的是通过C ++ DLL注册表的使用。
下面的代码是我从其他网站使用的例子。我希望这将有助于社会太



来源:的 http://www.news2news.com/vfp/?example=545&ver=vcs&PHPSESSID=70ba6845606a96b355ab7f772fb14386



代码:

 使用系统; 
使用System.Collections.Generic;使用System.Runtime.InteropServices
;
使用System.Linq的;

命名空间DeviceEnumerator
{
公共类节目
{
公共静态无效的主要()
{
变种的DeviceTree =新的DeviceTree();

的foreach(在Win32.DeviceClasses VAR DEVICECLASS)
{
Console.WriteLine(\\\
{0},deviceClass.Value);

的foreach(在deviceTree.DeviceNodes $ B $ VAR设备b。凡(D => d.ClassGuid == deviceClass.Key))
{
Console.WriteLine(
\t {1} {0},
device.Description,
device.EnumeratorName);
}
}

Console.Write(\\\
\\\
Any键......);
Console.ReadKey();
}
}

公共类的DeviceTree:IDisposable的
{
私人的IntPtr _machineHandle = IntPtr.Zero;
私人的IntPtr _rootDeviceHandle = IntPtr.Zero;
私人DeviceNode _rootNode;所有设备的

//持平收集发现
私有列表< DeviceNode> _deviceNodes;

公共DeviceNode的RootNode
{
得到
{
返回this._rootNode;
}
}

公开名单< DeviceNode> DeviceNodes
{
获得
{
返回this._deviceNodes;
}
}

公众的DeviceTree()
{
EnumerateDevices();
}

〜的DeviceTree()
{
this.Dispose(假);
}

公共无效的Dispose()
{
this.Dispose(真);
GC.SuppressFinalize(本);
}

受保护的虚拟无效的Dispose(BOOL处置)
{
如果(处置)
{
this._deviceNodes.Clear() ;
}

this.DisconnectFromMachine();
}

私人无效EnumerateDevices()
{
this.DisconnectFromMachine();

//本地机器假设
如果(Win32.CM_Connect_Machine(
空,楼盘this._machineHandle)!= 0)
{
的回报;
}


{
Win32.CM_Locate_DevNode_Ex(
裁判this._rootDeviceHandle,
0,
0,
this._machineHandle);

//递归枚举
this._rootNode =新DeviceNode(
this._rootDeviceHandle,
空,
this._machineHandle);
}
终于
{
this.DisconnectFromMachine();

如果(this._rootNode!= NULL)
{
this._deviceNodes = this._rootNode
.Flatten(结点=> node.Children).ToList ();
}
}
}

私人无效DisconnectFromMachine()
{
如果(this._machineHandle!= IntPtr.Zero)
{
Win32.CM_Disconnect_Machine(this._machineHandle);
this._machineHandle = IntPtr.Zero;
}
}
}

公共类DeviceNode:IDisposable的
{
私人只读DeviceNode _parentDevice;
私人只读表< DeviceNode> _children;
私人只读的IntPtr _deviceHandle;
私人只读的IntPtr _machineHandle;

私人只读字典<整型,字符串>
_deviceProperties;

公共DeviceNode ParentDevice
{
得到
{
返回_parentDevice;
}
}

公众解释<整型,字符串> DeviceProperties
{
得到
{
返回_deviceProperties;
}
}

公开名单< DeviceNode>儿童
{
得到
{
返回this._children;
}
}

公众的Guid ClassGuid
{
得到
{
字符串缓冲区=
this.GetProperty (Win32.DevRegProperty.ClassGuid);

变种GUID =新的GUID();

如果(buffer.Length> = 32)
{

{
GUID =新的GUID(缓冲);
}

{
GUID =新的GUID();
}
}

返回GUID;
}
}

公共字符串描述
{
得到
{
返回
的getProperty(Win32.DevRegProperty .DeviceDescription);
}
}

公共字符串的FriendlyName
{
得到
{
返回
的getProperty(Win32.DevRegProperty .FriendlyName);
}
}

公共字符串EnumeratorName
{
得到
{
返回
的getProperty(Win32.DevRegProperty .EnumeratorName);
}
}

公共字符串LocationInfo
{
得到
{
返回
的getProperty(Win32.DevRegProperty .LocationInfo);
}
}

公共DeviceNode(IntPtr的deviceHandle,DeviceNode parentDevice)
:这(
deviceHandle,
parentDevice,
parentDevice._machineHandle)
{
}

公共DeviceNode(
IntPtr的deviceHandle,
DeviceNode parentDevice,
的IntPtr machineHandle)
{
_deviceProperties =新词典<整型,字符串>();
_children =新的List< DeviceNode>();

_deviceHandle = deviceHandle;
_machineHandle = machineHandle;
_parentDevice = parentDevice;

EnumerateDeviceProperties();
EnumerateChildren();
}

私人字符串的getProperty(
Win32.DevRegProperty devRegProperty)
{
返回的getProperty((INT)devRegProperty);
}

私人字符串的getProperty(INT指数)
{
字符串缓冲区;
VAR的结果= this._deviceProperties
.TryGetValue(索引,出缓冲器);
返回的结果?缓冲区:的String.Empty;
}

私人无效EnumerateDeviceProperties()
{
为(VAR指数= 0;指数< 64;指数++)
{
UINT BUFSIZE = 2048;

IntPtr的缓冲区=
Marshal.AllocHGlobal((INT)BUFSIZE);

变种结果=
Win32.CM_Get_DevNode_Registry_Property_Ex(
_deviceHandle,
指数,
IntPtr.Zero,
缓冲区,
REF BUFSIZE,
0,
_machineHandle);

VAR propertyString =结果== 0
? Marshal.PtrToStringAnsi(缓冲)
:的String.Empty;

_deviceProperties.Add(索引,propertyString);

Marshal.FreeHGlobal(缓冲);
}
}

私人无效EnumerateChildren()
{
IntPtr的ptrFirstChild = IntPtr.Zero;

如果(Win32.CM_Get_Child_Ex(
裁判ptrFirstChild,
_deviceHandle,
0,
_machineHandle)!= 0)
{
回报;
}

VAR ptrChild = ptrFirstChild;
VAR ptrSibling = IntPtr.Zero;


{
变种childDevice =新DeviceNode(ptrChild,这一点);
_children.Add(childDevice);

如果(Win32.CM_Get_Sibling_Ex(
裁判ptrSibling,
ptrChild,
0,
_machineHandle)!= 0)打破;

ptrChild = ptrSibling;
}
,而(真);
}

公共无效的Dispose()
{
this.Dispose(真);
GC.SuppressFinalize(本);
}

受保护的虚拟无效的Dispose(BOOL处置)
{
如果(处置)
{
_deviceProperties.Clear();
}
}
}

内部静态类LinqExtensionMethods
{
公共静态的IEnumerable< T>返回< T>(T元素)
{
收益率的回报元素;
}

公共静态的IEnumerable< T> StartWith< T>(
本的IEnumerable< T>清单,T元素)
{
收益回报(元素).Concat(名单);
}

公共静态的IEnumerable< TEntity>拼合< TEntity>(
这个TEntity元素,
Func键< TEntity,IEnumerable的< TEntity>> childSelector)
{
如果(childSelector(元)!= NULL)
返回childSelector(元素)
.SelectMany(孩子=> child.Flatten(childSelector))
.StartWith(元);

变种物品=新的List< TEntity> {}元素;
回报率的项目;
}
}

公共静态类的Win32
{
//这是一个部分列表
公共静态只读
字典< ; GUID,字符串> DeviceClasses =
新字典< GUID,字符串>
{
{新的GUID({4D36E967-E325-11CE-BFC1-08002BE10318}),
磁盘驱动器},
{新的GUID({4d36e968- E325-11CE-BFC1-08002BE10318}),
显示适配器},
{新的GUID({4D36E96B-E325-11CE-BFC1-08002BE10318}),
键盘},
{新的GUID({4d36e96f-E325-11CE-BFC1-08002BE10318}),
老鼠},
};

公共枚举DevRegProperty:UINT
{
DeviceDescription = 1,
硬件ID = 2,
CompatibleIds = 3,
Unused0 = 4,
服务= 5,
Unused1 = 6,
Unused2 = 7,
级= 8,
ClassGuid = 9,
驱动= 0x0A的,
ConfigFlags = 0x0B中,
制造=的0x0C,
的FriendlyName =符进行,
LocationInfo = 0x0E的,
PhysicalDeviceObjectName =为0x0F,
性能= 0×10,
UiNumber = 0×11,
的UpperFilters = 0×12,
LOWERFILTERS = 0x13,
BusTypeGuid =量0x014,
LegacyBusType =为0x15,
BusNumber = 0x16,
EnumeratorName = 0x17已,
}

函数[DllImport(KERNEL32.DLL)]
公共静态外部UINT GetLogicalDrives();

函数[DllImport(KERNEL32.DLL)]
公共静态外部INT GetDriveType(
[的MarshalAs(UnmanagedType.LPStr)串rootPathName);

函数[DllImport(cfgmgr32.dll)]
公共静态外部INT CM_Connect_Machine(
[的MarshalAs(UnmanagedType.LPStr)字符串uncServerName,
裁判的IntPtr machineHandle );

函数[DllImport(cfgmgr32.dll)]
公共静态外部INT CM_Disconnect_Machine(
IntPtr的machineHandle);

函数[DllImport(cfgmgr32.dll)]
公共静态外部INT CM_Locate_DevNode_Ex(
文献的IntPtr deviceHandle,
INT DEVICEID,
UINT标志,
IntPtr的machineHandle);

函数[DllImport(cfgmgr32.dll)]
公共静态外部INT CM_Get_Child_Ex(
文献的IntPtr childDeviceHandle,
IntPtr的parentDeviceHandle,
UINT标志,
IntPtr的machineHandle);

函数[DllImport(cfgmgr32.dll)]
公共静态外部INT CM_Get_Sibling_Ex(
文献的IntPtr siblingDeviceHandle,
IntPtr的deviceHandle,
UINT标志,
IntPtr的machineHandle);

函数[DllImport(cfgmgr32.dll)]
公共静态外部INT
CM_Get_DevNode_Registry_Property_Ex(
IntPtr的deviceHandle,
int属性,
IntPtr的regDataType,
IntPtr的outBuffer,
裁判UINT大小,
INT标志,
IntPtr的machineHandle);
}
}


I am currently trying to scan all USB Ports with their USB Hub (check if it is Root or not) and to which controller they are connectet.

To make it more visible:

USB Port1 (nothing plugged in)   -> USB Hub1   |                 |-> Controller 1
USB Port2 (Keyboard plugged in)  ->            |-> USB Root Hub  |-> Controller 2
USB Port3 (nothing plugged in)   -> USB Hub2   |                 |
USB Port4 (nothing plugged in)   ->            |-> USB Root Hub  |-> Controller3 (Mainboard)

I want to show the User all ports and connected Hubs as a tree. And if the USB Port with its controller are in use or not.

I hope you guys can understand what I am trying to describe. If you could give me some Keywords or even Code snippets i would greatly appreciate it.

PS.: Sorry for my bad english.

Here is the Code so far (I am using the .NetFramework 4.5.x):

USBPortScanner Class:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Management;
using System.IO.Ports;

namespace USBPortScanner

{
    class USBPortScanner
    {
        static void Main(string[] args)
        {
            var usbDevices = GetUSBDevices();
            foreach (var usbDevice in usbDevices)
            {
                //Prints all defined porperties, they need to be defined in the USBDeviceInfo.cs!
                Console.WriteLine("Name: {0}\r\nCaption: {1}\r\nError Code: {2}\r\nDevice ID: {3}\r\nSystem Name: {4}\r\nStatus: {5}",
                    usbDevice.Name, usbDevice.Caption, usbDevice.ConfigManagerErrorCode, usbDevice.DeviceID, usbDevice.SystemName, usbDevice.Status);
                Console.WriteLine();
            }

            Console.Read();
        }
        //Sets the Properties for the device variable
        static List<USBDeviceInfo> GetUSBDevices()
        {
            List<USBDeviceInfo> devices = new List<USBDeviceInfo>();

            //Scanning all USBHubs with WMI
            using (var searcher = new ManagementObjectSearcher(@"Select * From Win32_USBHub"))
            {
                using (ManagementObjectCollection collection = searcher.Get())
                {
                    foreach (ManagementObject device in collection)
                    {

                        //To show all available data
                        //Console.WriteLine(device.Path);

                        //foreach (PropertyData prop in device.Properties)
                        //{
                        //    Console.WriteLine(prop.Name + ": " + prop.Value);
                        //}

                        //Console.WriteLine();

                        //Adds properties to device
                        devices.Add(new USBDeviceInfo(device));
                    }
                }
            }

            return devices;
        }
    }
}

USBDeviceInfo Class:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Management;

namespace USBPortScanner
{

    class USBDeviceInfo
    {
        public USBDeviceInfo(ManagementObject device)
        {
            this.Name = device.GetPropertyValue("Name").ToString();
            this.Caption = device.GetPropertyValue("Caption").ToString();

            if (device.GetPropertyValue("ConfigManagerErrorCode") != null)
            {
                this.ConfigManagerErrorCode = (ErrorCode)device.GetPropertyValue("ConfigManagerErrorCode");
            }
            else
            {
                this.ConfigManagerErrorCode = ErrorCode.Device_is_not_present_not_working_properly_or_does_not_have_all_of_its_drivers_installed;
            }

            this.DeviceID = device.GetPropertyValue("DeviceID").ToString();
            this.SystemName = device.GetPropertyValue("SystemName").ToString();
            this.Status = device.GetPropertyValue("Status").ToString();
        }

        //Sets the variables above usable for our purpose in the Program.cs
        public string Name { get; private set; }
        public string Caption { get; private set; }
        public ErrorCode ConfigManagerErrorCode { get; private set; }
        public string DeviceID { get; private set; }
        public string SystemName { get; private set; }
        public string Status { get; private set; }
    }
    enum ErrorCode : uint
    {
        Device_is_working_properly = 0,
        Device_is_not_configured_correctly = 1,
        Windows_cannot_load_the_driver_for_this_device = 2,
        Driver_for_this_device_might_be_corrupted_or_the_system_may_be_low_on_memory_or_other_resources = 3,
        Device_is_not_working_properly_One_of_its_drivers_or_the_registry_might_be_corrupted = 4,
        Driver_for_the_device_requires_a_resource_that_Windows_cannot_manage = 5,
        Boot_configuration_for_the_device_conflicts_with_other_devices = 6,
        Cannot_filter = 7,
        Driver_loader_for_the_device_is_missing = 8,
        Device_is_not_working_properly_The_controlling_firmware_is_incorrectly_reporting_the_resources_for_the_device = 9,
        Device_cannot_start = 10,
        Device_failed = 11,
        Device_cannot_find_enough_free_resources_to_use = 12,
        Windows_cannot_verify_the_device_resources = 13,
        Device_cannot_work_properly_until_the_computer_is_restarted = 14,
        Device_is_not_working_properly_due_to_a_possible_reenumeration_problem = 15,
        Windows_cannot_identify_all_of_the_resources_that_the_device_uses = 16,
        Device_is_requesting_an_unknown_resource_type = 17,
        Device_drivers_must_be_reinstalled = 18,
        Failure_using_the_VxD_loader = 19,
        Registry_might_be_corrupted = 20,
        System_failure_If_changing_the_device_driver_is_ineffective_see_the_hardware_documentation_Windows_is_removing_the_device = 21,
        Device_is_disabled = 22,
        System_failure_If_changing_the_device_driver_is_ineffective_see_the_hardware_documentation = 23,
        Device_is_not_present_not_working_properly_or_does_not_have_all_of_its_drivers_installed = 24,
        Windows_is_still_setting_up_the_device = 25 | 26,
        Device_does_not_have_valid_log_configuration = 27,
        Device_drivers_are_not_installed = 28,
        Device_is_disabled_The_device_firmware_did_not_provide_the_required_resources = 29,
        Device_is_using_an_IRQ_resource_that_another_device_is_using = 30,
        Device_is_not_working_properly_Windows_cannot_load_the_required_device_drivers = 31,

    }
}

解决方案

I've found the solution myself. The key is to use the registry via c++ dll. The Code below is a example i used from another site. I hope it will help the community too.

source: http://www.news2news.com/vfp/?example=545&ver=vcs&PHPSESSID=70ba6845606a96b355ab7f772fb14386

Code:

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

namespace DeviceEnumerator
{
    public class Program
    {
        public static void Main()
        {
            var deviceTree = new DeviceTree();

            foreach (var deviceClass in Win32.DeviceClasses)
            {
                Console.WriteLine("\n{0}:", deviceClass.Value);

                foreach (var device in deviceTree.DeviceNodes
                    .Where(d => d.ClassGuid == deviceClass.Key))
                {
                    Console.WriteLine(
                        "\t{1}: {0}",
                        device.Description,
                        device.EnumeratorName);
                }
            }

            Console.Write("\n\nAny key...");
            Console.ReadKey();
        }
    }

    public class DeviceTree : IDisposable
    {
        private IntPtr _machineHandle = IntPtr.Zero;
        private IntPtr _rootDeviceHandle = IntPtr.Zero;
        private DeviceNode _rootNode;

        // flat collection of all devices found
        private List< DeviceNode > _deviceNodes;

        public DeviceNode RootNode
        {
            get
            {
                return this._rootNode;
            }
        }

        public List< DeviceNode > DeviceNodes
        {
            get
            {
                return this._deviceNodes;
            }
        }

        public DeviceTree()
        {
            EnumerateDevices();
        }

        ~DeviceTree()
        {
            this.Dispose(false);
        }

        public void Dispose()
        {
            this.Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                this._deviceNodes.Clear();
            }

            this.DisconnectFromMachine();
        }

        private void EnumerateDevices()
        {
            this.DisconnectFromMachine();

            // local machine assumed
            if (Win32.CM_Connect_Machine(
                null, ref this._machineHandle) != 0)
            {
                return;
            }

            try
            {
                Win32.CM_Locate_DevNode_Ex(
                    ref this._rootDeviceHandle,
                    0,
                    0,
                    this._machineHandle);

                // recursive enumeration
                this._rootNode = new DeviceNode(
                    this._rootDeviceHandle,
                    null,
                    this._machineHandle);
            }
            finally
            {
                this.DisconnectFromMachine();

                if (this._rootNode != null)
                {
                    this._deviceNodes = this._rootNode
                        .Flatten(node => node.Children).ToList();
                }
            }
        }

        private void DisconnectFromMachine()
        {
            if (this._machineHandle != IntPtr.Zero)
            {
                Win32.CM_Disconnect_Machine(this._machineHandle);
                this._machineHandle = IntPtr.Zero;
            }
        }
    }

    public class DeviceNode : IDisposable
    {
        private readonly DeviceNode _parentDevice;
        private readonly List< DeviceNode > _children;
        private readonly IntPtr _deviceHandle;
        private readonly IntPtr _machineHandle;

        private readonly Dictionary< int, string >
            _deviceProperties;

        public DeviceNode ParentDevice
        {
            get
            {
                return _parentDevice;
            }
        }

        public Dictionary< int, string > DeviceProperties
        {
            get
            {
                return _deviceProperties;
            }
        }

        public List< DeviceNode > Children
        {
            get
            {
                return this._children;
            }
        }

        public Guid ClassGuid
        {
            get
            {
                string buffer =
                    this.GetProperty(Win32.DevRegProperty.ClassGuid);

                var guid = new Guid();

                if (buffer.Length >= 32)
                {
                    try
                    {
                        guid = new Guid(buffer);
                    }
                    catch
                    {
                        guid = new Guid();
                    }
                }

                return guid;
            }
        }

        public string Description
        {
            get
            {
                return
                    GetProperty(Win32.DevRegProperty.DeviceDescription);
            }
        }

        public string FriendlyName
        {
            get
            {
                return
                    GetProperty(Win32.DevRegProperty.FriendlyName);
            }
        }

        public string EnumeratorName
        {
            get
            {
                return
                    GetProperty(Win32.DevRegProperty.EnumeratorName);
            }
        }

        public string LocationInfo
        {
            get
            {
                return
                    GetProperty(Win32.DevRegProperty.LocationInfo);
            }
        }

        public DeviceNode(IntPtr deviceHandle, DeviceNode parentDevice)
            : this(
                    deviceHandle, 
                    parentDevice, 
                    parentDevice._machineHandle)
        {
        }

        public DeviceNode(
            IntPtr deviceHandle,
            DeviceNode parentDevice,
            IntPtr machineHandle)
        {
            _deviceProperties = new Dictionary< int, string >();
            _children = new List< DeviceNode >();

            _deviceHandle = deviceHandle;
            _machineHandle = machineHandle;
            _parentDevice = parentDevice;

            EnumerateDeviceProperties();
            EnumerateChildren();
        }

        private string GetProperty(
            Win32.DevRegProperty devRegProperty)
        {
            return GetProperty((int)devRegProperty);
        }

        private string GetProperty(int index)
        {
            string buffer;
            var result = this._deviceProperties
                .TryGetValue(index, out buffer);
            return result ? buffer : string.Empty;
        }

        private void EnumerateDeviceProperties()
        {
            for (var index = 0; index < 64; index++)
            {
                uint bufsize = 2048;

                IntPtr buffer = 
                    Marshal.AllocHGlobal((int)bufsize);

                var result = 
                    Win32.CM_Get_DevNode_Registry_Property_Ex(
                        _deviceHandle,
                        index,
                        IntPtr.Zero,
                        buffer,
                        ref bufsize,
                        0,
                        _machineHandle);

                var propertyString = result == 0
                    ? Marshal.PtrToStringAnsi(buffer) 
                    : string.Empty;

                _deviceProperties.Add(index, propertyString);

                Marshal.FreeHGlobal(buffer);
            }
        }

        private void EnumerateChildren()
        {
            IntPtr ptrFirstChild = IntPtr.Zero;

            if (Win32.CM_Get_Child_Ex(
                ref ptrFirstChild, 
                _deviceHandle, 
                0, 
                _machineHandle) != 0)
            {
                return;
            }

            var ptrChild = ptrFirstChild;
            var ptrSibling = IntPtr.Zero;

            do
            {
                var childDevice = new DeviceNode(ptrChild, this);
                _children.Add(childDevice);

                if (Win32.CM_Get_Sibling_Ex(
                    ref ptrSibling, 
                    ptrChild, 
                    0, 
                    _machineHandle) != 0) break;

                ptrChild = ptrSibling;
            }
            while (true);
        }

        public void Dispose()
        {
            this.Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                _deviceProperties.Clear();
            }
        }
    }

    internal static class LinqExtensionMethods
    {
        public static IEnumerable< T > Return< T >(T element)
        {
            yield return element;
        }

        public static IEnumerable< T > StartWith< T >(
            this IEnumerable< T > list, T element)
        {
            return Return(element).Concat(list);
        }

        public static IEnumerable< TEntity > Flatten< TEntity >(
            this TEntity element,
            Func< TEntity, IEnumerable< TEntity > > childSelector)
        {
            if (childSelector(element) != null)
                return childSelector(element)
                    .SelectMany(child => child.Flatten(childSelector))
                    .StartWith(element);

            var items = new List< TEntity > { element };
            return items;
        }
    }

    public static class Win32
    {
        // this is a partial list
        public static readonly
            Dictionary< Guid, string > DeviceClasses =
            new Dictionary< Guid, string >
            {
                { new Guid("{4d36e967-e325-11ce-bfc1-08002be10318}"), 
                    "Disk Drives" },
                { new Guid("{4d36e968-e325-11ce-bfc1-08002be10318}"), 
                    "Display Adapters" },
                { new Guid("{4d36e96b-e325-11ce-bfc1-08002be10318}"), 
                    "Keyboards" },
                { new Guid("{4d36e96f-e325-11ce-bfc1-08002be10318}"), 
                    "Mice" },
            };

        public enum DevRegProperty : uint
        {
            DeviceDescription = 1,
            HardwareId = 2,
            CompatibleIds = 3,
            Unused0 = 4,
            Service = 5,
            Unused1 = 6,
            Unused2 = 7,
            Class = 8,
            ClassGuid = 9,
            Driver = 0x0a,
            ConfigFlags = 0x0b,
            Mfg = 0x0c,
            FriendlyName = 0x0d,
            LocationInfo = 0x0e,
            PhysicalDeviceObjectName = 0x0f,
            Capabilities = 0x10,
            UiNumber = 0x11,
            UpperFilters = 0x12,
            LowerFilters = 0x13,
            BusTypeGuid = 0x014,
            LegacyBusType = 0x15,
            BusNumber = 0x16,
            EnumeratorName = 0x17,
        }

        [DllImport("kernel32.dll")]
        public static extern uint GetLogicalDrives();

        [DllImport("kernel32.dll")]
        public static extern int GetDriveType(
            [MarshalAs(UnmanagedType.LPStr)] string rootPathName);

        [DllImport("cfgmgr32.dll")]
        public static extern int CM_Connect_Machine(
            [MarshalAs(UnmanagedType.LPStr)] string uncServerName,
            ref IntPtr machineHandle);

        [DllImport("cfgmgr32.dll")]
        public static extern int CM_Disconnect_Machine(
            IntPtr machineHandle);

        [DllImport("cfgmgr32.dll")]
        public static extern int CM_Locate_DevNode_Ex(
            ref IntPtr deviceHandle,
            int deviceId,
            uint flags,
            IntPtr machineHandle);

        [DllImport("cfgmgr32.dll")]
        public static extern int CM_Get_Child_Ex(
            ref IntPtr childDeviceHandle,
            IntPtr parentDeviceHandle,
            uint flags,
            IntPtr machineHandle);

        [DllImport("cfgmgr32.dll")]
        public static extern int CM_Get_Sibling_Ex(
            ref IntPtr siblingDeviceHandle,
            IntPtr deviceHandle,
            uint flags,
            IntPtr machineHandle);

        [DllImport("cfgmgr32.dll")]
        public static extern int 
            CM_Get_DevNode_Registry_Property_Ex(
                IntPtr deviceHandle,
                int property,
                IntPtr regDataType,
                IntPtr outBuffer,
                ref uint size,
                int flags,
                IntPtr machineHandle);
    }
}

这篇关于C#中如何检查与USB集线器USB端口以及所使用的控制器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆