Exemplo n.º 1
0
        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);
        }
Exemplo n.º 2
0
        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);
        }