//获取某一类型的设备列表 [DllImport("setupapi.dll", CharSet = CharSet.Auto)] public static extern IntPtr SetupDiGetClassDevs(ref Guid ClassGuid, [MarshalAs(UnmanagedType.LPTStr)] string Enumerator, IntPtr hwndParent, UInt32 Flags); //枚举设备 [DllImport(@"setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern Boolean SetupDiEnumDeviceInterfaces(IntPtr hDevInfo, IntPtr devInfo, ref Guid interfaceClassGuid, UInt32 memberIndex, ref SP_DEVICE_INTERFACE_DATA deviceInterfaceData); //销毁设备列表 [DllImport(@"setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern bool SetupDiDestroyDeviceInfoList(IntPtr hDevInfo); //获取某个设备的详细信息 [DllImport("setupapi.dll", CharSet = CharSet.Auto)] private static extern Boolean SetupDiGetDeviceInterfaceDetail(IntPtr DeviceInfoSet, ref SP_DEVICE_INTERFACE_DATA DeviceIntefaceData, IntPtr DeviceInterfaceDetailData, int DeviceInterfacedetailDatasize, ref int DeviceInterfacedetaildataSize, IntPtr DeviceInfoData); //打开读写端口 [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)] public static extern IntPtr CreateFile(string fileName, [MarshalAs(UnmanagedType.U4)] FileAccess fileAccess, [MarshalAs(UnmanagedType.U4)] FileShare fileShare, IntPtr securityAttributes, [MarshalAs(UnmanagedType.U4)] FileMode creationDisposition, int flags, IntPtr template); //往端口写数据 [DllImport("kernel32.dll")] public static extern bool WriteFile(IntPtr hFile, byte[] lpBuffer, int nNumberOfBytesToWrite, out int lpNumberOfBytesWritten, [In] IntPtr lpOverlapped); //关闭读写端口 [DllImport("kernel32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool CloseHandle(IntPtr hObject); [FlagsAttribute] public enum DiGetClassFlags : uint { DIGCF_DEFAULT = 0x00000001, // only valid with DIGCF_DEVICEINTERFACE DIGCF_PRESENT = 0x00000002, DIGCF_ALLCLASSES = 0x00000004, DIGCF_PROFILE = 0x00000008, DIGCF_DEVICEINTERFACE = 0x00000010, } [StructLayout(LayoutKind.Sequential)] public struct SP_DEVINFO_DATA { public UInt32 cbSize; public Guid ClassGuid; public UInt32 DevInst; public IntPtr Reserved; } [StructLayout(LayoutKind.Sequential)] public struct SP_DEVICE_INTERFACE_DATA { public UInt32 cbSize; public Guid InterfaceClassGuid; public UInt32 Flags; public UIntPtr Reserved; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] public struct SP_DEVICE_INTERFACE_DETAIL_DATA { public UInt32 cbSize; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] public string DevicePath; }
3. 获取某一设备类型的设备列表
Guid guid = new Guid("a5dcbf10-6530-11d2-901f-00c04fb951ed"); IntPtr hInfo = SetupDiGetClassDevs(ref guid, null, IntPtr.Zero, (uint)(DiGetClassFlags.DIGCF_PRESENT | DiGetClassFlags.DIGCF_DEVICEINTERFACE)); if(hInfo.ToInt32() == -1) { return false; }
4. 获取设备的读写路径
for(uint i = 0; i < 1000; ++i) { SP_DEVICE_INTERFACE_DATA interface_Info = new SP_DEVICE_INTERFACE_DATA(); interface_Info.cbSize = (uint)Marshal.SizeOf(typeof(SP_DEVICE_INTERFACE_DATA)); if(!SetupDiEnumDeviceInterfaces(hInfo, IntPtr.Zero, ref guid, i, ref interface_Info)) { SetupDiDestroyDeviceInfoList(hInfo); break; } int needed = 0; SetupDiGetDeviceInterfaceDetail(hInfo, ref interface_Info, IntPtr.Zero, 0, ref needed, IntPtr.Zero); IntPtr detailDataBuffer; detailDataBuffer = Marshal.AllocHGlobal(needed); Marshal.WriteInt32(detailDataBuffer, 4 + Marshal.SystemDefaultCharSize); if(!SetupDiGetDeviceInterfaceDetail(hInfo, ref interface_Info, detailDataBuffer, needed, ref needed, IntPtr.Zero)) { SetupDiDestroyDeviceInfoList(hInfo); return false; } SP_DEVICE_INTERFACE_DETAIL_DATA detail = (SP_DEVICE_INTERFACE_DETAIL_DATA)Marshal.PtrToStructure(detailDataBuffer, typeof(SP_DEVICE_INTERFACE_DETAIL_DATA)); if(detail.DevicePath.Contains(@"USB\VID_067B&PID_2305\6&2002C22&0&1")) { name = detail.DevicePath; break; } }
在这里name就是设备读写的路径。接着使用这个路径来打开读写端口即可。
handle = CreateFile(name, FileAccess.ReadWrite, FileShare.ReadWrite, IntPtr.Zero, FileMode.Open, 0, IntPtr.Zero); if(handle.ToInt32() == -1) { return false; }
CloseHandle(handle);
int tmp = 0; bool result = WriteFile(handle, buf, buf.Length, out tmp, IntPtr.Zero);