#! python # # Enumerate serial ports on Windows including a human readable description # and hardware information using winreg. # # Using winreg helps find virtual comports # Taken from https://github.com/pyserial/pyserial/pull/70 since pyserial isnt getting recent updates try: # Python 3.X import winreg except ImportError: # Python 2.7 compatibility try: import _winreg as winreg except ImportError: winreg = None from serial.tools import list_ports_common from serial.tools import list_ports_windows SERIAL_REGISTRY_PATH = 'HARDWARE\\DEVICEMAP\\SERIALCOMM' def regval_to_listport(winport): """Convert a windows port from registry key to pyserial's ListPortInfo. Args: winport (tuple): Windows registry value (description, device, value). Returns: listport (ListPortInfo): comport device details. """ # Create the ListPortInfo description, device, _ = winport listport = list_ports_common.ListPortInfo(device) # Format the description like other ListPortInfo description = description.replace('\\Device\\', '') listport.description = "{} ({})".format(description, device) return listport # end regval_to_listport def winreg_comports(): """Return windows comports found in the registry. See Also: list_ports_winreg.comports(), list_ports_winreg.comports_list(), list_ports_windows.comports() Note: This should include virtual comports, and it is significantly faster than list_ports_windows.comports(). However, list_ports_windows has far more information. comports() contains all list_ports_windows.comports() and winreg_comports() that were not found from list_ports_windows. Returns: comports (list): Sorted list of ListPortInfo. """ try: # Get the Serial Coms registry key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, SERIAL_REGISTRY_PATH) # Get key info - number of values (subkeys, num_vals, last_modified) num_values = winreg.QueryInfoKey(key)[1] # Make a generator of comports for i in range(num_values): # get registry value for the comport value = winreg.EnumValue(key, i) yield regval_to_listport(value) # Close the registry key winreg.CloseKey(key) except (AttributeError, WindowsError, EnvironmentError): # winreg is None or there was a key error pass # end winreg_comports def comports_list(): """Return a list of comports found from list_ports_windows and comports found in the window registry. See Also: list_ports_winreg.comports(), list_ports_winreg.winreg_comports(), list_ports_windows.comports() Note: This should include virtual comports. This method contains all list_ports_windows.comports() and winreg_comports() that were not found from list_ports_windows. Returns: comports (list): List of ListPortInfo comport details. """ comports = list(list_ports_windows.comports()) comports[len(comports):] = [li for li in winreg_comports() if li not in comports] return comports # end comports_list def comports(include_links=False): """Generator for comports found from list ports windows and comports found in the windows registry. See Also: list_ports_winreg.comports_list(), list_ports_winreg.winreg_comports(), list_ports_windows.comports() Note: This should include virtual comports. This method contains all list_ports_windows.comports() and winreg_comports() that were not found from list_ports_windows. Yields: comport (ListPortInfo): Comport details. Returns: comports (generator): Generator of ListPortInfo comports. """ existing = [] for comport in list_ports_windows.comports(): existing.append(comport) yield comport for li in winreg_comports(): if li not in existing: existing.append(li) yield li # end comports # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # test if __name__ == '__main__': for port, desc, hwid in sorted(comports()): print("%s: %s [%s]" % (port, desc, hwid))