C#:USB设备枚举 --转自CSDN作者:Splash

时间:2021-01-20 19:05:10

(一)DeviceIoControl的PInvoke 

/* ----------------------------------------------------------
文件名称:DeviceIoControl.cs

作者:秦建辉

MSN:splashcn@msn.com
QQ:36748897

博客:
http://blog.csdn.net/jhqin

开发环境:
Visual Studio V2010
.NET Framework 4 Client Profile

版本历史:
V1.0 2011年10月10日
实现对DeviceIoControl接口的PInvoke

参考资料:
http://www.pinvoke.net/
------------------------------------------------------------
*/
using System;
using System.Runtime.InteropServices;

namespace Splash.IO.PORTS
{
#region ENUM
public enum USB_HUB_NODE : uint
{
UsbHub,
UsbMIParent
}

public enum USB_CONNECTION_STATUS
{
NoDeviceConnected,
DeviceConnected,
DeviceFailedEnumeration,
DeviceGeneralFailure,
DeviceCausedOvercurrent,
DeviceNotEnoughPower,
DeviceNotEnoughBandwidth,
DeviceHubNestedTooDeeply,
DeviceInLegacyHub
}

public enum USB_DEVICE_SPEED : byte
{
UsbLowSpeed,
// 低速USB 1.1
UsbFullSpeed, // 全速USB 1.1
UsbHighSpeed, // 高速USB 2.0
UsbSuperSpeed // 极速USB 3.0
}
#endregion

public partial class USB
{
internal const Int32 IOCTL_GET_HCD_DRIVERKEY_NAME = 0x220424;
internal const Int32 IOCTL_USB_GET_ROOT_HUB_NAME = 0x220408;
internal const Int32 IOCTL_USB_GET_NODE_CONNECTION_NAME = 0x220414;
internal const Int32 IOCTL_USB_GET_NODE_INFORMATION = 0x220408;
internal const Int32 IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX = 0x220448;
internal const Int32 IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION = 0x220410;

internal const Int32 MAXIMUM_USB_STRING_LENGTH = 255;
internal const Int32 USB_STRING_DESCRIPTOR_TYPE = 3;

[StructLayout(LayoutKind.Sequential, CharSet
= CharSet.Auto)]
internal struct USB_HCD_DRIVERKEY_NAME
{
public Int32 ActualLength;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst
= 256)]
public String Name;
}

#region USB_NODE_INFORMATION
[StructLayout(LayoutKind.Sequential, Pack
= 1)]
internal struct USB_HUB_DESCRIPTOR
{
public Byte bDescriptorLength;
public Byte bDescriptorType; // 描述符类型:0x29
public Byte bNumberOfPorts; // 支持的下游端口数目
public Int16 wHubCharacteristics; // 特征描述
public Byte bPowerOnToPowerGood; // 从端口加电到端口正常工作的时间间隔(以2ms为单位)
public Byte bHubControlCurrent; // 设备所需最大电流
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
public Byte[] bRemoveAndPowerMask; // 指示连接在集线器端口的设备是否可移走
}

[StructLayout(LayoutKind.Sequential)]
internal struct USB_HUB_INFORMATION
{
public USB_HUB_DESCRIPTOR HubDescriptor;
public Byte HubIsBusPowered;
}

[StructLayout(LayoutKind.Sequential)]
internal struct USB_MI_PARENT_INFORMATION
{
public Int32 NumberOfInterfaces;
};

[StructLayout(LayoutKind.Explicit)]
internal struct UsbNodeUnion
{
[FieldOffset(
0)]
public USB_HUB_INFORMATION HubInformation;
[FieldOffset(
0)]
public USB_MI_PARENT_INFORMATION MiParentInformation;
}

[StructLayout(LayoutKind.Sequential)]
internal struct USB_NODE_INFORMATION
{
public USB_HUB_NODE NodeType;
public UsbNodeUnion u;
}
#endregion

#region USB_NODE_CONNECTION_INFORMATION
[StructLayout(LayoutKind.Sequential, Pack
= 1)]
internal struct USB_DEVICE_DESCRIPTOR
{
public Byte bLength;
public Byte bDescriptorType;
public UInt16 bcdUSB;
public Byte bDeviceClass;
public Byte bDeviceSubClass;
public Byte bDeviceProtocol;
public Byte bMaxPacketSize0;
public UInt16 idVendor;
public UInt16 idProduct;
public UInt16 bcdDevice;
public Byte iManufacturer;
public Byte iProduct;
public Byte iSerialNumber;
public Byte bNumConfigurations;
}

[StructLayout(LayoutKind.Sequential, Pack
= 1)]
internal struct USB_ENDPOINT_DESCRIPTOR
{
public Byte bLength;
public Byte bDescriptorType;
public Byte bEndpointAddress;
public Byte bmAttributes;
public UInt16 wMaxPacketSize;
public Byte bInterval;
}

[StructLayout(LayoutKind.Sequential, Pack
= 1)]
internal struct USB_PIPE_INFO
{
public USB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
public UInt32 ScheduleOffset;
}

[StructLayout(LayoutKind.Sequential, Pack
= 1)]
internal struct USB_NODE_CONNECTION_INFORMATION_EX
{
public Int32 ConnectionIndex;
public USB_DEVICE_DESCRIPTOR DeviceDescriptor;
public Byte CurrentConfigurationValue;
public Byte Speed;
public Byte DeviceIsHub;
public Int16 DeviceAddress;
public Int32 NumberOfOpenPipes;
public USB_CONNECTION_STATUS ConnectionStatus;
[MarshalAs(UnmanagedType.ByValArray, SizeConst
= 32)]
public USB_PIPE_INFO[] PipeList;
}
#endregion

#region USB_DESCRIPTOR_REQUEST
[StructLayout(LayoutKind.Sequential)]
internal struct USB_SETUP_PACKET
{
public Byte bmRequest;
public Byte bRequest;
public UInt16 wValue;
public UInt16 wIndex;
public UInt16 wLength;
}

[StructLayout(LayoutKind.Sequential, CharSet
= CharSet.Auto)]
internal struct USB_STRING_DESCRIPTOR
{
public Byte bLength;
public Byte bDescriptorType;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst
= MAXIMUM_USB_STRING_LENGTH)]
public String bString;
}

[StructLayout(LayoutKind.Sequential)]
internal struct USB_DESCRIPTOR_REQUEST
{
public Int32 ConnectionIndex;
public USB_SETUP_PACKET SetupPacket;
public USB_STRING_DESCRIPTOR Data;
}
#endregion

#region USB_NODE_CONNECTION_DRIVERKEY_NAME
[StructLayout(LayoutKind.Sequential, CharSet
= CharSet.Auto)]
internal struct USB_NODE_CONNECTION_DRIVERKEY_NAME
{
public Int32 ConnectionIndex;
public Int32 ActualLength;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst
= MAXIMUM_USB_STRING_LENGTH)]
public String DriverKeyName;
}
#endregion

#region DeviceIoControl
[DllImport(
"kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
internal static extern Boolean DeviceIoControl(
IntPtr hFile,
Int32 dwIoControlCode,
IntPtr lpInBuffer,
Int32 nInBufferSize,
ref USB_HCD_DRIVERKEY_NAME lpOutBuffer,
Int32 nOutBufferSize,
out Int32 nBytesReturned,
IntPtr lpOverlapped
);

[DllImport(
"kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
internal static extern Boolean DeviceIoControl(
IntPtr hFile,
Int32 dwIoControlCode,
ref USB_NODE_INFORMATION lpInBuffer,
Int32 nInBufferSize,
ref USB_NODE_INFORMATION lpOutBuffer,
Int32 nOutBufferSize,
out Int32 lpBytesReturned,
IntPtr lpOverlapped
);

[DllImport(
"kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
internal static extern Boolean DeviceIoControl(
IntPtr hFile,
Int32 dwIoControlCode,
ref USB_NODE_CONNECTION_INFORMATION_EX lpInBuffer,
Int32 nInBufferSize,
ref USB_NODE_CONNECTION_INFORMATION_EX lpOutBuffer,
Int32 nOutBufferSize,
out Int32 lpBytesReturned,
IntPtr lpOverlapped
);

[DllImport(
"kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
internal static extern Boolean DeviceIoControl(
IntPtr hFile,
Int32 dwIoControlCode,
ref USB_DESCRIPTOR_REQUEST lpInBuffer,
Int32 nInBufferSize,
ref USB_DESCRIPTOR_REQUEST lpOutBuffer,
Int32 nOutBufferSize,
out Int32 lpBytesReturned,
IntPtr lpOverlapped
);

[DllImport(
"kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
internal static extern Boolean DeviceIoControl(
IntPtr hFile,
Int32 dwIoControlCode,
ref USB_NODE_CONNECTION_DRIVERKEY_NAME lpInBuffer,
Int32 nInBufferSize,
ref USB_NODE_CONNECTION_DRIVERKEY_NAME lpOutBuffer,
Int32 nOutBufferSize,
out Int32 lpBytesReturned,
IntPtr lpOverlapped
);
#endregion
}
}

(二)设备枚举API 

/* ----------------------------------------------------------
文件名称:WDKUsbEnum.cs

作者:秦建辉

MSN:splashcn@msn.com
QQ:36748897

博客:
http://blog.csdn.net/jhqin

开发环境:
Visual Studio V2010
.NET Framework 4 Client Profile

版本历史:
V1.0 2011年10月10日
基于WDK枚举USB设备
------------------------------------------------------------
*/
using System;
using System.Collections.Generic;
using System.Management;
using System.Runtime.InteropServices;
using System.Text;

namespace Splash.IO.PORTS
{
/// <summary>
/// USB主控制器信息
/// </summary>
public struct HostControllerInfo
{
public String PNPDeviceID; // 设备ID
public String Name; // 设备名称
}

/// <summary>
/// USB Hub信息
/// </summary>
public struct UsbHubInfo
{
public String PNPDeviceID; // 设备ID
public String Name; // 设备名称
public String Status; // 设备状态
}

/// <summary>
/// USB HUB节点信息
/// </summary>
public struct UsbNodeInformation
{
public String DevicePath; // 设备路径
public String PNPDeviceID; // 设备ID
public String Name; // 设备名称

public USB_HUB_NODE NodeType; // 节点类型

// USB_HUB_INFORMATION
public Boolean HubIsBusPowered; // 供电方式:true-总线供电 false-独立供电
public Int32 NumberOfPorts; // 端口数
public Int16 HubCharacteristics; // 特征描述
public Byte PowerOnToPowerGood; // 从端口加电到端口正常工作的时间间隔(以2ms为单位)
public Byte HubControlCurrent; // 设备所需最大电流

// USB_MI_PARENT_INFORMATION
public Int32 NumberOfInterfaces; // 接口数
}

/// <summary>
/// USB设备描述符
/// </summary>
public struct UsbDeviceDescriptor
{
public Byte bDescriptorType; // 描述符类型 USB_DEVICE_DESCRIPTOR_TYPE
public String UsbVersion; // USB规格版本号
public Byte bDeviceClass; // 设备类型
public Byte bDeviceSubClass; // 设备子类型
public Byte bDeviceProtocol; // 设备协议
public Byte bMaxPacketSize0; // 最大封包大小
public UInt16 idVendor; // VID
public UInt16 idProduct; // PID
public String DeviceVersion; // 设备版本号
public String Manufacturer; // 制造商
public String Product; // 产品描述
public String SerialNumber; // 序列号
public Byte bNumConfigurations; // 配置总数
}

/// <summary>
/// USB管道信息
/// </summary>
public struct UsbPipeInfo
{
public UInt32 ScheduleOffset;
public Byte bDescriptorType;
public Byte bEndpointAddress;
public Byte bmAttributes;
public UInt16 wMaxPacketSize;
public Byte bInterval;
}

/// <summary>
/// USB节点连接信息
/// </summary>
public struct UsbNodeConnectionInformation
{
public String DevicePath; // 设备路径
public Int32 ConnectionIndex; // 端口号

public UsbDeviceDescriptor DeviceDescriptor;

public Byte CurrentConfigurationValue; // 当前设备配置
public Byte Speed; // 设备速度
public Boolean DeviceIsHub; // 是否是集线器
public Int32 DeviceAddress; // 设备地址
public Int32 NumberOfOpenPipes; // 管道数
public USB_CONNECTION_STATUS ConnectionStatus; // 连接状态

public List<UsbPipeInfo> PipeList; // 管道信息
}

/// <summary>
/// USB设备枚举
/// </summary>
public partial class USB
{
#region HostController
/// <summary>
/// USB主控制器
/// </summary>
public static HostControllerInfo[] AllHostControllers
{
get
{
List
<HostControllerInfo> HostControllers = new List<HostControllerInfo>();

// 获取USB控制器及其相关联的设备实体
ManagementObjectCollection MOC = new ManagementObjectSearcher("SELECT * FROM Win32_USBController").Get();
if (MOC != null)
{
foreach (ManagementObject MO in MOC)
{
HostControllerInfo Element;
Element.PNPDeviceID
= MO["PNPDeviceID"] as String; // 设备ID
Element.Name = MO["Name"] as String; // 设备描述
HostControllers.Add(Element);
}
}

if (HostControllers.Count == 0) return null; else return HostControllers.ToArray();
}
}

/// <summary>
/// 获取驱动键名
/// </summary>
/// <param name="PNPDeviceID">USB主控制器设备ID</param>
/// <returns>获取设备驱动在注册表HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class下的路径</returns>
public static String GetHcdDriverKeyName(String PNPDeviceID)
{
if (String.IsNullOrEmpty(PNPDeviceID)) return null;

// 打开设备
IntPtr hHCDev = Kernel32.CreateFile(
"\\\\.\\" + PNPDeviceID.Replace('\\', '#') + "#{3ABF6F2D-71C4-462A-8A92-1E6861E6AF27}",
NativeFileAccess.GENERIC_WRITE,
NativeFileShare.FILE_SHARE_WRITE,
IntPtr.Zero,
NativeFileMode.OPEN_EXISTING,
IntPtr.Zero,
IntPtr.Zero);
if (hHCDev == Kernel32.INVALID_HANDLE_VALUE) return null;

// 获取驱动键名
Int32 nBytesReturned;
USB_HCD_DRIVERKEY_NAME Buffer
= new USB_HCD_DRIVERKEY_NAME();
Boolean Status
= DeviceIoControl(hHCDev,
IOCTL_GET_HCD_DRIVERKEY_NAME,
IntPtr.Zero,
0,
ref Buffer,
Marshal.SizeOf(Buffer),
out nBytesReturned,
IntPtr.Zero);

// 关闭设备
Kernel32.CloseHandle(hHCDev);
return Status ? Buffer.Name : null;
}
#endregion

#region USBHUB
/// <summary>
/// USB Hub信息集合
/// </summary>
public static UsbHubInfo[] AllUsbHubs
{
get
{
List
<UsbHubInfo> UsbHubs = new List<UsbHubInfo>();

// 获取USB控制器及其相关联的设备实体
ManagementObjectCollection MOC = new ManagementObjectSearcher("SELECT * FROM Win32_USBHub").Get();
if (MOC != null)
{
foreach (ManagementObject MO in MOC)
{
UsbHubInfo Element;
Element.PNPDeviceID
= MO["PNPDeviceID"] as String; // 设备ID
Element.Name = MO["Name"] as String; // 设备描述
Element.Status = MO["Status"] as String; // 设备状态
UsbHubs.Add(Element);
}
}

if (UsbHubs.Count == 0) return null; else return UsbHubs.ToArray();
}
}

/// <summary>
/// USB ROOT HUB设备路径
/// </summary>
/// <param name="PNPDeviceID">USB主控制器设备ID</param>
/// <returns>USB ROOT HUB设备路径</returns>
public static String GetUsbRootHubPath(String PNPDeviceID)
{
if (String.IsNullOrEmpty(PNPDeviceID)) return null;

// 打开设备
IntPtr hHCDev = Kernel32.CreateFile(
"\\\\.\\" + PNPDeviceID.Replace('\\', '#') + "#{3ABF6F2D-71C4-462A-8A92-1E6861E6AF27}",
NativeFileAccess.GENERIC_WRITE,
NativeFileShare.FILE_SHARE_WRITE,
IntPtr.Zero,
NativeFileMode.OPEN_EXISTING,
IntPtr.Zero,
IntPtr.Zero);
if (hHCDev == Kernel32.INVALID_HANDLE_VALUE) return null;

// 获取USB ROOT HUB名称
Int32 nBytesReturned;
USB_HCD_DRIVERKEY_NAME Buffer
= new USB_HCD_DRIVERKEY_NAME();
Boolean Status
= DeviceIoControl(hHCDev,
IOCTL_USB_GET_ROOT_HUB_NAME,
IntPtr.Zero,
0,
ref Buffer,
Marshal.SizeOf(Buffer),
out nBytesReturned,
IntPtr.Zero);

// 关闭设备
Kernel32.CloseHandle(hHCDev);
return Status ? Buffer.Name : null;
}

/// <summary>
/// USB HUB设备名称
/// </summary>
/// <param name="DevicePath">设备路径</param>
/// <returns>设备名称</returns>
public static String GetUsbHubName(String DevicePath)
{
if (String.IsNullOrEmpty(DevicePath)) return null;

// 从设备路径中提取设备ID
String DeviceID = DevicePath.Substring(0, DevicePath.LastIndexOf('#')).Replace('#', '_');

// 从Win32_USBHub获取设备描述
ManagementObjectCollection MOC = new ManagementObjectSearcher("SELECT * FROM Win32_USBHub WHERE DeviceID LIKE '" + DeviceID + "'").Get();
if (MOC != null)
{
foreach (ManagementObject MO in MOC)
{
return MO["Name"] as String;
}
}

return null;
}

/// <summary>
/// 获取USB HUB节点信息
/// </summary>
/// <param name="DevicePath">USB HUB设备路径</param>
/// <returns>节点信息</returns>
public static UsbNodeInformation[] GetUsbNodeInformation(String DevicePath)
{
if (String.IsNullOrEmpty(DevicePath)) return null;

// 打开设备文件
IntPtr hHubDevice = Kernel32.CreateFile(
"\\\\.\\" + DevicePath,
NativeFileAccess.GENERIC_WRITE,
NativeFileShare.FILE_SHARE_WRITE,
IntPtr.Zero,
NativeFileMode.OPEN_EXISTING,
IntPtr.Zero,
IntPtr.Zero);
if (hHubDevice == Kernel32.INVALID_HANDLE_VALUE) return null;

// 查询节点信息
Int32 nBytesReturned;
USB_NODE_INFORMATION Buffer
= new USB_NODE_INFORMATION();
Boolean Status
= DeviceIoControl(hHubDevice,
IOCTL_USB_GET_NODE_INFORMATION,
ref Buffer,
Marshal.SizeOf(Buffer),
ref Buffer,
Marshal.SizeOf(Buffer),
out nBytesReturned,
IntPtr.Zero);

// 关闭设备文件
Kernel32.CloseHandle(hHubDevice);
if (!Status) return null;

UsbNodeInformation Node
= new UsbNodeInformation();
Node.NodeType
= Buffer.NodeType; // 节点类型
Node.PNPDeviceID = DevicePath.Substring(0, DevicePath.LastIndexOf('#')).Replace('#', '\\'); // 设备ID
Node.DevicePath = DevicePath; // 设备路径
Node.Name = GetUsbHubName(DevicePath); // 设备名称
if (Buffer.NodeType == USB_HUB_NODE.UsbHub)
{
Node.NumberOfPorts
= Buffer.u.HubInformation.HubDescriptor.bNumberOfPorts; // 端口数
Node.HubIsBusPowered = Convert.ToBoolean(Buffer.u.HubInformation.HubIsBusPowered); // 供电方式
Node.HubCharacteristics = Buffer.u.HubInformation.HubDescriptor.wHubCharacteristics;
Node.PowerOnToPowerGood
= Buffer.u.HubInformation.HubDescriptor.bPowerOnToPowerGood;
Node.HubControlCurrent
= Buffer.u.HubInformation.HubDescriptor.bHubControlCurrent;
}
else
{
Node.NumberOfInterfaces
= Buffer.u.MiParentInformation.NumberOfInterfaces; // 接口数
}

return new UsbNodeInformation[1] { Node };
}
#endregion

#region NODECONNECTION
/// <summary>
/// 获取USB节点连接信息
/// </summary>
/// <param name="DevicePath">设备路径</param>
/// <param name="NumberOfPorts">端口总数</param>
/// <returns>USB节点信息连接信息集合</returns>
public static UsbNodeConnectionInformation[] GetUsbNodeConnectionInformation(String DevicePath, Int32 NumberOfPorts)
{
if (String.IsNullOrEmpty(DevicePath)) return null;

// 打开设备文件
IntPtr hHubDevice = Kernel32.CreateFile(
"\\\\.\\" + DevicePath,
NativeFileAccess.GENERIC_WRITE,
NativeFileShare.FILE_SHARE_WRITE,
IntPtr.Zero,
NativeFileMode.OPEN_EXISTING,
IntPtr.Zero,
IntPtr.Zero);
if (hHubDevice == Kernel32.INVALID_HANDLE_VALUE) return null;

List
<UsbNodeConnectionInformation> NodeCollection = new List<UsbNodeConnectionInformation>();

// 枚举端口
USB_NODE_CONNECTION_INFORMATION_EX Buffer = new USB_NODE_CONNECTION_INFORMATION_EX();
for (Int32 ConnectionIndex = 1; ConnectionIndex <= NumberOfPorts; ConnectionIndex++)
{
// 查询节点信息
Int32 nBytesReturned;
Buffer.ConnectionIndex
= ConnectionIndex;
Boolean Status
= DeviceIoControl(hHubDevice,
IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX,
ref Buffer,
Marshal.SizeOf(Buffer),
ref Buffer,
Marshal.SizeOf(Buffer),
out nBytesReturned,
IntPtr.Zero);
if (Status)
{
// 确定语言ID
UInt16 LanguageID = SelectLanguageID(hHubDevice, ConnectionIndex);

// 提取信息
UsbNodeConnectionInformation Node = new UsbNodeConnectionInformation();

Node.DevicePath
= DevicePath;
Node.ConnectionIndex
= Buffer.ConnectionIndex;
Node.ConnectionStatus
= Buffer.ConnectionStatus;
if (Buffer.ConnectionStatus == USB_CONNECTION_STATUS.DeviceConnected)
{
Node.CurrentConfigurationValue
= Buffer.CurrentConfigurationValue;
Node.Speed
= Buffer.Speed;
Node.DeviceIsHub
= Convert.ToBoolean(Buffer.DeviceIsHub);
Node.DeviceAddress
= Buffer.DeviceAddress;
Node.NumberOfOpenPipes
= Buffer.NumberOfOpenPipes;

// 设备描述符
Node.DeviceDescriptor.bDescriptorType = Buffer.DeviceDescriptor.bDescriptorType;
Node.DeviceDescriptor.bDeviceClass
= Buffer.DeviceDescriptor.bDeviceClass;
Node.DeviceDescriptor.bDeviceSubClass
= Buffer.DeviceDescriptor.bDeviceSubClass;
Node.DeviceDescriptor.bDeviceProtocol
= Buffer.DeviceDescriptor.bDeviceProtocol;

Node.DeviceDescriptor.UsbVersion
= BcdVersionToString(Buffer.DeviceDescriptor.bcdUSB); // USB版本号
Node.DeviceDescriptor.DeviceVersion = BcdVersionToString(Buffer.DeviceDescriptor.bcdDevice); // 设备版本号

Node.DeviceDescriptor.idVendor
= Buffer.DeviceDescriptor.idVendor; // 厂商标识
Node.DeviceDescriptor.idProduct = Buffer.DeviceDescriptor.idProduct; // 产品标识

if (LanguageID != 0)
{
if (Buffer.DeviceDescriptor.iSerialNumber != 0)
{
// 序列号
Node.DeviceDescriptor.SerialNumber = GetStringDescriptor(hHubDevice,
Buffer.ConnectionIndex,
Buffer.DeviceDescriptor.iSerialNumber,
LanguageID);
}

if (Buffer.DeviceDescriptor.iManufacturer != 0)
{
// 制造商名称
Node.DeviceDescriptor.Manufacturer = GetStringDescriptor(hHubDevice,
Buffer.ConnectionIndex,
Buffer.DeviceDescriptor.iManufacturer,
LanguageID);
}

if (Buffer.DeviceDescriptor.iProduct != 0)
{
// 产品名称
Node.DeviceDescriptor.Product = GetStringDescriptor(hHubDevice,
Buffer.ConnectionIndex,
Buffer.DeviceDescriptor.iProduct,
LanguageID);
}
}

Node.DeviceDescriptor.bMaxPacketSize0
= Buffer.DeviceDescriptor.bMaxPacketSize0;
Node.DeviceDescriptor.bNumConfigurations
= Buffer.DeviceDescriptor.bNumConfigurations;

// 管道信息
Node.PipeList = new List<UsbPipeInfo>();
for (Int32 PipeIndex = 0; PipeIndex < Buffer.NumberOfOpenPipes; PipeIndex++)
{
UsbPipeInfo PipeInfo;

PipeInfo.ScheduleOffset
= Buffer.PipeList[PipeIndex].ScheduleOffset;
PipeInfo.bDescriptorType
= Buffer.PipeList[PipeIndex].EndpointDescriptor.bDescriptorType;
PipeInfo.bEndpointAddress
= Buffer.PipeList[PipeIndex].EndpointDescriptor.bEndpointAddress;
PipeInfo.bmAttributes
= Buffer.PipeList[PipeIndex].EndpointDescriptor.bmAttributes;
PipeInfo.wMaxPacketSize
= Buffer.PipeList[PipeIndex].EndpointDescriptor.wMaxPacketSize;
PipeInfo.bInterval
= Buffer.PipeList[PipeIndex].EndpointDescriptor.bInterval;

Node.PipeList.Add(PipeInfo);
}
}

NodeCollection.Add(Node);
}
}

// 关闭设备文件
Kernel32.CloseHandle(hHubDevice);

// 返回结果
if (NodeCollection.Count == 0)
return null;
else
return NodeCollection.ToArray();
}

/// <summary>
/// 获取字符串描述符
/// </summary>
/// <param name="hHubDevice">USB Hub设备句柄</param>
/// <param name="ConnectionIndex">连接索引号</param>
/// <param name="DescriptorIndex">描述符索引号</param>
/// <param name="LanguageID">语言ID</param>
/// <returns>字符串描述符</returns>
public static String GetStringDescriptor(IntPtr hHubDevice, Int32 ConnectionIndex, Byte DescriptorIndex, UInt16 LanguageID)
{
USB_DESCRIPTOR_REQUEST Buffer
= new USB_DESCRIPTOR_REQUEST();
Buffer.ConnectionIndex
= ConnectionIndex;
Buffer.SetupPacket.wValue
= (UInt16)((USB_STRING_DESCRIPTOR_TYPE << 8) | DescriptorIndex);
Buffer.SetupPacket.wIndex
= LanguageID;
Buffer.SetupPacket.wLength
= MAXIMUM_USB_STRING_LENGTH;
Int32 nBytesReturned;
Boolean Status
= DeviceIoControl(hHubDevice,
IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION,
ref Buffer,
Marshal.SizeOf(Buffer),
ref Buffer,
Marshal.SizeOf(Buffer),
out nBytesReturned,
IntPtr.Zero);
if (Status)
return Buffer.Data.bString;
else
return null;
}

/// <summary>
/// 选择语言ID
/// </summary>
/// <param name="hHubDevice">USB Hub设备句柄</param>
/// <param name="ConnectionIndex">连接索引号</param>
/// <returns></returns>
public static UInt16 SelectLanguageID(IntPtr hHubDevice, Int32 ConnectionIndex)
{
// 获取支持的语言列表
String SupportedLanguagesString = GetStringDescriptor(hHubDevice, ConnectionIndex, 0, 0);
if(String.IsNullOrEmpty(SupportedLanguagesString))return 0;

UInt16 UserDefaultUILanguage
= Splash.Environment.UserDefaultUILanguage;
if(SupportedLanguagesString.IndexOf(Convert.ToChar(UserDefaultUILanguage)) != -1)
{
// 用户缺省界面语言
return UserDefaultUILanguage;
}
else if(SupportedLanguagesString.IndexOf(Convert.ToChar(0x0409)) != -1)
{
// 美国英语 0x0409
return 0x0409;
}
else
{
// 第一个可选择的LANGID
return Convert.ToUInt16(SupportedLanguagesString[0]);
}
}
#endregion

#region EXTERNALHUB
/// <summary>
/// 获取外接Hub设备路径
/// </summary>
/// <param name="ParentDevicePath">上层Hub设备路径</param>
/// <param name="ConnectionIndex">连接索引号</param>
/// <returns>外接Hub设备路径</returns>
public static String GetExternalHubPath(String ParentDevicePath, Int32 ConnectionIndex)
{
if (String.IsNullOrEmpty(ParentDevicePath)) return null;

// 打开设备文件
IntPtr hParentHubDevice = Kernel32.CreateFile(
"\\\\.\\" + ParentDevicePath,
NativeFileAccess.GENERIC_WRITE,
NativeFileShare.FILE_SHARE_WRITE,
IntPtr.Zero,
NativeFileMode.OPEN_EXISTING,
IntPtr.Zero,
IntPtr.Zero);
if (hParentHubDevice == Kernel32.INVALID_HANDLE_VALUE) return null;

USB_NODE_CONNECTION_DRIVERKEY_NAME Buffer
= new USB_NODE_CONNECTION_DRIVERKEY_NAME();
Buffer.ConnectionIndex
= ConnectionIndex;
Int32 nBytesReturned;
Boolean Status
= DeviceIoControl(hParentHubDevice,
IOCTL_USB_GET_NODE_CONNECTION_NAME,
ref Buffer,
Marshal.SizeOf(Buffer),
ref Buffer,
Marshal.SizeOf(Buffer),
out nBytesReturned,
IntPtr.Zero);

// 关闭设备文件
Kernel32.CloseHandle(hParentHubDevice);

if (Status)
return Buffer.DriverKeyName;
else
return null;
}

/// <summary>
/// 获取外接Hub设备路径
/// </summary>
/// <param name="hParentHubDevice">上层Hub设备句柄</param>
/// <param name="ConnectionIndex">连接索引号</param>
/// <returns>外接Hub设备路径</returns>
public static String GetExternalHubPath(IntPtr hParentHubDevice, Int32 ConnectionIndex)
{
if (hParentHubDevice == IntPtr.Zero || ConnectionIndex <= 0) return null;

USB_NODE_CONNECTION_DRIVERKEY_NAME Buffer
= new USB_NODE_CONNECTION_DRIVERKEY_NAME();
Buffer.ConnectionIndex
= ConnectionIndex;
Int32 nBytesReturned;
Boolean Status
= DeviceIoControl(hParentHubDevice,
IOCTL_USB_GET_NODE_CONNECTION_NAME,
ref Buffer,
Marshal.SizeOf(Buffer),
ref Buffer,
Marshal.SizeOf(Buffer),
out nBytesReturned,
IntPtr.Zero);

if (Status)
return Buffer.DriverKeyName;
else
return null;
}
#endregion

#region BCDVERSION
/// <summary>
/// 版本BCD编码转字符串
/// </summary>
/// <param name="bcd">版本BCD编码</param>
/// <returns>版本字符串</returns>
private static String BcdVersionToString(UInt16 bcd)
{
StringBuilder sb
= new StringBuilder(5);

// 主版本号
Int32 BIT4 = (bcd >> 12) & 0x0F;
if (BIT4 != 0) sb.Append(BIT4.ToString());

BIT4
= (bcd >> 8) & 0x0F;
sb.Append(BIT4.ToString());

sb.Append(
".");

// 子版本号
BIT4 = (bcd >> 4) & 0x0F;
sb.Append(BIT4.ToString());

BIT4
= bcd & 0x0F;
if (BIT4 != 0) sb.Append(BIT4.ToString());

return sb.ToString();
}
#endregion
}
}

(三)输出枚举信息到XML文档 

/* ----------------------------------------------------------
文件名称:UsbEnumXML.cs

作者:秦建辉

MSN:splashcn@msn.com
QQ:36748897

博客:
http://blog.csdn.net/jhqin

开发环境:
Visual Studio V2010
.NET Framework 4 Client Profile

版本历史:
V1.0 2011年10月28日
将USB设备枚举信息导出为XML文档
------------------------------------------------------------
*/
using System;
using System.Collections.Generic;
using System.Xml.Linq;

namespace Splash.IO.PORTS
{
/// <summary>
/// 将USB设备信息写入XML文件
/// </summary>
public partial class USB
{
/// <summary>
/// 将USB设备枚举信息导出为XML文档
/// </summary>
/// <param name="xmlFileName">保存的XML文件名</param>
/// <returns>
/// true:成功
/// false:失败
/// </returns>
public static Boolean EnumUsbToXML(String xmlFileName)
{
// 创建根节点
XElement RootNode = new XElement("Computer",
new XAttribute("MachineName", System.Environment.MachineName));

// 深度遍历主控制器
HostControllerInfo[] HostControllersCollection = USB.AllHostControllers;
if (HostControllersCollection != null)
{
Int32 ControllerIndex
= 1;
foreach (HostControllerInfo item in HostControllersCollection)
{
// 创建主控制器节点
String PNPDeviceID = item.PNPDeviceID;
String HcdDriverKeyName
= USB.GetHcdDriverKeyName(PNPDeviceID);
XElement HostControllerNode
= new XElement("HostController" + ControllerIndex,
new XAttribute("Name", item.Name), // 设备名称
new XAttribute("PNPDeviceID", PNPDeviceID), // 设备ID
new XAttribute("HcdDriverKeyName", HcdDriverKeyName) // 驱动键名
);
RootNode.Add(HostControllerNode);
ControllerIndex
++;

// 创建根集线器节点
String RootHubPath = USB.GetUsbRootHubPath(PNPDeviceID);
AddHubNode(HostControllerNode, RootHubPath,
"RootHub");
}
}

// 创建XML文档
XDocument xmlTree = new XDocument(RootNode);

// 存储文件,序列化时对XML进行格式设置(缩进)
xmlTree.Save(xmlFileName, SaveOptions.None);
return true;
}

/// <summary>
/// 增加集线器节点
/// </summary>
/// <param name="ParentNode">父节点</param>
/// <param name="HubPath">集线器路径</param>
private static void AddHubNode(XElement ParentNode, String HubPath, String HubNodeName)
{
UsbNodeInformation[] NodeInfoCollection
= USB.GetUsbNodeInformation(HubPath);
if (NodeInfoCollection != null)
{
USB_HUB_NODE NodeType
= NodeInfoCollection[0].NodeType;
XElement HubNode
= new XElement(HubNodeName,
new XAttribute("Name", NodeInfoCollection[0].Name),
new XAttribute("PNPDeviceID", NodeInfoCollection[0].PNPDeviceID),
new XAttribute("Path", NodeInfoCollection[0].DevicePath),
new XAttribute("NodeType", NodeType)
);

if (NodeType == USB_HUB_NODE.UsbHub)
{
Int32 NumberOfPorts
= NodeInfoCollection[0].NumberOfPorts;
HubNode.Add(
new XAttribute("NumberOfPorts", NumberOfPorts),
new XAttribute("HubIsBusPowered", NodeInfoCollection[0].HubIsBusPowered),
new XAttribute("HubCharacteristics", "0x" + NodeInfoCollection[0].HubCharacteristics.ToString("X4")),
new XAttribute("PowerOnToPowerGood", NodeInfoCollection[0].PowerOnToPowerGood),
new XAttribute("HubControlCurrent", NodeInfoCollection[0].HubControlCurrent)
);

// 深度遍历端口
UsbNodeConnectionInformation[] NodeConnectionInfoCollection = USB.GetUsbNodeConnectionInformation(HubPath, NumberOfPorts);
if (NodeConnectionInfoCollection != null)
{
foreach (UsbNodeConnectionInformation NodeConnectionInfo in NodeConnectionInfoCollection)
{
// 增加端口节点
AddPortNode(HubNode, NodeConnectionInfo);
}
}
}
else
{
HubNode.Add(
"NumberOfInterfaces", NodeInfoCollection[0].NumberOfInterfaces);
}

ParentNode.Add(HubNode);
}
}

/// <summary>
/// 增加端口节点
/// </summary>
/// <param name="HubNode">集线器节点</param>
/// <param name="NodeConnectionInfo">USB设备节点连接信息</param>
private static void AddPortNode(XElement HubNode, UsbNodeConnectionInformation NodeConnectionInfo)
{
String DevicePath
= NodeConnectionInfo.DevicePath;
Int32 ConnectionIndex
= NodeConnectionInfo.ConnectionIndex;
USB_CONNECTION_STATUS ConnectionStatus
= NodeConnectionInfo.ConnectionStatus;

// 创建端口节点
XElement PortNode = new XElement("Port" + ConnectionIndex,
new XAttribute("DevicePath", DevicePath),
new XAttribute("ConnectionIndex", ConnectionIndex),
new XAttribute("ConnectionStatus", NodeConnectionInfo.ConnectionStatus)
);

if (ConnectionStatus == USB_CONNECTION_STATUS.DeviceConnected)
{
Boolean DeviceIsHub
= NodeConnectionInfo.DeviceIsHub;
PortNode.Add(
new XAttribute("DeviceIsHub", DeviceIsHub),
new XAttribute("CurrentConfigurationValue", NodeConnectionInfo.CurrentConfigurationValue),
new XAttribute("Speed", NodeConnectionInfo.Speed),
new XAttribute("DeviceAddress", NodeConnectionInfo.DeviceAddress),
new XAttribute("NumberOfOpenPipes", NodeConnectionInfo.NumberOfOpenPipes)
);

// 设备描述符信息
AddDeviceDescriptorNode(PortNode, ref NodeConnectionInfo.DeviceDescriptor);

// 管道信息
AddPipeInfoNode(PortNode, ref NodeConnectionInfo.PipeList);

// 外部集线器
if (DeviceIsHub)
{
// 获取外部Hub设备路径
String ExternalHubPath = GetExternalHubPath(DevicePath, ConnectionIndex);

// 增加外部集线器节点
AddHubNode(PortNode, ExternalHubPath, "ExternalHub");
}
}

HubNode.Add(PortNode);
}

/// <summary>
/// 增加设备描述符节点
/// </summary>
/// <param name="PortNode"></param>
/// <param name="DeviceDescriptor"></param>
private static void AddDeviceDescriptorNode(XElement PortNode, ref UsbDeviceDescriptor DeviceDescriptor)
{
XElement DeviceDescriptorNode
= new XElement("DeviceDescriptor",
new XAttribute("bDescriptorType", "0x" + DeviceDescriptor.bDescriptorType.ToString("X2")),
new XAttribute("UsbVersion", DeviceDescriptor.UsbVersion),
new XAttribute("bDeviceClass", "0x" + DeviceDescriptor.bDeviceClass.ToString("X2")),
new XAttribute("bDeviceSubClass", "0x" + DeviceDescriptor.bDeviceSubClass.ToString("X2")),
new XAttribute("bDeviceProtocol", "0x" + DeviceDescriptor.bDeviceProtocol.ToString("X2")),
new XAttribute("bMaxPacketSize0", DeviceDescriptor.bMaxPacketSize0),
new XAttribute("bNumConfigurations", DeviceDescriptor.bNumConfigurations)
);

if (DeviceDescriptor.idVendor != 0)
{
DeviceDescriptorNode.Add(
new XAttribute("idVendor", "0x" + DeviceDescriptor.idVendor.ToString("X4")));
}

if (DeviceDescriptor.idProduct != 0)
{
DeviceDescriptorNode.Add(
new XAttribute("idProduct", "0x" + DeviceDescriptor.idProduct.ToString("X4")));
}

if (!String.IsNullOrEmpty(DeviceDescriptor.DeviceVersion))
{
DeviceDescriptorNode.Add(
new XAttribute("DeviceVersion", DeviceDescriptor.DeviceVersion));
}

if (!String.IsNullOrEmpty(DeviceDescriptor.Manufacturer))
{
DeviceDescriptorNode.Add(
new XAttribute("Manufacturer", DeviceDescriptor.Manufacturer));
}

if (!String.IsNullOrEmpty(DeviceDescriptor.Product))
{
DeviceDescriptorNode.Add(
new XAttribute("Product", DeviceDescriptor.Product));
}

if (!String.IsNullOrEmpty(DeviceDescriptor.SerialNumber))
{
DeviceDescriptorNode.Add(
new XAttribute("SerialNumber", DeviceDescriptor.SerialNumber));
}

PortNode.Add(DeviceDescriptorNode);
}

/// <summary>
/// 增加管道信息节点
/// </summary>
/// <param name="PortNode">端口节点</param>
/// <param name="PipeList">管道信息列表</param>
private static void AddPipeInfoNode(XElement PortNode, ref List<UsbPipeInfo> PipeList)
{
if(PipeList != null)
{
XElement PipeListNode
= new XElement("PipeList");
Int32 PipeIndex
= 1;
foreach(UsbPipeInfo item in PipeList)
{
XElement PipeInfoNode
= new XElement("Pipe" + PipeIndex,
new XAttribute("ScheduleOffset", item.ScheduleOffset),
new XAttribute("bDescriptorType", "0x" + item.bDescriptorType.ToString("X2")),
new XAttribute("bEndpointAddress", "0x" + item.bEndpointAddress.ToString("X2")),
new XAttribute("bmAttributes", "0x" + item.bmAttributes.ToString("X2")),
new XAttribute("wMaxPacketSize", item.wMaxPacketSize),
new XAttribute("bInterval", item.bInterval)
);

PipeListNode.Add(PipeInfoNode);
PipeIndex
++;
}

PortNode.Add(PipeListNode);
}
}
}
}

(四)Kernel32的PInvoke 

/* ----------------------------------------------------------
文件名称:Kernel32.cs

作者:秦建辉

MSN:splashcn@msn.com
QQ:36748897

博客:
http://blog.csdn.net/jhqin

开发环境:
Visual Studio V2010
.NET Framework 4 Client Profile

版本历史:
V1.0 2011年09月05日
实现对Kernel32.dll接口的PInvoke

参考资料:
http://www.pinvoke.net/
------------------------------------------------------------
*/
using System;
using System.Runtime.InteropServices;
using System.Security;

namespace Splash
{
#region Kernel32
[SuppressUnmanagedCodeSecurity]
internal static class Kernel32
{
/// <summary>
/// 无效的文件句柄
/// </summary>
public static readonly IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);

#region CreateFile
[DllImport(
"kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr CreateFile(
String fileName,
[MarshalAs(UnmanagedType.U4)] NativeFileAccess fileAccess,
[MarshalAs(UnmanagedType.U4)] NativeFileShare fileShare,
IntPtr securityAttributes,
[MarshalAs(UnmanagedType.U4)] NativeFileMode creationDisposition,
NativeFileFlag flags,
IntPtr template
);

[DllImport(
"kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr CreateFile(
String fileName,
[MarshalAs(UnmanagedType.U4)] NativeFileAccess fileAccess,
[MarshalAs(UnmanagedType.U4)] NativeFileShare fileShare,
IntPtr securityAttributes,
[MarshalAs(UnmanagedType.U4)] NativeFileMode creationDisposition,
IntPtr flags,
IntPtr template
);
#endregion

[DllImport(
"kernel32.dll", SetLastError = true)]
[
return: MarshalAs(UnmanagedType.Bool)]
public static extern Boolean CloseHandle(IntPtr hFile);

#region ReadFile
[DllImport(
"kernel32.dll", SetLastError = true)]
public static extern Boolean ReadFile(
IntPtr hFile,
[Out] Byte[] lpBuffer,
Int32 nNumberOfBytesToRead,
out Int32 lpNumberOfBytesRead,
[In]
ref System.Threading.NativeOverlapped lpOverlapped
);

[DllImport(
"kernel32.dll", SetLastError = true)]
public static extern Boolean ReadFile(
IntPtr hFile,
[Out] Byte[] lpBuffer,
Int32 nNumberOfBytesToRead,
IntPtr lpNumberOfBytesRead,
[In]
ref System.Threading.NativeOverlapped lpOverlapped
);

[DllImport(
"kernel32.dll", SetLastError = true)]
public static extern Boolean ReadFile(
IntPtr hFile,
[Out] Byte[] lpBuffer,
Int32 nNumberOfBytesToRead,
out Int32 lpNumberOfBytesRead,
IntPtr lpOverlapped
);
#endregion

#region WriteFile
[DllImport(
"kernel32.dll")]
public static extern Boolean WriteFile(
IntPtr hFile,
Byte[] lpBuffer,
Int32 nNumberOfBytesToWrite,
out Int32 lpNumberOfBytesWritten,
[In]
ref System.Threading.NativeOverlapped lpOverlapped
);

[DllImport(
"kernel32.dll")]
public static extern Boolean WriteFile(
IntPtr hFile,
Byte[] lpBuffer,
Int32 nNumberOfBytesToWrite,
IntPtr lpNumberOfBytesWritten,
[In]
ref System.Threading.NativeOverlapped lpOverlapped
);

[DllImport(
"kernel32.dll")]
public static extern Boolean WriteFile(
IntPtr hFile,
Byte[] lpBuffer,
Int32 nNumberOfBytesToWrite,
IntPtr lpNumberOfBytesWritten,
IntPtr lpOverlapped
);
#endregion

[DllImport(
"kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern Boolean GetOverlappedResult(
IntPtr hFile,
[In]
ref System.Threading.NativeOverlapped lpOverlapped,
out Int32 lpNumberOfBytesTransferred,
Boolean bWait
);
}
#endregion

#region ENUM
[Flags]
internal enum NativeFileAccess : uint
{
GENERIC_READ
= (0x80000000),
GENERIC_WRITE
= (0x40000000),
GENERIC_EXECUTE
= (0x20000000),
GENERIC_ALL
= (0x10000000),

FILE_SPECIAL
= 0,
FILE_APPEND_DATA
= (0x0004), // 文件
FILE_READ_DATA = (0x0001), // 文件和管道
FILE_WRITE_DATA = (0x0002), // 文件和管道
FILE_READ_EA = (0x0008), // 文件和目录
FILE_WRITE_EA = (0x0010), // 文件和目录
FILE_READ_ATTRIBUTES = (0x0080), // 所有
FILE_WRITE_ATTRIBUTES = (0x0100), // 所有
DELETE = 0x00010000,
READ_CONTROL
= (0x00020000),
WRITE_DAC
= (0x00040000),
WRITE_OWNER
= (0x00080000),
SYNCHRONIZE
= (0x00100000),
STANDARD_RIGHTS_REQUIRED
= (0x000F0000),
STANDARD_RIGHTS_READ
= (READ_CONTROL),
STANDARD_RIGHTS_WRITE
= (READ_CONTROL),
STANDARD_RIGHTS_EXECUTE
= (READ_CONTROL),
STANDARD_RIGHTS_ALL
= (0x001F0000),
SPECIFIC_RIGHTS_ALL
= (0x0000FFFF),
FILE_GENERIC_READ
= (STANDARD_RIGHTS_READ | FILE_READ_DATA | FILE_READ_ATTRIBUTES | FILE_READ_EA | SYNCHRONIZE),
FILE_GENERIC_WRITE
= (STANDARD_RIGHTS_WRITE | FILE_WRITE_DATA | FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA | FILE_APPEND_DATA | SYNCHRONIZE),
SPECIAL
= 0
}

internal enum NativeFileMode : uint
{
CREATE_NEW
= 1,
CREATE_ALWAYS
= 2,
OPEN_EXISTING
= 3,
OPEN_ALWAYS
= 4,
TRUNCATE_EXISTING
= 5,
}

[Flags]
internal enum NativeFileShare : uint
{
NONE
= 0,
FILE_SHARE_READ
= 0x00000001,
FILE_SHARE_WRITE
= 0x00000002,
FILE_SHARE_DEELETE
= 0x00000004,
}

[Flags]
internal enum NativeFileFlag : uint
{
FILE_ATTRIBUTE_READONLY
= 0x00000001,
FILE_ATTRIBUTE_HIDDEN
= 0x00000002,
FILE_ATTRIBUTE_SYSTEM
= 0x00000004,
FILE_ATTRIBUTE_DIRECTORY
= 0x00000010,
FILE_ATTRIBUTE_ARCHIVE
= 0x00000020,
FILE_ATTRIBUTE_DEVICE
= 0x00000040,
FILE_ATTRIBUTE_NORMAL
= 0x00000080,
FILE_ATTRIBUTE_TEMPORARY
= 0x00000100,
FILE_ATTRIBUTE_SPARSE_FILE
= 0x00000200,
FILE_ATTRIBUTE_REPARSE_POINT
= 0x00000400,
FILE_ATTRIBUTE_COMPRESSED
= 0x00000800,
FILE_ATTRIBUTE_OFFLINE
= 0x00001000,
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED
= 0x00002000,
FILE_ATTRIBUTE_ENCRYPTED
= 0x00004000,
FILE_FLAG_WRITE_THROUGH
= 0x80000000,
FILE_FLAG_OVERLAPPED
= 0x40000000,
FILE_FLAG_NO_BUFFERING
= 0x20000000,
FILE_FLAG_RANDOM_ACCESS
= 0x10000000,
FILE_FLAG_SEQUENTIAL_SCAN
= 0x08000000,
FILE_FLAG_DELETE_ON_CLOSE
= 0x04000000,
FILE_FLAG_BACKUP_SEMANTICS
= 0x02000000,
FILE_FLAG_POSIX_SEMANTICS
= 0x01000000,
FILE_FLAG_OPEN_REPARSE_POINT
= 0x00200000,
FILE_FLAG_OPEN_NO_RECALL
= 0x00100000,
FILE_FLAG_FIRST_PIPE_INSTANCE
= 0x00080000,
}
#endregion
}

USB设备枚举(五)生成TreeView数据源 

有一处错误已于2014年5月8日修正。请大家下载SkyDrive上的资源。

/* ----------------------------------------------------------
* 文件名称:TreeViewUsbItem.cs
*
* 作者:秦建辉
*
* QQ:36748897
*
* 博客:
http://www.firstsolver.com/wordpress/
*
* 开发环境:
* Visual Studio V2010
* .NET Framework 4 Client Profile
*
* 版本历史:
* V1.0 2014年05月08日
* 修正由网友指出的一处错误
*
* V1.0 2011年10月26日
* 为USB设备枚举信息生成TreeView数据源
------------------------------------------------------------
*/
using System;
using System.Collections.Generic;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using Splash.IO.PORTS;

namespace WPFUsbView
{
/// <summary>
/// TreeView节点对象
/// </summary>
internal class TreeViewUsbItem
{
/// <summary>
/// 节点图标
/// </summary>
public ImageSource Icon { get; set; }

/// <summary>
/// 节点名称
/// </summary>
public String Name { get; set; }

/// <summary>
/// 节点数据
/// </summary>
public Object Data { get; set; }

/// <summary>
/// 子节点列表
/// </summary>
public List<TreeViewUsbItem> Children { get; set; }

/// <summary>
/// 计算机图标
/// </summary>
public static ImageSource ImageComputer
{
get
{
return System.Windows.Interop.Imaging.CreateBitmapSourceFromHIcon(
Properties.Resources.notebook.Handle,
System.Windows.Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions()
);
}
}

/// <summary>
/// 主控制器图标
/// </summary>
public static ImageSource ImageHostController
{
get
{
return System.Windows.Interop.Imaging.CreateBitmapSourceFromHIcon(
Properties.Resources.usb.Handle,
System.Windows.Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions()
);
}
}

/// <summary>
/// Hub图标
/// </summary>
public static ImageSource ImageHub
{
get
{
return System.Windows.Interop.Imaging.CreateBitmapSourceFromHIcon(
Properties.Resources.hub.Handle,
System.Windows.Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions()
);
}
}

/// <summary>
/// USB设备图标
/// </summary>
public static ImageSource ImageDevice
{
get
{
return System.Windows.Interop.Imaging.CreateBitmapSourceFromHIcon(
Properties.Resources.port.Handle,
System.Windows.Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions()
);
}
}

/// <summary>
/// 连接的外部Hub数目
/// </summary>
public static Int32 ConnectedHubs = 0;

/// <summary>
/// 连接的USB设备数目
/// </summary>
public static Int32 ConnectedDevices = 0;

/// <summary>
/// 静态根节点
/// </summary>
public static List<TreeViewUsbItem> AllUsbDevices
{
get
{
// 初始化
ConnectedHubs = 0; // 连接的外部Hub数目
ConnectedDevices = 0; // 连接的USB设备数目

// 创建根节点
TreeViewUsbItem Root = new TreeViewUsbItem();
Root.Icon
= ImageComputer;
Root.Name
= "Computer";
Root.Data
= "Machine Name:" + System.Environment.MachineName;

// 子节点列表
// 深度遍历主控制器
HostControllerInfo[] HostControllersCollection = USB.AllHostControllers;
if (HostControllersCollection != null)
{
List
<TreeViewUsbItem> HCNodeCollection = new List<TreeViewUsbItem>(HostControllersCollection.Length);
foreach (HostControllerInfo item in HostControllersCollection)
{
// 创建主控制器节点
TreeViewUsbItem HCNode = new TreeViewUsbItem();

HCNode.Icon
= ImageHostController;
HCNode.Name
= item.Name;
HCNode.Data
= item;

// 创建根集线器节点
String RootHubPath = USB.GetUsbRootHubPath(item.PNPDeviceID);
HCNode.Children
= AddHubNode(RootHubPath, "RootHub");

HCNodeCollection.Add(HCNode);
}

Root.Children
= HCNodeCollection;
}

return new List<TreeViewUsbItem>(1) { Root };
}
}

/// <summary>
/// Hub节点
/// </summary>
/// <param name="HubPath">Hub路径</param>
/// <param name="HubNodeName">节点显示名称</param>
/// <returns>Hub节点集合</returns>
private static List<TreeViewUsbItem> AddHubNode(String HubPath, String HubNodeName)
{
UsbNodeInformation[] NodeInfoCollection
= USB.GetUsbNodeInformation(HubPath);
if (NodeInfoCollection != null)
{
TreeViewUsbItem HubNode
= new TreeViewUsbItem();
HubNode.Icon
= ImageHub;
if (String.IsNullOrEmpty(NodeInfoCollection[0].Name))
{
HubNode.Name
= HubNodeName;
}
else
{
HubNode.Name
= NodeInfoCollection[0].Name;
}
HubNode.Data
= NodeInfoCollection[0];

if (NodeInfoCollection[0].NodeType == USB_HUB_NODE.UsbHub)
{
HubNode.Children
= AddPortNode(HubPath, NodeInfoCollection[0].NumberOfPorts);
}
else
{
HubNode.Children
= null;
}

return new List<TreeViewUsbItem>(1) { HubNode };
}

return null;
}

/// <summary>
/// Port节点
/// </summary>
/// <param name="HubPath">Hub路径</param>
/// <param name="NumberOfPorts">端口数</param>
/// <returns>Port节点集合</returns>
private static List<TreeViewUsbItem> AddPortNode(String HubPath, Int32 NumberOfPorts)
{
// 深度遍历端口
UsbNodeConnectionInformation[] NodeConnectionInfoCollection = USB.GetUsbNodeConnectionInformation(HubPath, NumberOfPorts);
if (NodeConnectionInfoCollection != null)
{
List
<TreeViewUsbItem> PortNodeCollection = new List<TreeViewUsbItem>(NumberOfPorts);
foreach (UsbNodeConnectionInformation NodeConnectionInfo in NodeConnectionInfoCollection)
{
// 增加端口节点
TreeViewUsbItem PortNode = new TreeViewUsbItem();

PortNode.Icon
= ImageDevice;
PortNode.Name
= "[Port" + NodeConnectionInfo.ConnectionIndex + "]" + NodeConnectionInfo.ConnectionStatus;
PortNode.Data
= NodeConnectionInfo;
PortNode.Children
= null;
if (NodeConnectionInfo.ConnectionStatus == USB_CONNECTION_STATUS.DeviceConnected)
{
// 设备连接
ConnectedDevices++; // 连接的USB设备数目
if (!String.IsNullOrEmpty(NodeConnectionInfo.DeviceDescriptor.Product))
{
// 产品名称
PortNode.Name = String.Concat(PortNode.Name, ": ", NodeConnectionInfo.DeviceDescriptor.Product);
}

if (NodeConnectionInfo.DeviceIsHub)
{
// 获取外部Hub设备路径
String ExternalHubPath = USB.GetExternalHubPath(NodeConnectionInfo.DevicePath, NodeConnectionInfo.ConnectionIndex);
UsbNodeInformation[] NodeInfoCollection
= USB.GetUsbNodeInformation(ExternalHubPath);
if (NodeInfoCollection != null)
{
PortNode.Icon
= ImageHub;
PortNode.Data
= new ExternalHubInfo { NodeInfo = NodeInfoCollection[0], NodeConnectionInfo = NodeConnectionInfo };
if (NodeInfoCollection[0].NodeType == USB_HUB_NODE.UsbHub)
{
PortNode.Children
= AddPortNode(ExternalHubPath, NodeInfoCollection[0].NumberOfPorts);
}

if (String.IsNullOrEmpty(NodeConnectionInfo.DeviceDescriptor.Product))
{
if (!String.IsNullOrEmpty(NodeInfoCollection[0].Name))
{
// 产品名称
PortNode.Name = String.Concat(PortNode.Name, ": ", NodeInfoCollection[0].Name);
}
}
}

ConnectedHubs
++; // 连接的外部Hub数目
}
}

PortNodeCollection.Add(PortNode);
}

return PortNodeCollection;
}

return null;
}
}
}

USB设备枚举(六)生成ListView数据源 

/* ----------------------------------------------------------
文件名称:ListViewUsbItem.cs

作者:秦建辉

MSN:splashcn@msn.com
QQ:36748897

博客:
http://blog.csdn.net/jhqin

开发环境:
Visual Studio V2010
.NET Framework 4 Client Profile

版本历史:
V1.0 2011年11月08日
为USB设备枚举信息生成ListView数据源
------------------------------------------------------------
*/
using System;
using System.Collections.Generic;
using Splash.IO.PORTS;

namespace WPFUsbView
{
/// <summary>
/// TreeView节点对象
/// </summary>
internal class ListViewUsbItem
{
/// <summary>
/// USB属性名
/// </summary>
public String Name { get; set; }

/// <summary>
/// USB属性值
/// </summary>
public String Value { get; set; }

/// <summary>
/// 构造函数
/// </summary>
/// <param name="Name">USB属性名</param>
/// <param name="Value">USB属性值</param>
public ListViewUsbItem(String Name, String Value)
{
this.Name = Name;
this.Value = Value;
}

/// <summary>
/// 生成USB属性列表
/// </summary>
/// <param name="Data">用于生成列表的USB数据</param>
/// <returns>属性列表</returns>
public static List<ListViewUsbItem> UsbDetail(Object Data)
{
if (Data is String)
{
// 机器名
String Info = Data as String;
if (!String.IsNullOrEmpty(Info))
{
String[] Content
= Info.Split(new Char[] { ':' });
if (Content.Length == 2)
{
return new List<ListViewUsbItem>(1) { new ListViewUsbItem(Content[0], Content[1]) };
}
}
}
else if (Data is HostControllerInfo)
{
// 主控制器信息
HostControllerInfo Info = (HostControllerInfo)Data;
return new List<ListViewUsbItem>(3)
{
new ListViewUsbItem("Name", Info.Name),
new ListViewUsbItem("PNPDeviceID", Info.PNPDeviceID),
new ListViewUsbItem("HcdDriverKeyName", Info.HcdDriverKeyName)
};
}
else if (Data is UsbNodeInformation)
{
// USB节点信息
UsbNodeInformation Info = (UsbNodeInformation)Data;

List
<ListViewUsbItem> Items = new List<ListViewUsbItem>();
Add(
ref Items, Info);
return Items;
}
else if (Data is UsbNodeConnectionInformation)
{
// USB节点连接信息
UsbNodeConnectionInformation Info = (UsbNodeConnectionInformation)Data;
if(Info.ConnectionStatus != USB_CONNECTION_STATUS.DeviceConnected)
return null;

List
<ListViewUsbItem> Items = new List<ListViewUsbItem>();
Add(
ref Items, Info);
return Items;
}
else if (Data is ExternalHubInfo)
{
// 外部Hub信息
ExternalHubInfo Info = (ExternalHubInfo)Data;

List
<ListViewUsbItem> Items = new List<ListViewUsbItem>();

// 加入USB节点信息
Items.Add(new ListViewUsbItem("Node Information:", null));
Add(
ref Items, Info.NodeInfo);

// 加入USB节点连接信息
Items.Add(new ListViewUsbItem(null, null));
Items.Add(
new ListViewUsbItem("Node Connection Information:", null));
Add(
ref Items, Info.NodeConnectionInfo);

return Items;
}

return null;
}

/// <summary>
/// 增加USB节点信息
/// </summary>
/// <param name="Items">要增加的列表</param>
/// <param name="Info">要增加的信息</param>
private static void Add(ref List<ListViewUsbItem> Items, UsbNodeInformation Info)
{
if (Info.NodeType == USB_HUB_NODE.UsbHub)
{
Items.Add(
new ListViewUsbItem("Name", Info.Name));
Items.Add(
new ListViewUsbItem("PNPDeviceID", Info.PNPDeviceID));
Items.Add(
new ListViewUsbItem("DevicePath", Info.DevicePath));
Items.Add(
new ListViewUsbItem("NodeType", Info.NodeType.ToString()));
Items.Add(
new ListViewUsbItem("HubIsBusPowered", Info.HubIsBusPowered.ToString()));
Items.Add(
new ListViewUsbItem("NumberOfPorts", Info.NumberOfPorts.ToString()));
Items.Add(
new ListViewUsbItem("HubCharacteristics", "0x" + Info.HubCharacteristics.ToString("X4")));
Items.Add(
new ListViewUsbItem("PowerOnToPowerGood", (Info.PowerOnToPowerGood * 2).ToString() + "ms"));
Items.Add(
new ListViewUsbItem("HubControlCurrent", Info.HubControlCurrent.ToString()));
}
else
{
Items.Add(
new ListViewUsbItem("Name", Info.Name));
Items.Add(
new ListViewUsbItem("PNPDeviceID", Info.PNPDeviceID));
Items.Add(
new ListViewUsbItem("DevicePath", Info.DevicePath));
Items.Add(
new ListViewUsbItem("NodeType", Info.NodeType.ToString()));
Items.Add(
new ListViewUsbItem("NumberOfInterfaces", Info.NumberOfInterfaces.ToString()));
}
}

/// <summary>
/// 增加USB节点连接信息
/// </summary>
/// <param name="Items">要增加的列表</param>
/// <param name="Info">要增加的信息</param>
private static void Add(ref List<ListViewUsbItem> Items, UsbNodeConnectionInformation Info)
{
Items.Add(
new ListViewUsbItem("DevicePath", Info.DevicePath));
Items.Add(
new ListViewUsbItem("ConnectionIndex", Info.ConnectionIndex.ToString()));
Items.Add(
new ListViewUsbItem("CurrentConfigurationValue", "0x" + Info.CurrentConfigurationValue.ToString("X2")));
Items.Add(
new ListViewUsbItem("Speed", ((USB_DEVICE_SPEED)Info.Speed).ToString()));
Items.Add(
new ListViewUsbItem("DeviceIsHub", Info.DeviceIsHub.ToString()));
Items.Add(
new ListViewUsbItem("DeviceAddress", Info.DeviceAddress.ToString()));
Items.Add(
new ListViewUsbItem("NumberOfOpenPipes", Info.NumberOfOpenPipes.ToString()));

// 设备描述符
Items.Add(new ListViewUsbItem(null, null));
Items.Add(
new ListViewUsbItem("Device Descriptor:", null));
Items.Add(
new ListViewUsbItem("DescriptorType", "0x" + Info.DeviceDescriptor.bDescriptorType.ToString("X2")));
Items.Add(
new ListViewUsbItem("UsbVersion", Info.DeviceDescriptor.UsbVersion));
Items.Add(
new ListViewUsbItem("DeviceClass", "0x" + Info.DeviceDescriptor.bDeviceClass.ToString("X2")));
Items.Add(
new ListViewUsbItem("DeviceSubClass", "0x" + Info.DeviceDescriptor.bDeviceSubClass.ToString("X2")));
Items.Add(
new ListViewUsbItem("DeviceProtocol", "0x" + Info.DeviceDescriptor.bDeviceProtocol.ToString("X2")));
Items.Add(
new ListViewUsbItem("MaxPacketSize0", Info.DeviceDescriptor.bMaxPacketSize0.ToString()));
Items.Add(
new ListViewUsbItem("idVendor", "0x" + Info.DeviceDescriptor.idVendor.ToString("X4")));
Items.Add(
new ListViewUsbItem("idProduct", "0x" + Info.DeviceDescriptor.idProduct.ToString("X4")));
Items.Add(
new ListViewUsbItem("DeviceVersion", Info.DeviceDescriptor.DeviceVersion));
Items.Add(
new ListViewUsbItem("Manufacturer", Info.DeviceDescriptor.Manufacturer));
Items.Add(
new ListViewUsbItem("Product", Info.DeviceDescriptor.Product));
Items.Add(
new ListViewUsbItem("SerialNumber", Info.DeviceDescriptor.SerialNumber));
Items.Add(
new ListViewUsbItem("NumConfigurations", Info.DeviceDescriptor.bNumConfigurations.ToString()));

// 管道信息
foreach (UsbPipeInfo Pipe in Info.PipeList)
{
Items.Add(
new ListViewUsbItem(null, null));
Items.Add(
new ListViewUsbItem("Endpoint Descriptor:", null));
Items.Add(
new ListViewUsbItem("ScheduleOffset", Pipe.ScheduleOffset.ToString()));
Items.Add(
new ListViewUsbItem("DescriptorType", "0x" + Pipe.bDescriptorType.ToString("X2")));
Items.Add(
new ListViewUsbItem("EndpointAddress", "0x" + Pipe.bEndpointAddress.ToString("X2")));
Items.Add(
new ListViewUsbItem("bmAttributes", "0x" + Pipe.bmAttributes.ToString("X2")));
Items.Add(
new ListViewUsbItem("MaxPacketSize", Pipe.wMaxPacketSize.ToString()));
Items.Add(
new ListViewUsbItem("Interval", "0x" + Pipe.bInterval.ToString("X2")));
}
}
}
}

USB设备枚举(七)WPF扩展方法 

/* ----------------------------------------------------------
文件名称:WPFExtensions.cs

作者:秦建辉

MSN:splashcn@msn.com
QQ:36748897

博客:
http://blog.csdn.net/jhqin

开发环境:
Visual Studio V2010
.NET Framework 4 Client Profile

版本历史:
V1.1 2011年11月07日
实现扩展方法:WPF中TreeView类的ExpandAll功能

V1.0 2011年11月03日
实现扩展方法:WPF中Button类的PerformClick功能
------------------------------------------------------------
*/
using System.Windows.Controls;
using System.Windows.Automation.Peers;
using System.Windows.Automation.Provider;

namespace Splash.WPF
{
/// <summary>
/// 扩展方法
/// </summary>
public static partial class Extensions
{
/// <summary>
/// 扩展方法:实现WPF中Button类的PerformClick功能
/// </summary>
/// <param name="button">Button实例</param>
/// <remarks>
/// 需要添加对UIAutomationProvider.dll的引用
/// 参考网址:http://www.cnblogs.com/zhouyinhui/archive/2010/05/20/1740111.html
/// </remarks>
public static void PerformClick(this Button button)
{
ButtonAutomationPeer BAP
= new ButtonAutomationPeer(button);
IInvokeProvider IIP
= BAP.GetPattern(PatternInterface.Invoke) as IInvokeProvider;
if (IIP != null)
{
IIP.Invoke();
}
}

/// <summary>
/// 扩展方法:实现WPF中TreeView类的ExpandAll功能
/// </summary>
/// <param name="treeView">要展开的TreeView实例</param>
/// <remarks>
/// 参考网址:http://www.cnblogs.com/sayo/archive/2008/07/23/1249804.html
/// </remarks>
public static void ExpandAll(this TreeView treeView)
{
ExpandSubItems(treeView
as ItemsControl);
}

private static void ExpandSubItems(ItemsControl control)
{
if (control == null) return;
foreach (object item in control.Items)
{
TreeViewItem treeItem
= control.ItemContainerGenerator.ContainerFromItem(item) as TreeViewItem;
if (treeItem != null && treeItem.HasItems)
{
treeItem.IsExpanded
= true;
ExpandSubItems(treeItem
as ItemsControl);
}
}
}
}
}

(八)创建基于WPF的USB设备浏览器 

软件界面:

C#:USB设备枚举 --转自CSDN作者:Splash

 

下载地址(包含产品及源代码):

微软SkyDrive下载链接:WPFUsbView.zip

CSDN下载页面:http://download.csdn.net/detail/jhqin/3773593

源代码:

MainWindow.xaml

<Window x:Class="WPFUsbView.MainWindow"
xmlns
="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x
="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:usb
="clr-namespace:WPFUsbView"
Title
="USB Device Viewer" Height="600" Width="800" Icon="/WPFUsbView;component/images/usb.ico" WindowStyle="ThreeDBorderWindow" WindowStartupLocation="CenterScreen" Loaded="Window_Loaded" WindowState="Maximized">
<Window.Resources>
<Style TargetType="TreeViewItem">
<Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=OneWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type TreeViewItem}}}" />
</Style>
</Window.Resources>

<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>

<Grid Grid.Row="0" Background="CadetBlue">
<ToolBar Height="40" Width="Auto" HorizontalAlignment="Left" Background="CadetBlue">
<Button Margin="4,0" Name="buttonRefresh" Click="buttonRefresh_Click">
<Image Source="/WPFUsbView;component/images/refresh.png"></Image>
</Button>
<Button Margin="4,0" Name="buttonOpenXML" Click="buttonOpenXML_Click">
<Image Source="/WPFUsbView;component/images/XML.png"></Image>
</Button>
<Button Margin="4,0" Name="buttonInfo" Click="buttonInfo_Click">
<Image Source="/WPFUsbView;component/images/Info.png"></Image>
</Button>
</ToolBar>
</Grid>

<Grid Grid.Row="1" Name="gridDetail">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="4*"></ColumnDefinition>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition Width="6*"></ColumnDefinition>
</Grid.ColumnDefinitions>

<TreeView Grid.Column="0" HorizontalAlignment="Left" VerticalAlignment="Top" Name="treeView1" FontSize="16" SelectedItemChanged="treeView1_SelectedItemChanged">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate DataType="{x:Type usb:TreeViewUsbItem}" ItemsSource="{Binding Path=Children}">
<StackPanel Orientation="Horizontal">
<Image VerticalAlignment="Center" Source="{Binding Icon}" Width="16" Height="16" Margin="0,0,2,2"></Image>
<TextBlock VerticalAlignment="Center" Text="{Binding Name}"></TextBlock>
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>

<GridSplitter Grid.Column="1" Width="13" HorizontalAlignment="Center" VerticalAlignment="Stretch" LayoutUpdated="GridSplitter_LayoutUpdated">
<GridSplitter.Background>
<ImageBrush ImageSource="/WPFUsbView;component/images/SplitLine.png" Stretch="UniformToFill" TileMode="Tile" Viewport="0,0,15,500" ViewportUnits="Absolute" />
</GridSplitter.Background>
</GridSplitter>

<ListView Grid.Column="2" Name="listView1" FontSize="16">
<ListView.ItemTemplate>
<DataTemplate DataType="{x:Type usb:ListViewUsbItem}">
<StackPanel Orientation="Horizontal" Margin="0,2">
<TextBlock Width="250" Text="{Binding Name}"></TextBlock>
<TextBlock Width="Auto" Text="{Binding Value}" Foreground="Blue"></TextBlock>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>

<StatusBar Grid.Row="2" Height="32" Background="SteelBlue">
<StatusBarItem>
<Image Source="/WPFUsbView;component/images/usbdevice.png"></Image>
</StatusBarItem>
<StatusBarItem>
<TextBlock FontSize="16" Foreground="Brown" Name="textBlockUsbDevice">0</TextBlock>
</StatusBarItem>
<StatusBarItem>
<Image Source="/WPFUsbView;component/images/usb-hub.png"></Image>
</StatusBarItem>
<StatusBarItem>
<TextBlock FontSize="16" Foreground="Brown" Name="textBlockUsbHub">0</TextBlock>
</StatusBarItem>
</StatusBar>
</Grid>
</Window>

MainWindow.xaml.cs

using System;
using System.IO;
using System.Windows;
using Splash.IO.PORTS;
using Splash.WPF;

namespace WPFUsbView
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}

// 枚举设备信息并输出到XML文档
private void buttonOpenXML_Click(object sender, RoutedEventArgs e)
{
String xmlFile
= "UsbEnums.xml";
try
{
// 检测当前目录下是否可以创建文件
using (StreamWriter sw = new StreamWriter(xmlFile))
{
sw.Close();
}
}
catch(Exception)
{
// 当前目录无法创建文件,改到我的文档目录下
xmlFile = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\" + xmlFile;
}

if (USB.EnumUsbToXML(xmlFile))
{
// 判断文件是否存在
if (System.IO.File.Exists(xmlFile))
{
// 打开文件
Splash.Diagnostics.Extensions.ShellExecute(xmlFile);
return;
}
}

MessageBox.Show(
"Failed!");
return;
}

// 更新设备枚举信息
private void buttonRefresh_Click(object sender, RoutedEventArgs e)
{
// 枚举USB设备信息
treeView1.ItemsSource = TreeViewUsbItem.AllUsbDevices;

// 展开所有分支
treeView1.ExpandAll();

// 设备连接数
textBlockUsbDevice.Text = TreeViewUsbItem.ConnectedDevices.ToString();

// 外部Hub连接数
textBlockUsbHub.Text = TreeViewUsbItem.ConnectedHubs.ToString();
}

// 显示软件版本信息
private void buttonInfo_Click(object sender, RoutedEventArgs e)
{
About AboutWindow
= new About();
AboutWindow.Owner
= this;
AboutWindow.ShowDialog();
}

private void Window_Loaded(object sender, RoutedEventArgs e)
{
// 显示USB设备枚举信息
buttonRefresh.PerformClick();
}

// 更新布局,调整各控件大小
private void GridSplitter_LayoutUpdated(object sender, EventArgs e)
{
// 设置TreeView的宽度和高度
treeView1.Width = gridDetail.ColumnDefinitions[0].ActualWidth;
treeView1.Height
= gridDetail.ActualHeight;
}

private void treeView1_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
TreeViewUsbItem Node
= e.NewValue as TreeViewUsbItem;
if (Node != null)
{
listView1.ItemsSource
= ListViewUsbItem.UsbDetail(Node.Data);
}
}
}
}