当前位置:   article > 正文

C++ C#自动获得特定串口 获得串口列表_c++ 获取串口列表

c++ 获取串口列表

目的:自动获得特定串口。 

0、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. //获取特定串口号 示例Qualcomm HS-USB Diagnostics 9091 (COM20)
  9. int getSpecialComNum(char *in)
  10. {
  11. char out[100] = { 0 };
  12. sscanf_s(in, "Qualcomm HS-USB Diagnostics 9091 (COM%[0-9])", out,sizeof(out)); //不是%d哦
  13. return atoi(out);
  14. }
  15. //从设备信息中 获取特定串口号 @return <=0无效
  16. int getSpecialComNumFromDevInfo()
  17. {
  18. HDEVINFO hDevInfo = SetupDiGetClassDevs(NULL, NULL, NULL, DIGCF_PRESENT|DIGCF_ALLCLASSES);
  19. if (hDevInfo == INVALID_HANDLE_VALUE)
  20. {
  21. printf("SetupDiGetClassDevs Err:%d", GetLastError());
  22. return -2;
  23. };
  24. SP_CLASSIMAGELIST_DATA _spImageData = { 0 };
  25. _spImageData.cbSize = sizeof(SP_CLASSIMAGELIST_DATA);
  26. SetupDiGetClassImageList(&_spImageData);
  27. SP_DEVINFO_DATA spDevInfoData = { 0 };
  28. spDevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
  29. for (DWORD i = 0; SetupDiEnumDeviceInfo(hDevInfo, i, &spDevInfoData); i++)
  30. {
  31. char szBuf[MAX_PATH] = { 0 };
  32. int wImageIdx = 0;
  33. short wItem = 0;
  34. if (!SetupDiGetDeviceRegistryPropertyA(hDevInfo, &spDevInfoData, SPDRP_CLASS, NULL, (PBYTE)szBuf, MAX_PATH, 0))
  35. {
  36. continue;
  37. };
  38. if (strcmp(szBuf, "Ports") != 0) //只取端口
  39. {
  40. continue;
  41. }
  42. printf("Class1:%s\r\n", szBuf);
  43. if (SetupDiGetClassImageIndex(&_spImageData, &spDevInfoData.ClassGuid, &wImageIdx))
  44. {
  45. char szName[MAX_PATH] = { 0 };
  46. DWORD dwRequireSize;
  47. if (!SetupDiGetClassDescription(&spDevInfoData.ClassGuid, (PWSTR)szBuf, MAX_PATH, &dwRequireSize))
  48. {
  49. continue;
  50. };
  51. wprintf(L"Class:%s\r\n", szBuf);
  52. if (SetupDiGetDeviceRegistryProperty(hDevInfo, &spDevInfoData, SPDRP_FRIENDLYNAME, NULL, (PBYTE)szName, MAX_PATH - 1, 0))
  53. {
  54. wprintf(L"FriendlyName:%s\r\n\r\n", szName);
  55. if (int comNum=getSpecialComNum(szName) > 0)
  56. {
  57. return comNum;
  58. }
  59. }
  60. else if (SetupDiGetDeviceRegistryProperty(hDevInfo, &spDevInfoData, SPDRP_DEVICEDESC, NULL, (PBYTE)szName, MAX_PATH - 1, 0))
  61. {
  62. wprintf(L"Device:%s\r\n\r\n", szName);
  63. }
  64. }
  65. }
  66. SetupDiDestroyClassImageList(&_spImageData);
  67. return - 1;
  68. }
  69. int main(int argc, char* argv[])
  70. {
  71. printf("Locale is: %s\n", setlocale(LC_ALL, "chs"));
  72. printf("串口号:%d\n",getSpecialComNumFromDevInfo());
  73. //PrintDevicesInfo2();
  74. getchar();
  75. return 0;
  76. }

1、C++注册表方式

  1. #include <iostream>
  2. #include <windows.h>
  3. //***********************
  4. // 枚举所有的串口,以及名称
  5. //return 特定的串口号 或-1失败
  6. //***********************
  7. int EnumAllComm()
  8. {
  9. HKEY hkey;
  10. int result;
  11. int i = 0;
  12. result = RegOpenKeyEx(HKEY_LOCAL_MACHINE,"Hardware\\DeviceMap\\SerialComm", NULL, KEY_READ, &hkey);
  13. if (ERROR_SUCCESS == result) //打开串口注册表
  14. {
  15. do
  16. {
  17. TCHAR portName[0x100] = { 0 };//portName是注册表名称(不是设备管理器里的前缀),commName就是值 串口名字COMN
  18. TCHAR commName[0x100] = {0};
  19. DWORD dwSize = sizeof(portName) / sizeof(TCHAR);
  20. DWORD dwLong = dwSize;
  21. result = RegEnumValue(hkey, i, portName, &dwLong, NULL, NULL, (LPBYTE)commName, &dwSize);
  22. if (ERROR_NO_MORE_ITEMS == result) {break; } // 枚举串口
  23. printf("%d %s %s\n", i, portName, commName); //显示名称及值
  24. if (strcmp(portName, "\\Device\\QCUSB_COM5_2") == 0) //特定串口
  25. {
  26. return atoi(commName + 3);//去掉COM只取号 正常返回
  27. }
  28. i++;
  29. } while (TRUE);
  30. RegCloseKey(hkey); //关闭注册表
  31. }
  32. return -1;//没找到特定串口
  33. }
  34. int main()
  35. {
  36. std::cout << "Hello World!\n";
  37. std::cout << "**************************Special COM:"<<EnumAllComm()<<"\n";
  38. std::cout << "Hello World! end\n";
  39. }

 注册表的key在不同的电脑上是否会变化?

2.C++直接打开试

  1. //默认只找倒数第一个
  2. int getCommNum()
  3. {
  4. HANDLE hCom;
  5. int i;
  6. BOOL flag;
  7. char str[100] = {0};
  8. flag = FALSE;
  9. for (i = 30; i >= 1; i--)//此程序支持N个串口
  10. {
  11. sprintf(str,"\\\\.\\COM%d",i);
  12. //printf("%s%s",str,"\n");
  13. hCom = CreateFile(str, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
  14. if (INVALID_HANDLE_VALUE != hCom)
  15. {//能打开该串口,则添加该串口
  16. CloseHandle(hCom);
  17. return i;
  18. }
  19. }
  20. return -1;
  21. }

3、USB VID PID MI +串口前缀

  1. #define MY_USB_PID_VID_F200 _T("VID_05C6&PID_9018") //\\6&1DC4E91E&3
  2. #define MY_USB_PID_VID_F210 _T("VID_18D1&PID_4001") //\\&MI_046&4592401&0&0004
  3. #define MY_USB_PID_VID_F210_ELSE _T("VID_18D1&PID_4EE8")//这个在adb打开时存在
  4. //获取特定串口号 示例Qualcomm HS-USB Diagnostics 9091 (COM20)
  5. string getSpecialComNum(const char *in)
  6. {
  7. logger.INFO_F(FUN_LINE+in);
  8. CString temp(in);
  9. if (StrStr(temp, "Qualcomm HS-USB Android GPS 9018") == NULL && StrStr(temp, "USB 串行设备") == NULL)
  10. {
  11. return "";
  12. }
  13. int ret=getContentInBracket(temp);
  14. if (ret != 0) { return ""; }
  15. temp.Replace("COM","");
  16. logger.INFO_F(FUN_LINE +" OK, COM"+ temp.GetBuffer());
  17. return temp;
  18. //char out[100] = { 0 };
  19. //sscanf_s(in, "Qualcomm HS-USB Android GPS 9018 (COM%[0-9])", out, sizeof(out)); //不是%d哦
  20. //return out;
  21. }
  22. //从设备信息中 获取特定串口号 @return <=0无效
  23. int getSpecialComNumFromDevInfo()
  24. {
  25. HDEVINFO hDevInfo = SetupDiGetClassDevs(NULL, NULL, NULL, DIGCF_PRESENT | DIGCF_ALLCLASSES);
  26. if (hDevInfo == INVALID_HANDLE_VALUE)
  27. {
  28. printf("SetupDiGetClassDevs Err:%d", GetLastError());
  29. return -2;
  30. };
  31. SP_CLASSIMAGELIST_DATA _spImageData = { 0 };
  32. _spImageData.cbSize = sizeof(SP_CLASSIMAGELIST_DATA);
  33. SetupDiGetClassImageList(&_spImageData);
  34. SP_DEVINFO_DATA spDevInfoData = { 0 };
  35. spDevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
  36. for (DWORD i = 0; SetupDiEnumDeviceInfo(hDevInfo, i, &spDevInfoData); i++)
  37. {
  38. char szBuf[MAX_PATH] = { 0 };
  39. int wImageIdx = 0;
  40. short wItem = 0;
  41. if (!SetupDiGetDeviceRegistryPropertyA(hDevInfo, &spDevInfoData, SPDRP_CLASS, NULL, (PBYTE)szBuf, MAX_PATH, 0))
  42. {
  43. continue;
  44. };
  45. if (strcmp(szBuf, "Ports") != 0) //只取端口
  46. {
  47. continue;
  48. }
  49. printf("Class1:%s\r\n", szBuf);
  50. // PID_VID 识别 筛选出实际串口
  51. DWORD nSize = 0;
  52. TCHAR szDis[MAX_PATH] = { 0x00 };// 存储设备实例ID
  53. if (!SetupDiGetDeviceInstanceId(hDevInfo, &spDevInfoData, szDis, sizeof(szDis), &nSize)) { break; }
  54. // 根据设备信息寻找VID PID一致的设备
  55. CString strTemp;
  56. strTemp.Format(_T("%s"), szDis);
  57. logger.INFO_F(FUN_LINE+ szDis);
  58. //strTemp.MakeUpper();
  59. if ((strTemp.Find(MY_USB_PID_VID_F200, 0) == -1) && (strTemp.Find(MY_USB_PID_VID_F210, 0) == -1)) //没找到
  60. {
  61. logger.INFO_F(FUN_LINE+"USB_PID_VID mismatch.");
  62. continue;
  63. }
  64. logger.INFO_F(FUN_LINE+"PID_VID Check OK.");
  65. if (SetupDiGetClassImageIndex(&_spImageData, &spDevInfoData.ClassGuid, &wImageIdx))
  66. {
  67. char szName[MAX_PATH] = { 0 };
  68. DWORD dwRequireSize;
  69. if (!SetupDiGetClassDescriptionW(&spDevInfoData.ClassGuid, (PWSTR)szBuf, MAX_PATH, &dwRequireSize))
  70. {
  71. continue;
  72. };
  73. wprintf(L"Class:%s\r\n", szBuf);
  74. if (SetupDiGetDeviceRegistryPropertyW(hDevInfo, &spDevInfoData, SPDRP_FRIENDLYNAME, NULL, (PBYTE)szName, MAX_PATH - 1, 0))
  75. {
  76. wprintf(L"FriendlyName:%s\r\n\r\n", szName);
  77. int comNum = atoi(getSpecialComNum(wideCharToMultiByte((wchar_t *)szName)).c_str()); //根据特殊前缀来识别
  78. if (comNum > 0)
  79. {
  80. return comNum;
  81. }
  82. logger.ERROR_F(FUN_LINE+" Com prefix mismatch.");
  83. }
  84. else if (SetupDiGetDeviceRegistryProperty(hDevInfo, &spDevInfoData, SPDRP_DEVICEDESC, NULL, (PBYTE)szName, MAX_PATH - 1, 0))
  85. {
  86. wprintf(L"Device:%s\r\n\r\n", szName);
  87. }
  88. else
  89. {
  90. logger.ERROR_F(FUN_LINE);
  91. }
  92. }
  93. else
  94. {
  95. logger.ERROR_F(FUN_LINE);
  96. }
  97. }
  98. SetupDiDestroyClassImageList(&_spImageData);
  99. logger.ERROR_F(FUN_LINE);
  100. return -1;
  101. }
  102. //是否插了设备 @return <=0无效
  103. int isHaveDevice()
  104. {
  105. HDEVINFO hDevInfo = SetupDiGetClassDevs(NULL, NULL, NULL, DIGCF_PRESENT | DIGCF_ALLCLASSES);
  106. if (hDevInfo == INVALID_HANDLE_VALUE)
  107. {
  108. printf("SetupDiGetClassDevs Err:%d", GetLastError());
  109. return -2;
  110. };
  111. SP_CLASSIMAGELIST_DATA _spImageData = { 0 };
  112. _spImageData.cbSize = sizeof(SP_CLASSIMAGELIST_DATA);
  113. SetupDiGetClassImageList(&_spImageData);
  114. SP_DEVINFO_DATA spDevInfoData = { 0 };
  115. spDevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
  116. for (DWORD i = 0; SetupDiEnumDeviceInfo(hDevInfo, i, &spDevInfoData); i++)
  117. {
  118. char szBuf[MAX_PATH] = { 0 };
  119. int wImageIdx = 0;
  120. short wItem = 0;
  121. if (!SetupDiGetDeviceRegistryPropertyA(hDevInfo, &spDevInfoData, SPDRP_CLASS, NULL, (PBYTE)szBuf, MAX_PATH, 0))
  122. {
  123. continue;
  124. };
  125. if (strcmp(szBuf, "Ports") != 0) //只取端口
  126. {
  127. continue;
  128. }
  129. printf("Class1:%s\r\n", szBuf);
  130. // PID_VID 识别 筛选出实际串口
  131. DWORD nSize = 0;
  132. TCHAR szDis[MAX_PATH] = { 0x00 };// 存储设备实例ID
  133. if (!SetupDiGetDeviceInstanceId(hDevInfo, &spDevInfoData, szDis, sizeof(szDis), &nSize)) { break; }
  134. // 根据设备信息寻找VID PID一致的设备
  135. CString strTemp;
  136. strTemp.Format(_T("%s"), szDis);
  137. logger.INFO_F(FUN_LINE + szDis);
  138. //strTemp.MakeUpper();
  139. 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)) //没找到
  140. {
  141. logger.INFO_F(FUN_LINE + "USB_PID_VID mismatch.");
  142. continue;
  143. }
  144. logger.INFO_F(FUN_LINE + "PID_VID Check OK.");
  145. return 0;
  146. }
  147. SetupDiDestroyClassImageList(&_spImageData);
  148. logger.ERROR_F(FUN_LINE);
  149. return -1;
  150. }

4、C#自动获得特定串口 枚举【计算机管理】表

 C#

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Management;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. namespace FT_M20
  8. {
  9. class MySerialPort
  10. {
  11. public static string strConvertToHexStr(string str)
  12. {
  13. string strHex = "";
  14. foreach (byte b in str)
  15. {
  16. strHex += String.Format("{0:X2} ", b);
  17. }
  18. return strHex;
  19. }
  20. public static byte[] hexConvertToByteArray(String str)
  21. {
  22. str = str.Replace(" ", "");
  23. byte[] b = new byte[str.Length / 2];
  24. for (int i = 0; i < str.Length; i = i + 2)
  25. {
  26. b[i / 2] = (byte)Convert.ToInt32(str.Substring(i, 2), 16); //将十六进制“10”转换为十进制i
  27. }
  28. return b;
  29. }
  30. /// <summary>
  31. /// Get the target com num.
  32. /// </summary>
  33. /// <returns></returns>
  34. public static string GetComName()
  35. {
  36. string[] strArr = GetHarewareInfo(HardwareEnum.Win32_PnPEntity, "Name");
  37. foreach (string s in strArr)
  38. {
  39. //Quectel USB Serial - 1 Port(COM7)
  40. if (s.Contains("COM"))
  41. {
  42. if (s.Contains("Quectel USB Serial-1"))
  43. {
  44. //Log(s);
  45. return return "COM"+ Regex.Match(s, @"\(COM(?<port>\d+)").Groups["port"].Value; //从(COM20)提取串口号
  46. }
  47. }
  48. }
  49. return null;
  50. }
  51. /// <summary>
  52. /// Get the system devices information with windows api.
  53. /// </summary>
  54. /// <param name="hardType">Device type.</param>
  55. /// <param name="propKey">the property of the device.</param>
  56. /// <returns></returns>
  57. public static string[] GetHarewareInfo(HardwareEnum hardType, string propKey)
  58. {
  59. List<string> strs = new List<string>();
  60. try
  61. {
  62. using (ManagementObjectSearcher searcher = new ManagementObjectSearcher("select * from " + hardType))
  63. {
  64. var hardInfos = searcher.Get();
  65. foreach (var hardInfo in hardInfos)
  66. {
  67. if (hardInfo.Properties[propKey].Value != null)
  68. {
  69. String str = hardInfo.Properties[propKey].Value.ToString();
  70. strs.Add(str);
  71. }
  72. }
  73. }
  74. return strs.ToArray();
  75. }
  76. catch
  77. {
  78. return null;
  79. }
  80. finally
  81. {
  82. strs = null;
  83. }
  84. }//end of func GetHarewareInfo().
  85. /// <summary>
  86. /// 枚举win32 api
  87. /// </summary>
  88. public enum HardwareEnum
  89. {
  90. // 硬件
  91. Win32_Processor, // CPU 处理器
  92. Win32_PhysicalMemory, // 物理内存条
  93. Win32_Keyboard, // 键盘
  94. Win32_PointingDevice, // 点输入设备,包括鼠标。
  95. Win32_FloppyDrive, // 软盘驱动器
  96. Win32_DiskDrive, // 硬盘驱动器
  97. Win32_CDROMDrive, // 光盘驱动器
  98. Win32_BaseBoard, // 主板
  99. Win32_BIOS, // BIOS 芯片
  100. Win32_ParallelPort, // 并口
  101. Win32_SerialPort, // 串口
  102. Win32_SerialPortConfiguration, // 串口配置
  103. Win32_SoundDevice, // 多媒体设置,一般指声卡。
  104. Win32_SystemSlot, // 主板插槽 (ISA & PCI & AGP)
  105. Win32_USBController, // USB 控制器
  106. Win32_NetworkAdapter, // 网络适配器
  107. Win32_NetworkAdapterConfiguration, // 网络适配器设置
  108. Win32_Printer, // 打印机
  109. Win32_PrinterConfiguration, // 打印机设置
  110. Win32_PrintJob, // 打印机任务
  111. Win32_TCPIPPrinterPort, // 打印机端口
  112. Win32_POTSModem, // MODEM
  113. Win32_POTSModemToSerialPort, // MODEM 端口
  114. Win32_DesktopMonitor, // 显示器
  115. Win32_DisplayConfiguration, // 显卡
  116. Win32_DisplayControllerConfiguration, // 显卡设置
  117. Win32_VideoController, // 显卡细节。
  118. Win32_VideoSettings, // 显卡支持的显示模式。
  119. // 操作系统
  120. Win32_TimeZone, // 时区
  121. Win32_SystemDriver, // 驱动程序
  122. Win32_DiskPartition, // 磁盘分区
  123. Win32_LogicalDisk, // 逻辑磁盘
  124. Win32_LogicalDiskToPartition, // 逻辑磁盘所在分区及始末位置。
  125. Win32_LogicalMemoryConfiguration, // 逻辑内存配置
  126. Win32_PageFile, // 系统页文件信息
  127. Win32_PageFileSetting, // 页文件设置
  128. Win32_BootConfiguration, // 系统启动配置
  129. Win32_ComputerSystem, // 计算机信息简要
  130. Win32_OperatingSystem, // 操作系统信息
  131. Win32_StartupCommand, // 系统自动启动程序
  132. Win32_Service, // 系统安装的服务
  133. Win32_Group, // 系统管理组
  134. Win32_GroupUser, // 系统组帐号
  135. Win32_UserAccount, // 用户帐号
  136. Win32_Process, // 系统进程
  137. Win32_Thread, // 系统线程
  138. Win32_Share, // 共享
  139. Win32_NetworkClient, // 已安装的网络客户端
  140. Win32_NetworkProtocol, // 已安装的网络协议
  141. Win32_PnPEntity,//all device
  142. }
  143. }
  144. }

或者

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/484010
推荐阅读
相关标签
  

闽ICP备14008679号