C#:USB设备枚举(二)设备枚举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
    }
}

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值