目的:获取Windows系统中的所有可用和在用串口

方法:注册表查询法

优点:简单、实用、快速、无遗漏,无多余结果。

说明:另外还有8种方法可以枚举串口,但都不如此法。

代码和详细注释如下:

//---------------------------------------------------------------------------
// 枚举串口
void __fastcall TForm1::BtnEnumClick(TObject *Sender)
{
// 清除信息提示区
Memo1->Clear(); // 清空串口列表, sg 是 TStringGrid 对象
sg->Clear();
sg->Cells[0][0] = L"串口物理名称";
sg->Cells[1][0] = L"串口逻辑名称"; // 就是 COM1, COM2 之类的 // 列标题居中对齐
sg->Alignments[0][0] = taCenter;
sg->Alignments[1][0] = taCenter; // 创建注册表对象
std::auto_ptr<TRegistry> Registry(new TRegistry(KEY_READ));

try
{
// 注册表根路径
Registry->RootKey = HKEY_LOCAL_MACHINE; // 打开串口设备所在的注册表路径
bool bResult = Registry->OpenKey("\\HARDWARE\\DEVICEMAP\\SERIALCOMM", false); // 若打开注册表失败,提示信息,直接返回
if (!bResult) {
ShowHint("注册表路径不存在.");
return;
} // 数据项(名称)列表,就是串口物理名称列表
std::auto_ptr<TStringList> ItemNameList(new TStringList()); // 获取数据项(名称)列表,就是串口物理名称列表
Registry->GetValueNames(ItemNameList.get()); // 单个数据项的名称和值 (字符串形式),值的字符串形式就是串口逻辑名称,就是COM1, COM2 之类的
UnicodeString sItemName, sItemValue; // 逐个获取数据项值 (字符串形式)
for (int i = 0; i < ItemNameList->Count; i++)
{
// 当前数据项名称,也就是串口物理名称
sItemName = ItemNameList->Strings[i]; // 读取对应的数据项值 (字符串形式),也就是串口逻辑名称
sItemValue = Registry->ReadString(sItemName); // 显示串口物理名称和串口逻辑名称
//ShowHint(sItemName + "\t" + sItemValue);
// sg 是 TStringGrid 对象
sg->Cells[0][i + 1] = sItemName;
sg->Cells[1][i + 1] = sItemValue;
sg->AutoSizeColumns(true, 0);
} // 关闭会产生写入操作
//Registry->CloseKey();
}
// 在读取注册表时发生异常
catch(...) {
ShowHint("在读取注册表时发生异常.");
}
}
//---------------------------------------------------------------------------

以下是程序运行结果:

说明1:若只想获得可用(空闲)串口,还得逐个打开上述串口,成功打开的是可用(空闲)串口,否则为在用(被其它程序占用的)串口。

说明2:若要支持热插拔串口,还需响应 WM_DEVICECHANGE 消息。

枚举串口的各种方法对比

枚举串口方法

说明

EnumPorts

能够获得历史上曾经在系统中存在过的所有串口,不实用

WMI

无法获取纯粹用软件虚拟出来的串口,例如VSPD串口

注册表

简便、实用、快速,无遗漏,无多余

SetupAPI

GUID_DEVINTERFACE_COMPORT

结果同注册表法,但结果信息太详细,能够分辨出串口类型是纯软件虚拟的,还是蓝牙虚拟的,还是USB虚拟的,等等。

SetupAPI

Ports Device   information set

结果同注册表法,但结果信息太详细,能够分辨出串口类型是纯软件虚拟的,还是蓝牙虚拟的,还是USB虚拟的,等等。

GetDefaultCommConfig

结果有遗漏

QueryDosDevice

结果同注册表法,

文件读写法

结果同注册表法,但要尝遍255个串口,效率太低。

获取Windows系统中的所有可用和在用串口的更多相关文章

  1. Pyqt 获取windows系统中已安装软件列表

    开始之前的基础知识 1. 获取软件列表 在Python的标准库中,_winreg可以操作Windows的注册表.获取已经安装的软件列表一般是读去windows的注册表: SOFTWARE\Micros ...

  2. 这段百度问答,对我相关有对啊!!!----如何获取Windows系统登陆用户名

    如何获取Windows系统登陆用户名 http://zhidao.baidu.com/link?url=Hva9PkVwYZv8KSEWftSqTWe8fqM1dhoq59BurnfADmcOvFjF ...

  3. Windows系统中CreateFileMapping实现的共享内存及用法

    在32位的Windows系统中,每一个进程都有权访问他自己的4GB(232=4294967296)平面地址空间,没有段,没有选择符,没有near和far指针,没有near和far函数调用,也没有内存模 ...

  4. UEFI+GPT模式下的Windows系统中分区结构和默认分区大小及硬盘整数分区研究

    内容摘要:本文主要讨论和分析在UEFI+GPT模式下的Windows系统(主要是最新的Win10X64)中默认的分区结构和默认的分区大小,硬盘整数分区.4K对齐.起始扇区.恢复分区.ESP分区.MSR ...

  5. 通过PowerShell获取Windows系统密码Hash

    当你拿到了系统控制权之后如何才能更长的时间内控制已经拿到这台机器呢?作为白帽子,已经在对手防线上撕开一个口子,如果你需要进一步扩大战果,你首先需要做的就是潜伏下来,收集更多的信息便于你判断,便于有更大 ...

  6. 快速获取Windows系统上的国家和地区信息

    Windows系统上包含了200多个国家和地区的数据,有时候编程需要这些资料.以下代码可以帮助你快速获取这些信息.将Console语句注释掉,可以更快的完成分析. static void Main(s ...

  7. Python使用WMI模块获取Windows系统的硬件信息,并使用pyinstaller库编译打包成exe的可执行文件

    由于公司现阶段大多数应用软件都是基于Windows系统开发和部署,很多软件安装部署都是在windows server 2012.windows server 2008之类的服务器上,部门同事每次测试一 ...

  8. [源码]一键获取windows系统登陆密码vc6版源码

    [源码]一键获取windows系统登陆密码vc6版源码支持:XP/2000/2003/WIN7/2008等 此版本编译出来的程序体积较小几十KB... 而vs版则1点几M,体积整整大了2-30倍对某些 ...

  9. C/C++获取Windows系统CPU和内存及硬盘使用情况

    //1.获取Windows系统内存使用率 //windows 内存 使用率 DWORD getWin_MemUsage(){ MEMORYSTATUS ms; ::GlobalMemoryStatus ...

随机推荐

  1. TP3.2 图片上传及缩略图

    基于TP自带的上传文件的类, Think/Upload.class.php 设置表单的enctype属性 下面是上传的具体方法 /** * 图片上传处理 * @param [String] $path ...

  2. 将PDF文件中按页截取,并以流的形势返回给客户端

    #需要用到pyPdf库 from pyPdf import PdfFileWriter,PdfFileReader from django.http import HttpResponse try: ...

  3. Java基础—标识符及命名规范

      什么是标识符符? 凡是可以由自己命名的地方都称为修饰符. 例: 项目名 ,包名 ,类名 .方法名 2.   命名规范. ①    不可使用java关键字和保留字,但是可以包含关键字和保留字. ②  ...

  4. ConcurrentModificationException异常出现的原因

    原因:对list .map 等迭代的时进行修改就会抛出java.util.ConcurrentModificationException异常 比如: public synchronized void ...

  5. SQL-Oracle游标

    游标提供了一种从集合性质的结果集中提供出单条记录的手段.初始时指向首记录. 游标的种类 静态游标.REF游标 静态游标:能够理解为一个数据快照,打开游标后的结果集是数据库表中数据的备份,数据不会对表的 ...

  6. linux进程标识符具体解释1

    每一个进程都有一个实际用户标识符和一个实际组标识符,它们永远是启动该进程之用户的用户标识符和组标识符. 进程的有效用户标识符和有效组标识符或许更重要些,它们被用来确定一个用户是否能訪问某个确定的文件. ...

  7. class的二般用法

    一般来说,class就是给一堆元素添加样式的,但是还有二般的用法,就是用来作为一个开关,来切换他的子孙元素的样式.举个例子: <ul> <li><span>1< ...

  8. Hibernate(或其它ORM)里的inverse用法详解,内容摘自Java web轻量级开发面试教程

    本文来是从 java web轻量级开发面试教程从摘录的. Inverse的英文含义是反转,在Hibernate中用来决定是由哪方来维护两个业务实体类之间的关联关系,具体而言,就是由哪方去设置这个被外键 ...

  9. nginx+redis缓存微信的token数据

    上一篇文章我们讲了如何在负载均衡的项目中使用redis来缓存session数据,戳这里. 我们在项目的进展过程中,不仅需要缓存session数据,有时候还需要缓存一些别的数据,比如说,微信的acces ...

  10. JAVA IO分析三:IO总结&文件分割与合并实例

    时间飞逝,马上就要到2018年了,今天我们将要学习的是IO流学习的最后一节,即总结回顾前面所学,并学习一个案例用于前面所学的实际操作,下面我们就开始本节的学习: 一.原理与概念 一.概念流:流动 .流 ...