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++实现:
先拼成注册表路径,再读注册表。
// PrintDeviceInfo.cpp : 定义控制台应用程序的入口点。
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
#include <Windows.h>
#include <setupapi.h>
#pragma comment(lib, "setupapi.lib")
// 注册表 找特定的串口号
//计算机\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4d36e96d-e325-11ce-bfc1-08002be10318}\0010
//AttachedTo=?
//return 特定的串口号 或 -1没找到特定串口 -2打开串口注册表 失败
int getF200SpecialComNumByRegister(char *guid)
{
HKEY hkey;
int result;
int i = 0;
//char path[100] = "SYSTEM\\CurrentControlSet\\Control\\Class\\{4d36e96d-e325-11ce-bfc1-08002be10318}\\0010";
char path[100] = "SYSTEM\\CurrentControlSet\\Control\\Class\\";
strcat_s(path, guid);
result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, path, NULL, KEY_READ, &hkey);
if (ERROR_SUCCESS == result) //打开串口注册表
{
do
{
TCHAR portName[0x100] = { 0 };//portName是注册表名称(不是设备管理器里的前缀),commName就是值 串口名字COMN
TCHAR commName[0x100] = { 0 };
DWORD dwSize = sizeof(portName) / sizeof(TCHAR);
DWORD dwLong = dwSize;
result = RegEnumValue(hkey, i, portName, &dwLong, NULL, NULL, (LPBYTE)commName, &dwSize);
if (ERROR_NO_MORE_ITEMS == result) { break; } // 枚举串口
printf("%d %s %s\n", i, portName, commName); //显示名称及值
if ((strcmp(portName, "AttachedTo") == 0)) //特定串口
{
RegCloseKey(hkey); //关闭注册表
return atoi(commName + 3);//去掉COM只取号 正常返回
}
i++;
} while (TRUE);
RegCloseKey(hkey); //关闭注册表
return -1;//没找到特定串口
}
return -2;//打开串口注册表 失败
}
//获取特定串口号 示例Qualcomm HS-USB Diagnostics 9091 (COM20)
int getSpecialComNum(const char *in)
{
char out[100] = { 0 };
sscanf_s(in, "Qualcomm HS-USB Diagnostics 9091 (COM%[0-9])", out,sizeof(out)); //不是%d哦
return atoi(out);
}
//从设备信息中 获取特定串口号 @return <=0无效
int getSpecialComNumFromDevInfo()
{
printf("Locale is: %s\n", setlocale(LC_ALL, "chs"));//设置为中文
HDEVINFO hDevInfo = SetupDiGetClassDevs(NULL, NULL, NULL, DIGCF_PRESENT|DIGCF_ALLCLASSES);
if (hDevInfo == INVALID_HANDLE_VALUE)
{
printf("SetupDiGetClassDevs Err:%d", GetLastError());
return -2;
};
SP_DEVINFO_DATA spDevInfoData = { 0 };
spDevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
for (DWORD i = 0; SetupDiEnumDeviceInfo(hDevInfo, i, &spDevInfoData); i++)
{
//char szBuf[MAX_PATH] = { 0 };
//if (!SetupDiGetDeviceRegistryPropertyA(hDevInfo, &spDevInfoData, SPDRP_CLASS, NULL, (PBYTE)szBuf, MAX_PATH, 0)) { continue; };
//if (strcmp(szBuf, "Ports") != 0 && strcmp(szBuf, "Modem") != 0) //只取端口
//{ continue; }
char szName[MAX_PATH] = { 0 };
if (SetupDiGetDeviceRegistryPropertyA(hDevInfo, &spDevInfoData, SPDRP_FRIENDLYNAME, NULL, (PBYTE)szName, MAX_PATH - 1, 0))
{
if (strcmp(szName, "Qualcomm HS-USB Modem 9091 #3") != 0) { continue; } //只取这个
printf("FriendlyName:%s\r\n", szName);
}
else { continue; }
memset(szName,0,sizeof(szName));
if (SetupDiGetDeviceRegistryPropertyA(hDevInfo, &spDevInfoData, SPDRP_DRIVER, NULL, (PBYTE)szName, MAX_PATH - 1, 0))
{
printf("%d Device:%s\r\n", i, szName);
return getF200SpecialComNumByRegister(szName);
break;
}
}
SetupDiDestroyDeviceInfoList(hDevInfo);
printf("Can not find Modem COM");
return -4;
}
int main(int argc, char* argv[])
{
printf("自动识别串口号:%d\n",getSpecialComNumFromDevInfo());
getchar();
return 0;
}
按这个方法可以获取设备管理器任意信息。