查询计算机上可用端口的两种方法

在设备远程控制中,经常需要搜索设备上已安装端口号,例如在“计算机”→“设备”能看到的端口(COM和LPT)。本文介绍的两种方法都是通过访问注册表实现的。

方法一:仅查询端口号,如:COM1、COM2等

HKEY hkey;
LPCTSTR lpSubKey = _T("HARDWARE\\DEVICEMAP\\SERIALCOMM\\");

long retopen = (::RegOpenKeyEx(HKEY_LOCAL_MACHINE, lpSubKey, 0, KEY_READ, &hkey));

if(retopen == ERROR_SUCCESS)	//打开成功,枚举串口号
{
	DWORD dinx = 0;
	TCHAR c_valuename[40];
	TCHAR c_vari[10];
	DWORD k = REG_SZ;
	DWORD nsize = sizeof(c_valuename);
	DWORD ncbvari = sizeof(c_vari);

	//k为输出值,代表读取的数值的数据类型。串口的类型为REG_SZ,此处不做特别判断
	while(RegEnumValue(hkey, dinx++, c_valuename, &nsize, NULL, &k, (LPBYTE)c_vari, &ncbvari) != ERROR_NO_MORE_ITEMS)
	{
		CString strInfo;
		strInfo.Format(_T("Port found: %s\n"), c_vari);

		OutputDebugString(strInfo);    //根据需要处理获得的结果

		//每次执行RegEnumValue后nSize和ncbvari的值都会被改变,需要再次赋值,否则可能出错
		nsize = sizeof(c_valuename);
		ncbvari	= sizeof(c_vari);
	}
}
else if(ERROR_FILE_NOT_FOUND == retopen)
{
    AddInformation(MB_ICONWARNING, _T("计算机上没有串口!"));
}
else
{
	CString strError;
	strError.Format(_T("打开注册表失败,错误号%d。程序将无串口可用!"), retopen);
	AfxMessageBox(strError, MB_ICONWARNING);
}

RegCloseKey(hkey);	//不再需要使用hkey时,应关闭它。

 方法二:利用API函数SetupDiGetClassDevs,获得端口号和端口名称

1、将C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Lib(Setupapi.lib)和C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Include(Setupapi.h) 直接复制到工程目录下面。(路径可能会有不同)

2、添加:      

#include <setupapi.h>

#pragma comment(lib, "Setupapi.lib")

3、

//GUID_DEVCLASS_PORTS 端口(COM 和 LPT)的GUID值,查询注册表可以获得
//注册表中路径:HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Class下
GUID ClassGuid = {0x4d36e978, 0xe325, 0x11ce, {0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18}};

HDEVINFO hDevInfo = SetupDiGetClassDevs(&ClassGuid, 
    NULL, 
    NULL, 
    DIGCF_PRESENT);		//之返回当前存在的设备

if (hDevInfo)
{
	int iy = 0;
	SP_DEVINFO_DATA SpDevInfo = { sizeof(SP_DEVINFO_DATA) };
	for (DWORD iDevIndex = 0; SetupDiEnumDeviceInfo(hDevInfo, iDevIndex, &SpDevInfo); iDevIndex++)
	{
		TCHAR szName[512] = { 0 };
		if (SetupDiGetDeviceRegistryProperty(hDevInfo, &SpDevInfo, SPDRP_FRIENDLYNAME,
				NULL, (PBYTE)szName, sizeof(szName), NULL))
		{
			CString com, str, strComOpen;
				
            str.Format(_T("%s"), szName);	//获取串口的名称,如ELTIMA Virtual Serial Port(COM1->COM2)
				
            int posBeg = str.Find('(');		
            int posEnd = str.Find(')');
			com = str.Mid(posBeg + 1, posEnd - posBeg - 1);//获取串口的名称COM3
		}
	}
	SetupDiDestroyDeviceInfoList(hDevInfo);
}

 

扩展:

HDEVINFO
SetupDiGetClassDevs(
const GUID* ClassGuid,
PCTSTR Enumerator,
HWND hwndParent,
DWORD Flags
);

PGUID  ClassGuid

在创建设备列表的时候提供一个指向GUID的指针。如果设定了标志(参数Flags的值)为DIGCF_ALLCLASSES,则这个参数可以忽略,且列表结果中包括所有已经安装的设备类别。


PCTSTR  Enumerator

提供包含设备实例的枚举注册表分支下的键名,可以通过它获取设备信息。如果这个参数没有指定,则要从整个枚举树中获取所有设备实例的设备信息。


HWND  hwndParent

提供顶级窗口的句柄,所有用户接口可以使用它来与成员联系。


DWORD  Flags

提供在设备信息结构中使用的控制选项。可以是以下数值:

DIGCF_PRESENT——只返回当前存在的设备。

DIGCF_ALLCLASSES ——返回所有已安装的设备。如果这个标志设置了,ClassGuid参数将被忽略。

DIGCF_PROFILE —— 只返回当前硬件配置文件中的设备。

DIGCF_INTERFACEDEVICE —— 返回所有支持的设备。

DIGCF_DEFAULT ——只返回与系统默认设备相关的设备。
 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值