热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

如何知道COM端口在使用中

假如机器上原来有两个COM口,COM1和COM2安装了一个USB设备后,这个USB设备使用了VCP(virtualcomport)把COM3占用了,当我安装另一个新设备时,我如何知道哪些CO

假如机器上原来有两个COM口,COM1和COM2
安装了一个USB设备后,这个USB设备使用了VCP(virtual com port)把COM3占用了,
当我安装另一个新设备时,我如何知道哪些COM口已被分配呢?

通过设备管理器无疑是可以看出来,那如何编程实现呢?

uses
  Windows, SysUtils, Registry, Math;

const
  n_MaxComPortCnt = 256;

  sKey_COMNameArbiter   = '/System/CurrentControlSet/Control/COM Name Arbiter/';
  sKey_NameComDB = 'ComDB';

resourcestring
  sErr_OpenRegKey = 'Failed to open register key: %s';
  sErr_WrongComPortName = 'Wrong COM port name: %s';
  sErr_ProcNA  = 'Processing not available for Com Port: %s';

function CalComPortIndex(const AComPortName: Integer): Integer;
var
  QT, Res: Integer;
begin
  // Each 8 ports per Byte.
  QT := AComPortName div 8;
  Res := AComPortName mod 8;

  if QT = 0 then
  begin
    // 01..07
    Result := AComportName;
  end else begin
    if Res = 0 then
    begin
      // 08, 16, 32...
      Result := 8;
    end else begin
      Result := Res;
    end;
  end;
end;

function CalByteIndex(const AComPortName: Integer): Integer;
begin
  // Each 8 ports per Byte.
  Result := 0;
  if AComPortName > n_MaxComPortCnt then Exit;
  Result := (AComPortName div 8) + 1;
end;

function ComPortInstalled(AComPortName: string): Boolean;
var
  nName, Len: Integer;
  bIdx, pIdx, Flags: Integer;
  Reg: TRegistry;
  FlagBuff: array[1..n_MaxComPortCnt] of Byte;   // Each 8 ports per Byte.
  Value: Cardinal;
begin
  (*
   * Binary value: 31 00 00 00 00 00 00 00 .... (32 byte in total)
   *  0    0    0    1    1    1    1    1
   * 8th  7th  6th  5th  4th  3rd  2nd  1st     (Each bit for one port)
   *
   * COM1 - COM5 installed(occupied), but it doesn't tell they are busy!
   *)

  Len := Length(AComPortName);
  nName := StrToIntDef(Copy(AComPortName, 4, Len-3), 0);
  if nName = 0 then
    raise Exception.CreateFmt(sErr_WrongComPortName, [AComPortName]);

  pIdx := CalComPortIndex(nName);
  bIdx := CalByteIndex(nName);
  if bIdx = 0 then
    raise Exception.CreateFmt(sErr_ProcNA, [AComPortName]);

  Reg := TRegistry.Create;
  try
    Reg.RootKey := HKEY_LOCAL_MACHINE;
    FillChar(FlagBuff, Length(FlagBuff), 0);
    if Reg.OpenKey(sKey_COMNameArbiter, False) then
      Reg.ReadBinaryData(sKey_NameComDB, FlagBuff[1], SizeOf(FlagBuff))
    else
      raise Exception.CreateFmt(sErr_OpenRegKey, [sKey_COMNameArbiter]);
  finally
    Reg.Free;
  end;

  Flags := FlagBuff[bIdx];
  Value := Round(Power(2, pIdx-1));
  Result := (Flags and Value) = Value;
end;


推荐阅读
  • 本文讨论了在手机移动端如何使用HTML5和JavaScript实现视频上传并压缩视频质量,或者降低手机摄像头拍摄质量的问题。作者指出HTML5和JavaScript无法直接压缩视频,只能通过将视频传送到服务器端由后端进行压缩。对于控制相机拍摄质量,只有使用JAVA编写Android客户端才能实现压缩。此外,作者还解释了在交作业时使用zip格式压缩包导致CSS文件和图片音乐丢失的原因,并提供了解决方法。最后,作者还介绍了一个用于处理图片的类,可以实现图片剪裁处理和生成缩略图的功能。 ... [详细]
  • Python实现变声器功能(萝莉音御姐音)的方法及步骤
    本文介绍了使用Python实现变声器功能(萝莉音御姐音)的方法及步骤。首先登录百度AL开发平台,选择语音合成,创建应用并填写应用信息,获取Appid、API Key和Secret Key。然后安装pythonsdk,可以通过pip install baidu-aip或python setup.py install进行安装。最后,书写代码实现变声器功能,使用AipSpeech库进行语音合成,可以设置音量等参数。 ... [详细]
  • Java序列化对象传给PHP的方法及原理解析
    本文介绍了Java序列化对象传给PHP的方法及原理,包括Java对象传递的方式、序列化的方式、PHP中的序列化用法介绍、Java是否能反序列化PHP的数据、Java序列化的原理以及解决Java序列化中的问题。同时还解释了序列化的概念和作用,以及代码执行序列化所需要的权限。最后指出,序列化会将对象实例的所有字段都进行序列化,使得数据能够被表示为实例的序列化数据,但只有能够解释该格式的代码才能够确定数据的内容。 ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • 本文介绍了深入浅出Linux设备驱动编程的重要性,以及两种加载和删除Linux内核模块的方法。通过一个内核模块的例子,展示了模块的编译和加载过程,并讨论了模块对内核大小的控制。深入理解Linux设备驱动编程对于开发者来说非常重要。 ... [详细]
  • 本文介绍了在CentOS上安装Python2.7.2的详细步骤,包括下载、解压、编译和安装等操作。同时提供了一些注意事项,以及测试安装是否成功的方法。 ... [详细]
  • JDK源码学习之HashTable(附带面试题)的学习笔记
    本文介绍了JDK源码学习之HashTable(附带面试题)的学习笔记,包括HashTable的定义、数据类型、与HashMap的关系和区别。文章提供了干货,并附带了其他相关主题的学习笔记。 ... [详细]
  • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
  • 本文介绍了设计师伊振华受邀参与沈阳市智慧城市运行管理中心项目的整体设计,并以数字赋能和创新驱动高质量发展的理念,建设了集成、智慧、高效的一体化城市综合管理平台,促进了城市的数字化转型。该中心被称为当代城市的智能心脏,为沈阳市的智慧城市建设做出了重要贡献。 ... [详细]
  • C# 7.0 新特性:基于Tuple的“多”返回值方法
    本文介绍了C# 7.0中基于Tuple的“多”返回值方法的使用。通过对C# 6.0及更早版本的做法进行回顾,提出了问题:如何使一个方法可返回多个返回值。然后详细介绍了C# 7.0中使用Tuple的写法,并给出了示例代码。最后,总结了该新特性的优点。 ... [详细]
  • 本文总结了在开发中使用gulp时的一些技巧,包括如何使用gulp.dest自动创建目录、如何使用gulp.src复制具名路径的文件以及保留文件夹路径的方法等。同时介绍了使用base选项和通配符来保留文件夹路径的技巧,并提到了解决带文件夹的复制问题的方法,即使用gulp-flatten插件。 ... [详细]
  • 本文详细说明了在JavaScript中解决alert弹出窗口文本换行问题的方法。通过给alert弹出的文本添加换行符,可以实现在弹窗中显示多行文本的效果。同时,提供了相关代码示例和注意事项,帮助读者更好地理解和应用这一解决方法。 ... [详细]
  • SLAM中相机运动估计的基本问题及解决方案
    本文讨论了SLAM中相机运动估计的基本问题,指出了解决方案的存在。作者认为阅读相关SLAM书籍是掌握基础原理的有效途径,而不是仅仅依赖现成的解决方案。同时,作者也提到了激光雷达和特征点匹配等技术在SLAM中的应用,并建议读者深入理解相关原理,而不是盲目追求现成的代码。 ... [详细]
author-avatar
领悟人生的悲欢喜乐_829
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有