目的:自动获得特定串口。
// PrintDeviceInfo.cpp : 定义控制台应用程序的入口点。
#include
#include
#include
#include
#include
#pragma comment(lib, "setupapi.lib")
//获取特定串口号 示例Qualcomm HS-USB Diagnostics 9091 (COM20)
int getSpecialComNum(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()
{
HDEVINFO hDevInfo = SetupDiGetClassDevs(NULL, NULL, NULL, DIGCF_PRESENT|DIGCF_ALLCLASSES);
if (hDevInfo == INVALID_HANDLE_VALUE)
{
printf("SetupDiGetClassDevs Err:%d", GetLastError());
return -2;
};
SP_CLASSIMAGELIST_DATA _spImageData = { 0 };
_spImageData.cbSize = sizeof(SP_CLASSIMAGELIST_DATA);
SetupDiGetClassImageList(&_spImageData);
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 };
int wImageIdx = 0;
short wItem = 0;
if (!SetupDiGetDeviceRegistryPropertyA(hDevInfo, &spDevInfoData, SPDRP_CLASS, NULL, (PBYTE)szBuf, MAX_PATH, 0))
{
continue;
};
if (strcmp(szBuf, "Ports") != 0) //只取端口
{
continue;
}
printf("Class1:%s\r\n", szBuf);
if (SetupDiGetClassImageIndex(&_spImageData, &spDevInfoData.ClassGuid, &wImageIdx))
{
char szName[MAX_PATH] = { 0 };
DWORD dwRequireSize;
if (!SetupDiGetClassDescription(&spDevInfoData.ClassGuid, (PWSTR)szBuf, MAX_PATH, &dwRequireSize))
{
continue;
};
wprintf(L"Class:%s\r\n", szBuf);
if (SetupDiGetDeviceRegistryProperty(hDevInfo, &spDevInfoData, SPDRP_FRIENDLYNAME, NULL, (PBYTE)szName, MAX_PATH - 1, 0))
{
wprintf(L"FriendlyName:%s\r\n\r\n", szName);
if (int comNum=getSpecialComNum(szName) > 0)
{
return comNum;
}
}
else if (SetupDiGetDeviceRegistryProperty(hDevInfo, &spDevInfoData, SPDRP_DEVICEDESC, NULL, (PBYTE)szName, MAX_PATH - 1, 0))
{
wprintf(L"Device:%s\r\n\r\n", szName);
}
}
}
SetupDiDestroyClassImageList(&_spImageData);
return - 1;
}
int main(int argc, char* argv[])
{
printf("Locale is: %s\n", setlocale(LC_ALL, "chs"));
printf("串口号:%d\n",getSpecialComNumFromDevInfo());
//PrintDevicesInfo2();
getchar();
return 0;
}
#include
#include
//***********************
// 枚举所有的串口,以及名称
//return 特定的串口号 或-1失败
//***********************
int EnumAllComm()
{
HKEY hkey;
int result;
int i = 0;
result = RegOpenKeyEx(HKEY_LOCAL_MACHINE,"Hardware\\DeviceMap\\SerialComm", 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, "\\Device\\QCUSB_COM5_2") == 0) //特定串口
{
return atoi(commName + 3);//去掉COM只取号 正常返回
}
i++;
} while (TRUE);
RegCloseKey(hkey); //关闭注册表
}
return -1;//没找到特定串口
}
int main()
{
std::cout << "Hello World!\n";
std::cout << "**************************Special COM:"<
注册表的key在不同的电脑上是否会变化?
//默认只找倒数第一个
int getCommNum()
{
HANDLE hCom;
int i;
BOOL flag;
char str[100] = {0};
flag = FALSE;
for (i = 30; i >= 1; i--)//此程序支持N个串口
{
sprintf(str,"\\\\.\\COM%d",i);
//printf("%s%s",str,"\n");
hCom = CreateFile(str, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (INVALID_HANDLE_VALUE != hCom)
{//能打开该串口,则添加该串口
CloseHandle(hCom);
return i;
}
}
return -1;
}
#define MY_USB_PID_VID_F200 _T("VID_05C6&PID_9018") //\\6&1DC4E91E&3
#define MY_USB_PID_VID_F210 _T("VID_18D1&PID_4001") //\\&MI_046&4592401&0&0004
#define MY_USB_PID_VID_F210_ELSE _T("VID_18D1&PID_4EE8")//这个在adb打开时存在
//获取特定串口号 示例Qualcomm HS-USB Diagnostics 9091 (COM20)
string getSpecialComNum(const char *in)
{
logger.INFO_F(FUN_LINE+in);
CString temp(in);
if (StrStr(temp, "Qualcomm HS-USB Android GPS 9018") == NULL && StrStr(temp, "USB 串行设备") == NULL)
{
return "";
}
int ret=getContentInBracket(temp);
if (ret != 0) { return ""; }
temp.Replace("COM","");
logger.INFO_F(FUN_LINE +" OK, COM"+ temp.GetBuffer());
return temp;
//char out[100] = { 0 };
//sscanf_s(in, "Qualcomm HS-USB Android GPS 9018 (COM%[0-9])", out, sizeof(out)); //不是%d哦
//return out;
}
//从设备信息中 获取特定串口号 @return <=0无效
int getSpecialComNumFromDevInfo()
{
HDEVINFO hDevInfo = SetupDiGetClassDevs(NULL, NULL, NULL, DIGCF_PRESENT | DIGCF_ALLCLASSES);
if (hDevInfo == INVALID_HANDLE_VALUE)
{
printf("SetupDiGetClassDevs Err:%d", GetLastError());
return -2;
};
SP_CLASSIMAGELIST_DATA _spImageData = { 0 };
_spImageData.cbSize = sizeof(SP_CLASSIMAGELIST_DATA);
SetupDiGetClassImageList(&_spImageData);
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 };
int wImageIdx = 0;
short wItem = 0;
if (!SetupDiGetDeviceRegistryPropertyA(hDevInfo, &spDevInfoData, SPDRP_CLASS, NULL, (PBYTE)szBuf, MAX_PATH, 0))
{
continue;
};
if (strcmp(szBuf, "Ports") != 0) //只取端口
{
continue;
}
printf("Class1:%s\r\n", szBuf);
// PID_VID 识别 筛选出实际串口
DWORD nSize = 0;
TCHAR szDis[MAX_PATH] = { 0x00 };// 存储设备实例ID
if (!SetupDiGetDeviceInstanceId(hDevInfo, &spDevInfoData, szDis, sizeof(szDis), &nSize)) { break; }
// 根据设备信息寻找VID PID一致的设备
CString strTemp;
strTemp.Format(_T("%s"), szDis);
logger.INFO_F(FUN_LINE+ szDis);
//strTemp.MakeUpper();
if ((strTemp.Find(MY_USB_PID_VID_F200, 0) == -1) && (strTemp.Find(MY_USB_PID_VID_F210, 0) == -1)) //没找到
{
logger.INFO_F(FUN_LINE+"USB_PID_VID mismatch.");
continue;
}
logger.INFO_F(FUN_LINE+"PID_VID Check OK.");
if (SetupDiGetClassImageIndex(&_spImageData, &spDevInfoData.ClassGuid, &wImageIdx))
{
char szName[MAX_PATH] = { 0 };
DWORD dwRequireSize;
if (!SetupDiGetClassDescriptionW(&spDevInfoData.ClassGuid, (PWSTR)szBuf, MAX_PATH, &dwRequireSize))
{
continue;
};
wprintf(L"Class:%s\r\n", szBuf);
if (SetupDiGetDeviceRegistryPropertyW(hDevInfo, &spDevInfoData, SPDRP_FRIENDLYNAME, NULL, (PBYTE)szName, MAX_PATH - 1, 0))
{
wprintf(L"FriendlyName:%s\r\n\r\n", szName);
int comNum = atoi(getSpecialComNum(wideCharToMultiByte((wchar_t *)szName)).c_str()); //根据特殊前缀来识别
if (comNum > 0)
{
return comNum;
}
logger.ERROR_F(FUN_LINE+" Com prefix mismatch.");
}
else if (SetupDiGetDeviceRegistryProperty(hDevInfo, &spDevInfoData, SPDRP_DEVICEDESC, NULL, (PBYTE)szName, MAX_PATH - 1, 0))
{
wprintf(L"Device:%s\r\n\r\n", szName);
}
else
{
logger.ERROR_F(FUN_LINE);
}
}
else
{
logger.ERROR_F(FUN_LINE);
}
}
SetupDiDestroyClassImageList(&_spImageData);
logger.ERROR_F(FUN_LINE);
return -1;
}
//是否插了设备 @return <=0无效
int isHaveDevice()
{
HDEVINFO hDevInfo = SetupDiGetClassDevs(NULL, NULL, NULL, DIGCF_PRESENT | DIGCF_ALLCLASSES);
if (hDevInfo == INVALID_HANDLE_VALUE)
{
printf("SetupDiGetClassDevs Err:%d", GetLastError());
return -2;
};
SP_CLASSIMAGELIST_DATA _spImageData = { 0 };
_spImageData.cbSize = sizeof(SP_CLASSIMAGELIST_DATA);
SetupDiGetClassImageList(&_spImageData);
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 };
int wImageIdx = 0;
short wItem = 0;
if (!SetupDiGetDeviceRegistryPropertyA(hDevInfo, &spDevInfoData, SPDRP_CLASS, NULL, (PBYTE)szBuf, MAX_PATH, 0))
{
continue;
};
if (strcmp(szBuf, "Ports") != 0) //只取端口
{
continue;
}
printf("Class1:%s\r\n", szBuf);
// PID_VID 识别 筛选出实际串口
DWORD nSize = 0;
TCHAR szDis[MAX_PATH] = { 0x00 };// 存储设备实例ID
if (!SetupDiGetDeviceInstanceId(hDevInfo, &spDevInfoData, szDis, sizeof(szDis), &nSize)) { break; }
// 根据设备信息寻找VID PID一致的设备
CString strTemp;
strTemp.Format(_T("%s"), szDis);
logger.INFO_F(FUN_LINE + szDis);
//strTemp.MakeUpper();
if ((strTemp.Find(MY_USB_PID_VID_F200, 0) == -1) && (strTemp.Find(MY_USB_PID_VID_F210, 0) == -1) && (strTemp.Find(MY_USB_PID_VID_F210_ELSE, 0) == -1)) //没找到
{
logger.INFO_F(FUN_LINE + "USB_PID_VID mismatch.");
continue;
}
logger.INFO_F(FUN_LINE + "PID_VID Check OK.");
return 0;
}
SetupDiDestroyClassImageList(&_spImageData);
logger.ERROR_F(FUN_LINE);
return -1;
}
C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Management;
using System.Text;
using System.Threading.Tasks;
namespace FT_M20
{
class MySerialPort
{
public static string strConvertToHexStr(string str)
{
string strHex = "";
foreach (byte b in str)
{
strHex += String.Format("{0:X2} ", b);
}
return strHex;
}
public static byte[] hexConvertToByteArray(String str)
{
str = str.Replace(" ", "");
byte[] b = new byte[str.Length / 2];
for (int i = 0; i < str.Length; i = i + 2)
{
b[i / 2] = (byte)Convert.ToInt32(str.Substring(i, 2), 16); //将十六进制“10”转换为十进制i
}
return b;
}
///
/// Get the target com num.
///
///
public static string GetComName()
{
string[] strArr = GetHarewareInfo(HardwareEnum.Win32_PnPEntity, "Name");
foreach (string s in strArr)
{
//Quectel USB Serial - 1 Port(COM7)
if (s.Contains("COM"))
{
if (s.Contains("Quectel USB Serial-1"))
{
//Log(s);
return return "COM"+ Regex.Match(s, @"\(COM(?\d+)").Groups["port"].Value; //从(COM20)提取串口号
}
}
}
return null;
}
///
/// Get the system devices information with windows api.
///
/// Device type.
/// the property of the device.
///
public static string[] GetHarewareInfo(HardwareEnum hardType, string propKey)
{
List strs = new List();
try
{
using (ManagementObjectSearcher searcher = new ManagementObjectSearcher("select * from " + hardType))
{
var hardInfos = searcher.Get();
foreach (var hardInfo in hardInfos)
{
if (hardInfo.Properties[propKey].Value != null)
{
String str = hardInfo.Properties[propKey].Value.ToString();
strs.Add(str);
}
}
}
return strs.ToArray();
}
catch
{
return null;
}
finally
{
strs = null;
}
}//end of func GetHarewareInfo().
///
/// 枚举win32 api
///
public enum HardwareEnum
{
// 硬件
Win32_Processor, // CPU 处理器
Win32_PhysicalMemory, // 物理内存条
Win32_Keyboard, // 键盘
Win32_PointingDevice, // 点输入设备,包括鼠标。
Win32_FloppyDrive, // 软盘驱动器
Win32_DiskDrive, // 硬盘驱动器
Win32_CDROMDrive, // 光盘驱动器
Win32_BaseBoard, // 主板
Win32_BIOS, // BIOS 芯片
Win32_ParallelPort, // 并口
Win32_SerialPort, // 串口
Win32_SerialPortConfiguration, // 串口配置
Win32_SoundDevice, // 多媒体设置,一般指声卡。
Win32_SystemSlot, // 主板插槽 (ISA & PCI & AGP)
Win32_USBController, // USB 控制器
Win32_NetworkAdapter, // 网络适配器
Win32_NetworkAdapterConfiguration, // 网络适配器设置
Win32_Printer, // 打印机
Win32_PrinterConfiguration, // 打印机设置
Win32_PrintJob, // 打印机任务
Win32_TCPIPPrinterPort, // 打印机端口
Win32_POTSModem, // MODEM
Win32_POTSModemToSerialPort, // MODEM 端口
Win32_DesktopMonitor, // 显示器
Win32_DisplayConfiguration, // 显卡
Win32_DisplayControllerConfiguration, // 显卡设置
Win32_VideoController, // 显卡细节。
Win32_VideoSettings, // 显卡支持的显示模式。
// 操作系统
Win32_TimeZone, // 时区
Win32_SystemDriver, // 驱动程序
Win32_DiskPartition, // 磁盘分区
Win32_LogicalDisk, // 逻辑磁盘
Win32_LogicalDiskToPartition, // 逻辑磁盘所在分区及始末位置。
Win32_LogicalMemoryConfiguration, // 逻辑内存配置
Win32_PageFile, // 系统页文件信息
Win32_PageFileSetting, // 页文件设置
Win32_BootConfiguration, // 系统启动配置
Win32_ComputerSystem, // 计算机信息简要
Win32_OperatingSystem, // 操作系统信息
Win32_StartupCommand, // 系统自动启动程序
Win32_Service, // 系统安装的服务
Win32_Group, // 系统管理组
Win32_GroupUser, // 系统组帐号
Win32_UserAccount, // 用户帐号
Win32_Process, // 系统进程
Win32_Thread, // 系统线程
Win32_Share, // 共享
Win32_NetworkClient, // 已安装的网络客户端
Win32_NetworkProtocol, // 已安装的网络协议
Win32_PnPEntity,//all device
}
}
}
或者