用C#做串口通讯很方便,因为dotfx2.0已经集成了Serial Port控件,此控件使用上比MSComm控件更简单,当然它也有一个小bug

(RecievedBytesThreshold设置有时候不好使),但是这个问题很好解决,而做串口通讯最最基本的问题就是如何获得目标机器的要与

之通讯的特定设备的特定com号,有许多软件在处理这个问题的时候都是要求用户手动去选择对应的串口号,这多少有些不人性化,这篇

文章就是介绍如何自动获得目标机器对应特定串口设备的串口号,从而达到软件与目标设备的自动通讯。
方法基本上是我前一篇文章的一个应用,代码如下(注意自己添加引用的命名空间)
// <summary>
/// 通过vid,pid获得串口设备号
/// </summary>
/// <param name="vid">vid</param>
/// <param name="pid">pid</param>
/// <returns>串口号</returns>
public static string GetPortNameFormVidPid(string vid, string pid)
{
Guid myGUID = Guid.Empty;
string enumerator = "USB";
try
{
IntPtr hDevInfo = HardWareLib.SetupDiGetClassDevs(ref myGUID, enumerator, IntPtr.Zero, HardWareLib.DIGCF_ALLCLASSES | HardWareLib.DIGCF_PRESENT);
if (hDevInfo.ToInt32() == HardWareLib.INVALID_HANDLE_VALUE)
{
throw new Exception("没有该类设备");
}
HardWareLib.SP_DEVINFO_DATA deviceInfoData;//想避免在api中使用ref,就把structure映射成类
deviceInfoData = new HardWareLib.SP_DEVINFO_DATA();
deviceInfoData.cbSize = 28;//如果要使用SP_DEVINFO_DATA,一定要给该项赋值28=16+4+4+4
deviceInfoData.devInst = 0;
deviceInfoData.classGuid = System.Guid.Empty;
deviceInfoData.reserved = 0;
UInt32 i;
StringBuilder property = new StringBuilder(HardWareLib.MAX_DEV_LEN);
for (i = 0; HardWareLib.SetupDiEnumDeviceInfo(hDevInfo, i, deviceInfoData); i++)
{
// Console.Write(deviceInfoData.classGuid.ToString());
// HardWareOperation.SetupDiGetDeviceInstanceId(hDevInfo, deviceInfoData, porperty, (uint) porperty.Capacity, 0);
HardWareLib.SetupDiGetDeviceRegistryProperty(hDevInfo, deviceInfoData,
(uint)HardWareLib.SPDRP_.SPDRP_CLASS,
0, property, (uint)property.Capacity, IntPtr.Zero);
if (property.ToString().ToLower() != "ports") continue;//首先看看是不是串口设备(有些USB设备不是串口设备)
HardWareLib.SetupDiGetDeviceRegistryProperty(hDevInfo, deviceInfoData,
(uint)HardWareLib.SPDRP_.SPDRP_HARDWAREID,
0, property, (uint)property.Capacity, IntPtr.Zero);
if (!(property.ToString().ToLower().Contains(vid.ToLower())
&& property.ToString().ToLower().Contains(pid.ToLower()))) continue;//找到对应于vid&pid的设备
HardWareLib.SetupDiGetDeviceRegistryProperty(hDevInfo, deviceInfoData,
(uint)HardWareLib.SPDRP_.SPDRP_FRIENDLYNAME,
0, property, (uint)property.Capacity, IntPtr.Zero);
break; }
HardWareLib.SetupDiDestroyDeviceInfoList(hDevInfo);//记得用完释放相关内存
string friendlyName = property.ToString();
string pattern=@"(COM[1-9][0-9]?)$";//friendlyName一般形式为以(COMn)结尾,n为1-99
if (Regex.IsMatch(friendlyName, pattern, RegexOptions.IgnoreCase))
{
string portName=Regex.Match(friendlyName, pattern, RegexOptions.IgnoreCase).Value;
return portName.Trim(new char[] { '(', ')' });
}
return null;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
return null;
}
}
HardWareLib.cs(也就是前一篇文章的一个类)
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices; namespace ForGeneralUse
{
public class HardWareLib
{
/// <summary>
/// 设备的各项属性,注意有些属性是不通用的,例如SPDRP_FRIENDLYNAME只适用于端口设备
/// </summary>
public enum SPDRP_
{
SPDRP_DEVICEDESC = (0x00000000), // DeviceDesc (R/W)
SPDRP_HARDWAREID = (0x00000001), // HardwareID (R/W)
SPDRP_SERVICE = (0x00000004), // Service (R/W)
SPDRP_CLASS = (0x00000007), // Class (R--tied to ClassGUID)
SPDRP_CLASSGUID = (0x00000008), // ClassGUID (R/W)
SPDRP_DRIVER = (0x00000009), // Driver (R/W)
SPDRP_CONFIGFLAGS = (0x0000000A), // ConfigFlags (R/W)
SPDRP_MFG = (0x0000000B), // Mfg (R/W)
SPDRP_FRIENDLYNAME = (0x0000000C), // FriendlyName (R/W)
SPDRP_PHYSICAL_DEVICE_OBJECT_NAME = (0x0000000E), // PhysicalDeviceObjectName (R)
SPDRP_CAPABILITIES = (0x0000000F), // Capabilities (R)
SPDRP_REMOVAL_POLICY_HW_DEFAULT = (0x00000020), // Hardware Removal Policy (R)
SPDRP_INSTALL_STATE = (0x00000022), // Device Install State (R)
}
public const int DIGCF_ALLCLASSES = (0x00000004);
public const int DIGCF_DEVICEINTERFACE = 0x00000010;
public const int DIGCF_PRESENT = (0x00000002);
public const int INVALID_HANDLE_VALUE = -1;
public const int MAX_DEV_LEN = 1000; /// <summary>
/// 获取一个指定类别或全部类别的所有已安装设备的信息
/// </summary>
/// <param name="gClass">该类别对应的guid</param>
/// <param name="iEnumerator">类别名称(在HKLMSYSTEMCurrentControlSetEnum内获取)</param>
/// <param name="hParent">应用程序定义的窗口句柄</param>
/// <param name="nFlags">获取的模式</param>
/// <returns>设备信息集合的句柄</returns>
[DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern IntPtr SetupDiGetClassDevs(ref Guid gClass, String enumerator, IntPtr hParent, UInt32 nFlags); /// <summary>
/// 获得该设备的设备范例ID
/// </summary>
/// <param name="DeviceInfoSet">设备信息集合</param>
/// <param name="DeviceInfoData">表示该设备</param>
/// <param name="DeviceInstanceId">设备范例ID(输出)</param>
/// <param name="DeviceInstanceIdSize">该ID所占大小(字节)</param>
/// <param name="RequiredSize">需要多少字节</param>
/// <returns>是否成功</returns>
DllImport("setupapi.dll", SetLastError = true)]
public static extern bool SetupDiGetDeviceInstanceId(IntPtr DeviceInfoSet,
HardWareLib.SP_DEVINFO_DATA DeviceInfoData,
StringBuilder DeviceInstanceId,
UInt32 DeviceInstanceIdSize,
UInt32 RequiredSize); /// <summary>
/// 枚举指定设备信息集合的成员,并将数据放在SP_DEVINFO_DATA中
/// </summary>
/// <param name="lpInfoSet">设备信息集合句柄</param>
/// <param name="dwIndex">元素索引</param>
/// <param name="devInfoData">表示一个设备(作为输出)</param>
/// <returns>是否成功</returns>
[DllImport("setupapi.dll", SetLastError = true)]
public static extern bool SetupDiEnumDeviceInfo(IntPtr lpInfoSet, UInt32 dwIndex, SP_DEVINFO_DATA devInfoData); // <summary>
/// 获取指定设备的属性
/// </summary>
/// <param name="lpInfoSet">设备信息集合</param>
/// <param name="DeviceInfoData">表示该设备</param>
/// <param name="Property">表示要获取哪项属性</param>
/// <param name="PropertyRegDataType">注册类型</param>
/// <param name="PropertyBuffer">属性(输出)</param>
/// <param name="PropertyBufferSize">存储属性的字节大小</param>
/// <param name="RequiredSize">需要的字节大小</param>
/// <returns>是否成功</returns>
[DllImport("setupapi.dll", SetLastError = true)]
public static extern bool SetupDiGetDeviceRegistryProperty(IntPtr lpInfoSet,
SP_DEVINFO_DATA DeviceInfoData,
UInt32 Property,
UInt32 PropertyRegDataType,
StringBuilder PropertyBuffer,
UInt32 PropertyBufferSize,
IntPtr RequiredSize); /// <summary>
/// 销毁一个设备信息集合,并且释放所有关联的内存
/// </summary>
/// <param name="lpInfoSet">设备信息集合</param>
/// <returns></returns>
[DllImport("setupapi.dll", SetLastError = true)]
public static extern bool SetupDiDestroyDeviceInfoList(IntPtr lpInfoSet);
/// <summary>
/// 设备信息数据
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public class SP_DEVINFO_DATA
{
public int cbSize;//本结构的大小(字节表示)
public Guid classGuid;//本结构所表示的设备的GUID
public int devInst;//设备句柄
public ulong reserved;//没用
};
}
}
如果大家想了解正则表达式的简单使用,推荐大家访问如下网址
http://www.szwblm.com/Netvb/ShowArticle.asp?ArticleID=19633,
http://www.szwblm.com/Netvb/ShowArticle.asp?ArticleID=14918 本文来自转载,小编尚未尝试,静待。。。

通过串口设备vid,pid自动获得该设备所对应的串口号的更多相关文章

  1. adb设备,根据serial获取vid pid

    使用adb devices命令,可以轻松获取到所有连接到PC的adb设备的serial值. 但是adb命令无法获取adb usb设备的vendor id和product id. 本程序根据adb协议, ...

  2. USB VID PID 查询

    USB VID PID 查询:http://www.linux-usb.org/usb.ids 说明: USB设备中有VID何PID,分别表示此USB设备是哪个厂商的哪种设备. 一个USB的VID对应 ...

  3. Linux自动共享USB设备:udev+Samba

    一.概述 公司最近要我实现USB设备插入Ubuntu后,自动共享到网络上,能像Windows共享一样(如\\192.168.1.10)访问里面的内容,不需要写入权限.当时听完这需求,我这新人表示惊呆了 ...

  4. 自动创建字符设备,不需mknod

    自动创建设备文件 1.自动创建设备文件的流程 字符设备驱动模块 -->创建一个设备驱动class--->创建属于class的device--->调用mdev工具(自动完成)--> ...

  5. C# 获取 串口 设备名称 与 串口号 ManagementObjectSearcher类

    1.效果图: 2.代码 class Program { static void Main(string[] args) { GetComList(); } private static void Ge ...

  6. 根据PID和VID得到USB转串口的串口号

    /******************************************************************************* * * FindAppUART.cpp ...

  7. Appium自动获取 Android 设备 id 和包名等信息(python)

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/zhusongziye/article/d ...

  8. 根据设备id自动打开本设备的串口

    对于串口设备经常遇到重新拔插串口设备时候,程序又需要重新选择串口打开.对此很少麻烦的要死. 现在我们可以根据该设备的id去遍历串口设备,一旦符合就打开此串口即可. public void init() ...

  9. udisk2阻止自动Mount某些设备

    1.在/etc/udev/rules.d/目录下添加一个诸如99.udisk2.rules 2.其中的内容诸如: # This file contains udev rules for udisks ...

随机推荐

  1. ASP.NET 4.0 取消表单危险字符验证

    /// <summary> /// ASP.NET4.0 表单验证类 /// </summary> public class FormRequestValidation : R ...

  2. 解决"System.AccessViolationException”类型的未经处理的异常在 未知模块(IIS Worker Process 已停止工作)导致无法连接远程数据库的问题

    解决方法: 用管理员身份运行CMD,输入netsh winsock reset并回车(注意,必须是已管理员身份运行,这个重置LSP连接)

  3. Linux学习笔记(1)Linux虚拟机安装过程中的知识点及常用管理工具

    1. VMware的相关知识 (1)建议的VMware的配置: CPU 主频1GHz以上 内存 1GB以上 硬盘 分区空闲空间8GB以上 (2)VMware创建快照 快照的作用是保存虚拟机的现有状态, ...

  4. Pig用户自定义函数(UDF)转

    原文地址:http://blog.csdn.net/zythy/article/details/18326693 我们以气温统计和词频统计为例,讲解以下三种用户自定义函数. 用户自定义函数 什么时候需 ...

  5. Understanding, Operating and Monitoring Apache Kafka

    Apache Kafka is an attractive service because it's conceptually simple and powerful. It's easy to un ...

  6. 【java 断点续传】

    模拟 断点续传 首先,先读取word文件的 一部分 package com.sxd.readLines; import java.io.File; import java.io.FileInputSt ...

  7. 常用chrome插件推荐

    下面打红色的2个强烈推荐使用: FQ的: https://chrome.google.com/webstore/detail/ecross-free/njdjpgffklilbojbobbfecfcg ...

  8. jquery的siblings()

    jquery 点击 感兴趣 感兴趣变为 蓝色 去掉onclick事件 不感兴趣 变为 黑色 加上点击事件 点击 不感兴趣 不感兴趣变为 蓝色 去掉onclick 感兴趣 变为 黑色 加上点击事件 ht ...

  9. yii2.0 的数据的 改

    修改数据 /**     * 根据获取到的数据的id 去编辑对应的数据  controller层     */ //引入对应的model use app\models\About; //定义一个方法 ...

  10. 解决:未能加载文件或程序集“EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089”

    使用nuget管理程序包,有可能在不同时间安装不同版本的Entity Framework:在项目创建初期安装的是6.0.0.0版本,后来添加的类库,安装了6.1.1版本,所以出现这个问题. 解决办法: ...