Форум Микро-Чип
Поиск и заказ электронных компонентов
 

Вернуться   Форум Микро-Чип > Общетехнические вопросы

Общетехнические вопросы Общие вопросы аналоговой и цифровой электроники.

Ответ
 
Опции темы Опции просмотра
Старый 26.07.2018, 18:16   #1
DimaS
Senior Member
 
Регистрация: 05.04.2008
Адрес: Israel
Возраст: 45
Сообщений: 1,538
Вес репутации: 2283/77
DimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond repute
По умолчанию Узнать СОМ порты под Виндой

Даже не знаю куда лучше написать.
Чтобы под виндой получить список СОМ-портов я делаю так (считывние в ComboBox, Борданд Билдер):
Код:
  TRegistry *reg = new TRegistry(KEY_READ);
  try
  {
    reg->RootKey = HKEY_LOCAL_MACHINE;
    // False because we do not want to create it if it doesn't exist
    reg->OpenKey("HARDWARE\\DEVICEMAP\\SERIALCOMM",false);
    TStringList* ts = new TStringList();
    reg->GetValueNames(ts);
    //i=ts->Count;
    ComboBox1->Items->Clear();

    for (int i=0;i<ts->Count;i++){
          ComboBox1->Items->Add(reg->ReadString(ts->Strings[i]));
    }
    delete ts;

    reg->CloseKey();
  }
  __finally
  {
    delete reg;
  }

В результате получаю список стрингов типа "COM1", "COM3", "COM10", "COM58" и т.п.
Но как сделать так, чтобы в сточках были не только номера СОМх, но и как в девайс менеджере - название интерйеса?
Ну типа "STM32 Virtual Com Port (COM10)" ?
DimaS вне форума   Ответить с цитированием
Старый 26.07.2018, 22:09   #2
Sergey K
Senior Member
 
Регистрация: 23.10.2008
Адрес: Киев
Возраст: 36
Сообщений: 268
Вес репутации: 422/44
Sergey K is just really niceSergey K is just really niceSergey K is just really niceSergey K is just really niceSergey K is just really nice
По умолчанию Re: Узнать СОМ порты под Виндой

Под Дельфями делал в том-же направлении, через реестр:

Код:
//Получаем имя порта
      if Reg.OpenKeyReadOnly('\System\CurrentControlSet\Enum\'+EnumList.Strings[i]+'\Device Parameters') then
        begin
        //Имя порта
        S:=Reg.ReadString('PortName');
        //Ищем его в нашем списке
        idx:=PortSel.Items.IndexOf(S);
        end;
      Reg.CloseKey;
      //Получаем дружелюбное имя
      if Reg.OpenKeyReadOnly('\System\CurrentControlSet\Enum\'+EnumList.Strings[i]) then
        begin
        S:=S+'='+Reg.ReadString('FriendlyName');
Получаю:
Код:
COM1=Последовательный порт (COM1)
COM5=PCI Serial Port (COM5)
Sergey K вне форума   Ответить с цитированием
Старый 27.07.2018, 17:11   #3
DimaS
Senior Member
 
Регистрация: 05.04.2008
Адрес: Israel
Возраст: 45
Сообщений: 1,538
Вес репутации: 2283/77
DimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond repute
По умолчанию Re: Узнать СОМ порты под Виндой

Что-то пока не получается.
Откуда
EnumList.Strings[i берется?
DimaS вне форума   Ответить с цитированием
Старый 27.07.2018, 19:38   #4
БОЦМАН
Senior Member
 
Регистрация: 04.02.2012
Адрес: Хабаровск
Сообщений: 648
Вес репутации: 1168/43
БОЦМАН has much to be proud ofБОЦМАН has much to be proud ofБОЦМАН has much to be proud ofБОЦМАН has much to be proud ofБОЦМАН has much to be proud ofБОЦМАН has much to be proud ofБОЦМАН has much to be proud ofБОЦМАН has much to be proud ofБОЦМАН has much to be proud of
По умолчанию Re: Узнать СОМ порты под Виндой

Чтобы возиться с кучей всяких преобразователей, насвинячил для навигации в свое время VB-скрипт (файл COM X.vbs):
Код:
HKLM = &H80000002
strKeyPath = "HARDWARE\DEVICEMAP\SERIALCOMM"
On Error Resume Next
Set AE = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\default:StdRegProv")
Set W = createObject("WScript.Shell")
AE.EnumValues HKLM, strKeyPath, Names
if not isarray(Names) then str = "НЕТ СОМ-портов"
 For i = LBound(Names) To UBound(Names)
   AE.GetStringValue HKLM, strKeyPath, Names(i), PORT
   str = str & PORT & VBtab & Names(i) & VbCrLf
next
 W.Popup STR,3
Идея наваять что-то "более" была успешно заброшена, остались кое какие ссылки по вопросу:
http://www.codeproject.com/KB/hardwa...ssLibrary.aspx
https://www.codeproject.com/Articles...ect-USB-Drives
Windows Management Instrumentation (WMI) позволит собрать кучу инфы про девайсы, подключенные к компу!
https://www.microsoft.com/en-us/down...s.aspx?id=8572
https://docs.microsoft.com/ru-ru/win...n32-serialport
https://docs.microsoft.com/ru-ru/win...ieving-a-class
БОЦМАН вне форума   Ответить с цитированием
Старый 27.07.2018, 21:31   #5
Sergey K
Senior Member
 
Регистрация: 23.10.2008
Адрес: Киев
Возраст: 36
Сообщений: 268
Вес репутации: 422/44
Sergey K is just really niceSergey K is just really niceSergey K is just really niceSergey K is just really niceSergey K is just really nice
По умолчанию Re: Узнать СОМ порты под Виндой

Цитата:
Сообщение от DimaS Посмотреть сообщение
Что-то пока не получается.
Откуда
EnumList.Strings[i берется?
Ранее список заполняется по функции, которую Вы приводили. Загляните сами в эту ветку реестра, и я думаю, Вам станет все понятно. Я очень давно это делал.
Sergey K вне форума   Ответить с цитированием
Старый 28.07.2018, 09:38   #6
DimaS
Senior Member
 
Регистрация: 05.04.2008
Адрес: Israel
Возраст: 45
Сообщений: 1,538
Вес репутации: 2283/77
DimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond repute
По умолчанию Re: Узнать СОМ порты под Виндой

Цитата:
Сообщение от Sergey K Посмотреть сообщение
Ранее список заполняется по функции, которую Вы приводили. Загляните сами в эту ветку реестра, и я думаю, Вам станет все понятно. Я очень давно это делал.

Пытался, но пока не понял.
idx:=PortSel.Items.IndexOf(S); - эт что за функиця?
И зачем, если idx больше не используется?
DimaS вне форума   Ответить с цитированием
Старый 28.07.2018, 22:22   #7
Sergey K
Senior Member
 
Регистрация: 23.10.2008
Адрес: Киев
Возраст: 36
Сообщений: 268
Вес репутации: 422/44
Sergey K is just really niceSergey K is just really niceSergey K is just really niceSergey K is just really niceSergey K is just really nice
По умолчанию Re: Узнать СОМ порты под Виндой

Я привел кусочек кода.
Там сначала заполняется выпадающий список именами портов (СОМ1, СОМ5 и т.д.).
Далее, поочередно этот номер порта подставляется в ветку реестра "\System\CurrentControlSet\Enum\*", где есть ключ "FriendlyName". Далее имя порта + это самое "FriendlyName" заменяет в выпадающем списке просто название порта.

idx:=PortSel.Items.IndexOf(S); - находит в списке индекс строки, в которой упоминается строка "S" (в ней содержится имя порта (СОМ1)), чтобы затем заменить просто имя(номер) порта на "FriendlyName" (т.е. с описанием что это).

Код:
S:=Reg.ReadString('PortName');
...
idx:=PortSel.Items.IndexOf(S);
...
S:=S+'='+Reg.ReadString('FriendlyName');
...
PortSel.Items.Strings[idx]:=S;
Sergey K вне форума   Ответить с цитированием
Старый 28.07.2018, 22:35   #8
DimaS
Senior Member
 
Регистрация: 05.04.2008
Адрес: Israel
Возраст: 45
Сообщений: 1,538
Вес репутации: 2283/77
DimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond repute
По умолчанию Re: Узнать СОМ порты под Виндой

Цитата:
Сообщение от Sergey K Посмотреть сообщение
Я привел кусочек кода.
Там сначала заполняется выпадающий список именами портов (СОМ1, СОМ5 и т.д.).


Так PortSel это и есть этот список?

Цитата:
Далее, поочередно этот номер порта подставляется в ветку реестра "\System\CurrentControlSet\Enum\*", где есть ключ "FriendlyName". Далее имя порта + это самое "FriendlyName" заменяет в выпадающем списке просто название порта.

Это я все понял, но я не вижу у себя в реестре ветки типа
"\System\CurrentControlSet\Enum\COMx


А ФрендлиНейм находится например тут:
"\System\CurrentControlSet\Enum\USB\0000000000 01A\


И как мне по номеру СОМ порта найти ветку USB\000000000001A\ я и не понял.
DimaS вне форума   Ответить с цитированием
Старый 29.07.2018, 23:19   #9
Sergey K
Senior Member
 
Регистрация: 23.10.2008
Адрес: Киев
Возраст: 36
Сообщений: 268
Вес репутации: 422/44
Sergey K is just really niceSergey K is just really niceSergey K is just really niceSergey K is just really niceSergey K is just really nice
По умолчанию Re: Узнать СОМ порты под Виндой

Проглянул код еще раз, внимательнее, я немного не точно сказал. В ветке \System\CurrentControlSet\Services\SerEnum\Enum есть параметры "0", "1", "2"... и так до "Count" - это все СОМ-порты, а значения этих параметров (MF\PCI#VEN_9710&DEV_9835&SUBSYS_00121000&REV_01\5& 12c9c843&0&08F0#Child0001) это код устройства в системе.
Оно сохраняется в EnumList.Strings[i].
Далее подставляется в HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\MF\PCI#VEN_9710&DEV_9835&SUBSYS_00121000&REV_01\5& 12c9c843&0&08F0#Child0001 и там есть искомое "FriendlyName" = "PCI Serial Port (COM5)", но оно есть не у всех портов.
Из ветки HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\M F\PCI#VEN_9710&DEV_9835&SUBSYS_00121000&REV_01\5&1 2c9c843&0&08F0#Child0001\Device Parameters я беру имя порта ("СОМ5").
Sergey K вне форума   Ответить с цитированием
Старый 01.08.2018, 11:01   #10
siarzhuk
Senior Member
 
Аватар для siarzhuk
 
Регистрация: 08.11.2014
Возраст: 48
Сообщений: 158
Вес репутации: 1161/27
siarzhuk has much to be proud ofsiarzhuk has much to be proud ofsiarzhuk has much to be proud ofsiarzhuk has much to be proud ofsiarzhuk has much to be proud ofsiarzhuk has much to be proud ofsiarzhuk has much to be proud ofsiarzhuk has much to be proud ofsiarzhuk has much to be proud of
По умолчанию Re: Узнать СОМ порты под Виндой

Работаем через сервисы Setupapi.h

Код:
bool CollectAvailablePorts(std::map<DWORD, CString>& ports, bool bKnUSBOnly)
{
  //Make sure we clear out any elements which may already be in the array(s)
  ports.clear();

  //First need to convert the name "Ports" to a GUID using SetupDiClassGuidsFromName
  DWORD dwGuids = 0;
  SetupDiClassGuidsFromName(_T("Ports"), NULL, 0, &dwGuids);
  if (dwGuids == 0) {
    return false;
  }

  //Allocate the needed memory
  ATL::CHeapPtr<GUID> pGuids;
  if (!pGuids.Allocate(dwGuids)) {
    SetLastError(ERROR_OUTOFMEMORY);
    return false;
  }

  //Call the function again
  if (!SetupDiClassGuidsFromName(_T("Ports"), pGuids, dwGuids, &dwGuids)) {
    return false;
  }

  //Now create a "device information set" which is required to enumerate all the ports
  HDEVINFO hDevInfoSet = SetupDiGetClassDevs(pGuids, NULL, NULL, DIGCF_PRESENT);
  if (hDevInfoSet == INVALID_HANDLE_VALUE) {
    return false;
  }

  //Finally do the enumeration
  BOOL bMoreItems = TRUE;
  int nIndex = 0;
  SP_DEVINFO_DATA devInfo;
  while (bMoreItems) {
    //Enumerate the current device
    devInfo.cbSize = sizeof(SP_DEVINFO_DATA);
    bMoreItems = SetupDiEnumDeviceInfo(hDevInfoSet, nIndex, &devInfo);
    if (bMoreItems) {
      //Did we find a serial port for this device
      int nPort = -1;

      //Get the registry key which stores the ports settings
      HKEY hDeviceKey = SetupDiOpenDevRegKey(hDevInfoSet, &devInfo, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_QUERY_VALUE);
      if (hDeviceKey) {
        //Read in the name of the port
        TCHAR szPortName[256];
        szPortName[0] = _T('\0');
        DWORD dwSize = sizeof(szPortName);
        DWORD dwType = 0;
          if ((RegQueryValueEx(hDeviceKey, _T("PortName"), NULL, &dwType, reinterpret_cast<LPBYTE>(szPortName), &dwSize) == ERROR_SUCCESS)
            && (dwType == REG_SZ))
        {
//          TRACE(_T("%s\n"), szPortName);
          //If it looks like "COMX" then
          //add it to the array which will be returned
          size_t nLen = _tcslen(szPortName);
          if (nLen > 3) {
            if ((_tcsnicmp(szPortName, _T("COM"), 3) == 0) && IsNumeric(&(szPortName[3]), FALSE)) {
              //Work out the port number
              nPort = _ttoi(&(szPortName[3]));
            }
          }
        }

        //Close the key now that we are finished with it
        RegCloseKey(hDeviceKey);
      }

      //If the port was a serial port, then also try to get its friendly name
      if (nPort >= 0) {
        TCHAR szFriendlyName[256] = { 0 };
        DWORD dwSize = sizeof(szFriendlyName);
        DWORD dwType = 0;
        if (!(SetupDiGetDeviceRegistryProperty(hDevInfoSet, &devInfo, SPDRP_DEVICEDESC, &dwType,
                                                reinterpret_cast<PBYTE>(szFriendlyName), dwSize, &dwSize)
            && (dwType == REG_SZ)))
        {
          szFriendlyName[0] = _T('\0');
        }

        bool bInclude = !bKnUSBOnly;
        if (bKnUSBOnly) {
          CString strHardwareId;
          dwSize = 256;
          dwType = 0;
          if (SetupDiGetDeviceRegistryProperty(hDevInfoSet, &devInfo, SPDRP_HARDWAREID, &dwType,
                reinterpret_cast<PBYTE>(strHardwareId.GetBuffer(dwSize)), dwSize, &dwSize)
              && (dwType == REG_SZ || dwType == REG_MULTI_SZ)) {

            strHardwareId.ReleaseBuffer();
            strHardwareId.Replace('\\', ' ');
            strHardwareId.Replace('&', ' ');
            TCHAR buffer[128] = { 0 };
            DWORD dwVID = 0, dwPID = 0;

            if (4 == _stscanf(strHardwareId.GetString(),
                    _T("%s %s VID_%x PID_%x"), buffer, buffer, &dwVID, &dwPID))
              bInclude = CheckKnUSBIdentifiers(dwVID, dwPID);
          }
        }

        if (bInclude)
          ports.insert(std::pair<DWORD, CString>(nPort, szFriendlyName));
//        TRACE(_T("%d %s\n"), nPort, szFriendlyName);
      }
    }

    ++nIndex;
  }

  //Free up the "device information set" now that we are finished with it
  SetupDiDestroyDeviceInfoList(hDevInfoSet);

  //Return the success indicator
  return true;
}
думаю если поискать по именам SetupDi* функций то найдётся пример и без ATL/STL. ;-)



Ещё и WM_DEVICECHANGE обрабатываем, чтобы список менять на лету если это USB устройства и пользователь ими вдруг манипулировать вздумал.
siarzhuk вне форума   Ответить с цитированием
Старый 01.08.2018, 13:27   #11
Vint
Senior Member
 
Аватар для Vint
 
Регистрация: 08.06.2007
Сообщений: 501
Вес репутации: 838/56
Vint is a splendid one to beholdVint is a splendid one to beholdVint is a splendid one to beholdVint is a splendid one to beholdVint is a splendid one to beholdVint is a splendid one to beholdVint is a splendid one to behold
По умолчанию Re: Узнать СОМ порты под Виндой

Цитата:
Сообщение от DimaS Посмотреть сообщение
Даже не знаю куда лучше написать.
Чтобы под виндой получить список СОМ-портов я делаю так (считывние в ComboBox, Борданд Билдер):
Код:
  TRegistry *reg = new TRegistry(KEY_READ);
  try
  {
    reg->RootKey = HKEY_LOCAL_MACHINE;
    // False because we do not want to create it if it doesn't exist
    reg->OpenKey("HARDWARE\\DEVICEMAP\\SERIALCOMM",false);
    TStringList* ts = new TStringList();
    reg->GetValueNames(ts);
    //i=ts->Count;
    ComboBox1->Items->Clear();

    for (int i=0;i<ts->Count;i++){
          ComboBox1->Items->Add(reg->ReadString(ts->Strings[i]));
    }
    delete ts;

    reg->CloseKey();
  }
  __finally
  {
    delete reg;
  }

В результате получаю список стрингов типа "COM1", "COM3", "COM10", "COM58" и т.п.
Но как сделать так, чтобы в сточках были не только номера СОМх, но и как в девайс менеджере - название интерйеса?
Ну типа "STM32 Virtual Com Port (COM10)" ?
Есть штабной проект PIC32UBL- это утилита для работы
с бутлодырем. Но он на VStudio сделан. Вот оттуда функция,
она работает.
Вложения
Тип файла: rar comPort.rar (1.1 Кб, 6 просмотров)
Vint вне форума   Ответить с цитированием
Старый 10.08.2018, 11:18   #12
DimaS
Senior Member
 
Регистрация: 05.04.2008
Адрес: Israel
Возраст: 45
Сообщений: 1,538
Вес репутации: 2283/77
DimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond repute
По умолчанию Re: Узнать СОМ порты под Виндой

Цитата:
это утилита для работы
с бутлодырем. Но он на VStudio сделан. Вот оттуда функция,
она работает.

Функция может и работает, только я виду там функцию OpenPort а не определение номеров портов и их названий в системе.
DimaS вне форума   Ответить с цитированием
Ответ


Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
 
Опции темы
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход


Часовой пояс GMT +3, время: 23:36.


Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, Jelsoft Enterprises Ltd. Перевод: zCarot