小言_互联网的博客

自动识别查找特定的串口号 比如设备管理器中Modem属性里的串口 按这个方法可以获取设备管理器任意信息。C++

971人阅读  评论(0)

1.目标: 自动识别查找特定的串口号

2.注册表里搜串口号

设备管理器中所有的信息都在注册表中有,那么我直接在注册表里搜COM143。

搜到了这个,但这里有2个名称key相同的。后面193,192还是可能会变的,不方便精确识别。继续搜。

这里可以。 

 最后一个了。

共有5个地方存在:

计算机\HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM
计算机\HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Class\{4d36e96d-e325-11ce-bfc1-08002be10318}\0010
计算机\HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Enum\USB\VID_05C6&PID_9091&MI_01\6&c6a59d9&0&0001\Device Parameters
计算机\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4d36e96d-e325-11ce-bfc1-08002be10318}\0010
计算机\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USB\VID_05C6&PID_9091&MI_01\6&c6a59d9&0&0001\Device Parameters 

 计算机\HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM列出了所有串口

3.具体筛选

1)看看ControlSet001、ControlSet002、CurrentControlSet的区别

1、ControlSet001:系统真实的配置信息
2、ControlSet002:最后一次成功启动的配置信息
3、CurrentControlSet:系统运行时的配置信息

一、系统启动时,从ControlSet001复制到CurrentControlSet中。
二、系统运行时,修改的都是CurrentControlSet中的信息。
三、系统重启时,从CurrentControlSet复制到ControlSet001中。
四、系统正常启动时,从ControlSet001和CurrentControlSet复制到ControlSet002。
五、开机选择“最近一次正确配置”时,从ControlSet002复制到CurrentControlSet中。

所有选CurrentControlSet分支。

2)Control与Enum分支的区别

Windows驱动有三种注册表键负责配置。它们是硬件(或实例), 类和 服务。

  • 硬件(或实例)键包含单个设备的信息。
  • 类键涉及所有相同类型设备的共同信息。
  • 服务键包含驱动程序信息。
注册表 路径
硬件(hardware)键 [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\ Enum\总线\硬件ID]
类(class)键 [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\ Control\Class\GUID]
服务(service)键 [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\ Services\服务名]

因为GUID我可以获取,我这里选Control,即

计算机\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4d36e96d-e325-11ce-bfc1-08002be10318}\0010

4.代码实现

C# python自动获取modem里的串口号 高通芯片C++ MFC_小黄人软件的博客-CSDN博客

C++ C#自动获得特定串口 获得串口列表_小黄人软件的博客-CSDN博客_c#获取串口列表

C++实现:

先拼成注册表路径,再读注册表。

 


  
  1. // PrintDeviceInfo.cpp : 定义控制台应用程序的入口点。
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <locale.h>
  5. #include <Windows.h>
  6. #include <setupapi.h>
  7. #pragma comment(lib, "setupapi.lib")
  8. // 注册表 找特定的串口号
  9. //计算机\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4d36e96d-e325-11ce-bfc1-08002be10318}\0010
  10. //AttachedTo=?
  11. //return 特定的串口号 或 -1没找到特定串口 -2打开串口注册表 失败
  12. int getF200SpecialComNumByRegister(char *guid)
  13. {
  14. HKEY hkey;
  15. int result;
  16. int i = 0;
  17. //char path[100] = "SYSTEM\\CurrentControlSet\\Control\\Class\\{4d36e96d-e325-11ce-bfc1-08002be10318}\\0010";
  18. char path[ 100] = "SYSTEM\\CurrentControlSet\\Control\\Class\\";
  19. strcat_s(path, guid);
  20. result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, path, NULL, KEY_READ, &hkey);
  21. if (ERROR_SUCCESS == result) //打开串口注册表
  22. {
  23. do
  24. {
  25. TCHAR portName[ 0x100] = { 0 }; //portName是注册表名称(不是设备管理器里的前缀),commName就是值 串口名字COMN
  26. TCHAR commName[ 0x100] = { 0 };
  27. DWORD dwSize = sizeof(portName) / sizeof(TCHAR);
  28. DWORD dwLong = dwSize;
  29. result = RegEnumValue(hkey, i, portName, &dwLong, NULL, NULL, (LPBYTE)commName, &dwSize);
  30. if (ERROR_NO_MORE_ITEMS == result) { break; } // 枚举串口
  31. printf( "%d %s %s\n", i, portName, commName); //显示名称及值
  32. if (( strcmp(portName, "AttachedTo") == 0)) //特定串口
  33. {
  34. RegCloseKey(hkey); //关闭注册表
  35. return atoi(commName + 3); //去掉COM只取号 正常返回
  36. }
  37. i++;
  38. } while (TRUE);
  39. RegCloseKey(hkey); //关闭注册表
  40. return -1; //没找到特定串口
  41. }
  42. return -2; //打开串口注册表 失败
  43. }
  44. //获取特定串口号 示例Qualcomm HS-USB Diagnostics 9091 (COM20)
  45. int getSpecialComNum(const char *in)
  46. {
  47. char out[ 100] = { 0 };
  48. sscanf_s(in, "Qualcomm HS-USB Diagnostics 9091 (COM%[0-9])", out, sizeof(out)); //不是%d哦
  49. return atoi(out);
  50. }
  51. //从设备信息中 获取特定串口号 @return <=0无效
  52. int getSpecialComNumFromDevInfo()
  53. {
  54. printf( "Locale is: %s\n", setlocale(LC_ALL, "chs")); //设置为中文
  55. HDEVINFO hDevInfo = SetupDiGetClassDevs( NULL, NULL, NULL, DIGCF_PRESENT|DIGCF_ALLCLASSES);
  56. if (hDevInfo == INVALID_HANDLE_VALUE)
  57. {
  58. printf( "SetupDiGetClassDevs Err:%d", GetLastError());
  59. return -2;
  60. };
  61. SP_DEVINFO_DATA spDevInfoData = { 0 };
  62. spDevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
  63. for (DWORD i = 0; SetupDiEnumDeviceInfo(hDevInfo, i, &spDevInfoData); i++)
  64. {
  65. //char szBuf[MAX_PATH] = { 0 };
  66. //if (!SetupDiGetDeviceRegistryPropertyA(hDevInfo, &spDevInfoData, SPDRP_CLASS, NULL, (PBYTE)szBuf, MAX_PATH, 0)) { continue; };
  67. //if (strcmp(szBuf, "Ports") != 0 && strcmp(szBuf, "Modem") != 0) //只取端口
  68. //{ continue; }
  69. char szName[MAX_PATH] = { 0 };
  70. if ( SetupDiGetDeviceRegistryPropertyA(hDevInfo, &spDevInfoData, SPDRP_FRIENDLYNAME, NULL, (PBYTE)szName, MAX_PATH - 1, 0))
  71. {
  72. if ( strcmp(szName, "Qualcomm HS-USB Modem 9091 #3") != 0) { continue; } //只取这个
  73. printf( "FriendlyName:%s\r\n", szName);
  74. }
  75. else { continue; }
  76. memset(szName, 0, sizeof(szName));
  77. if ( SetupDiGetDeviceRegistryPropertyA(hDevInfo, &spDevInfoData, SPDRP_DRIVER, NULL, (PBYTE)szName, MAX_PATH - 1, 0))
  78. {
  79. printf( "%d Device:%s\r\n", i, szName);
  80. return getF200SpecialComNumByRegister(szName);
  81. break;
  82. }
  83. }
  84. SetupDiDestroyDeviceInfoList(hDevInfo);
  85. printf( "Can not find Modem COM");
  86. return -4;
  87. }
  88. int main(int argc, char* argv[])
  89. {
  90. printf( "自动识别串口号:%d\n", getSpecialComNumFromDevInfo());
  91. getchar();
  92. return 0;
  93. }

按这个方法可以获取设备管理器任意信息。

 


转载:https://blog.csdn.net/chenhao0568/article/details/128862067
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场