public static List <SerialPortDevice> Enumerate() { List <SerialPortDevice> devices = new List <SerialPortDevice>(); Guid[] guids = GetClassGUIDs("Ports"); Guid[] addGuids = new Guid[] { new Guid(0x86e0d1e0, 0x8089, 0x11d0, 0x9c, 0xe4, 0x08, 0x00, 0x3e, 0x30, 0x1f, 0x73) }; //GetClassGUIDs("Modem"); int oldSize = guids.Length; Array.Resize <Guid>(ref guids, oldSize + addGuids.Length); addGuids.CopyTo(guids, oldSize); string port; string description; string busDescription; string deviceId; string devicePath; int size; for (int guidIndex = 0; guidIndex < guids.Length; guidIndex++) { Console.WriteLine("l1"); IntPtr hDevInfoSet = NativeMethods.SetupDiGetClassDevs(ref guids[guidIndex], null, IntPtr.Zero, NativeMethods.DiGetClassFlags.DIGCF_PRESENT | NativeMethods.DiGetClassFlags.DIGCF_DEVICEINTERFACE); if (hDevInfoSet.ToInt64() == NativeMethods.INVALID_HANDLE_VALUE) { break; } Console.WriteLine("l2"); IntPtr hParentsDevInfoSet = NativeMethods.SetupDiCreateDeviceInfoList(IntPtr.Zero, IntPtr.Zero); if (hParentsDevInfoSet.ToInt64() == NativeMethods.INVALID_HANDLE_VALUE) { break; } Console.WriteLine("l3"); NativeMethods.SP_DEVICE_INTERFACE_DATA devInterfaceData = new NativeMethods.SP_DEVICE_INTERFACE_DATA(); devInterfaceData.CbSize = (uint)Marshal.SizeOf(devInterfaceData); NativeMethods.SP_DEVINFO_DATA devInfoData = new NativeMethods.SP_DEVINFO_DATA(); NativeMethods.SP_DEVINFO_DATA parentDevInfoData = new NativeMethods.SP_DEVINFO_DATA(); devInfoData.CbSize = (uint)Marshal.SizeOf(devInfoData); parentDevInfoData.CbSize = (uint)Marshal.SizeOf(parentDevInfoData); Console.WriteLine("l4"); try { bool ok = true; for (uint i = 0; ok; i++) { ok = NativeMethods.SetupDiEnumDeviceInfo(hDevInfoSet, i, ref devInfoData); if (!ok) { break; } Console.WriteLine("l5"); port = GetPortName(hDevInfoSet, devInfoData); if (!port.StartsWith("COM")) { continue; } Console.WriteLine(port); busDescription = ""; deviceId = ""; devicePath = ""; //get device path: try { Console.WriteLine("l6"); ok = NativeMethods.SetupDiEnumDeviceInterfaces(hDevInfoSet, IntPtr.Zero, ref guids[guidIndex], i, ref devInterfaceData); if (ok) { //call with 0 to get the size: Console.WriteLine("l7"); uint nRequiredSize; ok = NativeMethods.SetupDiGetDeviceInterfaceDetail(hDevInfoSet, devInterfaceData, IntPtr.Zero, 0, out nRequiredSize, devInfoData); Console.WriteLine("l8"); if (ok == false) { ok = true; int error = Marshal.GetLastWin32Error(); // expect that ok is false and that error is ERROR_INSUFFICIENT_BUFFER = 122, // and nRequiredSize is the required size if (error != 122) { //throw new Win32Exception(error); Console.WriteLine(error); //goto skipDevicepath; } } Console.WriteLine("l9"); // build a Device Interface Detail Data structure IntPtr didd = Marshal.AllocHGlobal((int)nRequiredSize); try { uint nBytes = nRequiredSize; Marshal.WriteInt32(didd, (IntPtr.Size == 4) ? (4 + Marshal.SystemDefaultCharSize) : 8); // now we can get some more detailed information if (NativeMethods.SetupDiGetDeviceInterfaceDetail(hDevInfoSet, devInterfaceData, didd, nBytes, out nRequiredSize, devInfoData)) { devicePath = Marshal.PtrToStringAuto(new IntPtr(didd.ToInt32() + 4)); } } finally { Marshal.FreeHGlobal(didd); } } } catch (Exception ex) { Console.WriteLine($"Failed to {ex.Message} enumerate USB serial devices. Error: [{Marshal.GetLastWin32Error()}] HR: [{Marshal.GetHRForLastWin32Error()}]"); } //skipDevicepath: Console.WriteLine("l10"); //get other info: description = GetDescription(hDevInfoSet, devInfoData); NativeMethods.CM_Get_Device_ID_Size(out size, devInfoData.DevInst); size++; //account for '\0' StringBuilder IDBuffer = new StringBuilder(size); int getDevIdRet = NativeMethods.CM_Get_Device_ID(devInfoData.DevInst, IDBuffer, size); if (getDevIdRet != (int)NativeMethods.GetDeviceIdResult.CR_SUCCESS) { //throw new Win32Exception(Marshal.GetLastWin32Error(), $"Failed to get parent device ID. With error: {getDevIdRet}]"); } else { deviceId = IDBuffer.ToString(); busDescription = GetDeviceBusDescription(hDevInfoSet, devInfoData); } if ((busDescription.Length == 0) || (busDescription == description)) { NativeMethods.CM_Get_Parent(out parentDevInfoData.DevInst, devInfoData.DevInst); NativeMethods.CM_Get_Device_ID_Size(out size, parentDevInfoData.DevInst); size++; //account for '\0' IDBuffer = new StringBuilder(size); getDevIdRet = NativeMethods.CM_Get_Device_ID(parentDevInfoData.DevInst, IDBuffer, size); if (getDevIdRet != (int)NativeMethods.GetDeviceIdResult.CR_SUCCESS) { //throw new Win32Exception(Marshal.GetLastWin32Error(), $"Failed to get parent device ID. With error: {getDevIdRet}]"); } else { deviceId = IDBuffer.ToString(); bool result = NativeMethods.SetupDiOpenDeviceInfo(hParentsDevInfoSet, deviceId, IntPtr.Zero, 0, ref parentDevInfoData); if (!result) { //throw new Win32Exception(Marshal.GetLastWin32Error(), $"SetupDiOpenDeviceInfo failed Error: [{Marshal.GetLastWin32Error()}] HR: [{Marshal.GetHRForLastWin32Error()}]"); //busDescription = ""; } else { busDescription = GetDeviceBusDescription(hParentsDevInfoSet, parentDevInfoData); } } } //Dictionary<string, string> id = GetDeviceVidPid(hDevInfoSet, devInfoData); var device = new SerialPortDevice { Port = port, Description = description, FriendlyName = GetFriendlyName(hDevInfoSet, devInfoData), BusReportedDeviceDescription = busDescription, DeviceID = deviceId, DevicePath = devicePath //Vid = id.ContainsKey("VID") ? (int?)int.Parse(id["VID"], System.Globalization.NumberStyles.HexNumber) : null, //Pid = id.ContainsKey("PID") ? (int?)int.Parse(id["PID"], System.Globalization.NumberStyles.HexNumber) : null, //Rev = id.ContainsKey("REV") ? (int?)int.Parse(id["REV"], System.Globalization.NumberStyles.HexNumber) : null }; devices.Add(device); } if (!ok && Marshal.GetLastWin32Error() != NativeMethods.NO_ERROR && Marshal.GetLastWin32Error() != NativeMethods.ERROR_NO_MORE_ITEMS) { throw new Win32Exception(Marshal.GetLastWin32Error(), $"Failed to enumerate USB serial devices. Error: [{Marshal.GetLastWin32Error()}] HR: [{Marshal.GetHRForLastWin32Error()}]"); } } finally { NativeMethods.SetupDiDestroyDeviceInfoList(hParentsDevInfoSet); NativeMethods.SetupDiDestroyDeviceInfoList(hDevInfoSet); } } return(devices); }
public static List <SerialPortDevice> Enumerate() { List <SerialPortDevice> devices = new List <SerialPortDevice>(); Guid[] guids = GetClassGUIDs("Ports"); Guid[] addGuids = GetClassGUIDs("Modem"); int oldSize = guids.Length; Array.Resize <Guid>(ref guids, oldSize + addGuids.Length); addGuids.CopyTo(guids, oldSize); string port; string description; string busDescription; string deviceId; for (int guidIndex = 0; guidIndex < guids.Length; guidIndex++) { IntPtr hDevInfoSet = NativeMethods.SetupDiGetClassDevs(ref guids[guidIndex], null, IntPtr.Zero, NativeMethods.DiGetClassFlags.DIGCF_PRESENT); if (hDevInfoSet.ToInt64() == NativeMethods.INVALID_HANDLE_VALUE) { break; } IntPtr hParentsDevInfoSet = NativeMethods.SetupDiCreateDeviceInfoList(IntPtr.Zero, IntPtr.Zero); if (hParentsDevInfoSet.ToInt64() == NativeMethods.INVALID_HANDLE_VALUE) { break; } NativeMethods.SP_DEVINFO_DATA devInfoData = new NativeMethods.SP_DEVINFO_DATA(); NativeMethods.SP_DEVINFO_DATA parentDevInfoData = new NativeMethods.SP_DEVINFO_DATA(); devInfoData.CbSize = (uint)Marshal.SizeOf(devInfoData); parentDevInfoData.CbSize = (uint)Marshal.SizeOf(parentDevInfoData); try { for (uint i = 0; NativeMethods.SetupDiEnumDeviceInfo(hDevInfoSet, i, ref devInfoData); i++) { port = GetPortName(hDevInfoSet, devInfoData); if (!port.StartsWith("COM")) { continue; } busDescription = ""; deviceId = ""; description = GetDescription(hDevInfoSet, devInfoData); NativeMethods.CM_Get_Device_ID_Size(out int size, devInfoData.DevInst); size++; //account for '\0' StringBuilder IDBuffer = new StringBuilder(size); int getDevIdRet = NativeMethods.CM_Get_Device_ID(devInfoData.DevInst, IDBuffer, size); if (getDevIdRet != (int)NativeMethods.GetDeviceIdResult.CR_SUCCESS) { //throw new Win32Exception(Marshal.GetLastWin32Error(), $"Failed to get parent device ID. With error: {getDevIdRet}]"); } else { deviceId = IDBuffer.ToString(); busDescription = GetDeviceBusDescription(hDevInfoSet, devInfoData); } if ((busDescription.Length == 0) || (busDescription == description)) { NativeMethods.CM_Get_Parent(out parentDevInfoData.DevInst, devInfoData.DevInst); NativeMethods.CM_Get_Device_ID_Size(out size, parentDevInfoData.DevInst); size++; //account for '\0' IDBuffer = new StringBuilder(size); getDevIdRet = NativeMethods.CM_Get_Device_ID(parentDevInfoData.DevInst, IDBuffer, size); if (getDevIdRet != (int)NativeMethods.GetDeviceIdResult.CR_SUCCESS) { //throw new Win32Exception(Marshal.GetLastWin32Error(), $"Failed to get parent device ID. With error: {getDevIdRet}]"); } else { deviceId = IDBuffer.ToString(); bool result = NativeMethods.SetupDiOpenDeviceInfo(hParentsDevInfoSet, deviceId, IntPtr.Zero, 0, ref parentDevInfoData); if (!result) { //throw new Win32Exception(Marshal.GetLastWin32Error(), $"SetupDiOpenDeviceInfo failed Error: [{Marshal.GetLastWin32Error()}] HR: [{Marshal.GetHRForLastWin32Error()}]"); //busDescription = ""; } else { busDescription = GetDeviceBusDescription(hParentsDevInfoSet, parentDevInfoData); } } } var device = new SerialPortDevice { Port = port, Description = description, FriendlyName = GetFriendlyName(hDevInfoSet, devInfoData), BusReportedDeviceDescription = busDescription, DeviceID = deviceId }; devices.Add(device); } if (Marshal.GetLastWin32Error() != NativeMethods.NO_ERROR && Marshal.GetLastWin32Error() != NativeMethods.ERROR_NO_MORE_ITEMS) { throw new Win32Exception(Marshal.GetLastWin32Error(), $"Failed to enumerate USB serial devices. Error: [{Marshal.GetLastWin32Error()}] HR: [{Marshal.GetHRForLastWin32Error()}]"); } } finally { NativeMethods.SetupDiDestroyDeviceInfoList(hParentsDevInfoSet); NativeMethods.SetupDiDestroyDeviceInfoList(hDevInfoSet); } } return(devices); }