1. 程式人生 > >通過讀登錄檔檢測本機串列埠資訊

通過讀登錄檔檢測本機串列埠資訊

用QT做上位機,使用串列埠通訊時,想自動掃描串列埠裝置,即在下拉列表框中,只顯示已有的串列埠。

本來挺簡單的,只要輪詢HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM就能找到已有的串列埠,但QT的QSettings有個bug,如果鍵名裡有斜槓'/',則讀出的鍵值就是空的。參考別人使用API函式讀取鍵值的文章,寫了下面這個函式。

UINT32 comPortInfo(QStringList *qslKeyValList)
{
	//1.從登錄檔中取出 鍵名
	QString qsRegPath = "HKEY_LOCAL_MACHINE\\HARDWARE\\DEVICEMAP\\SERIALCOMM";
	QSettings *reg = new QSettings(qsRegPath,QSettings::NativeFormat);
	QStringList qsListKeys = reg->allKeys();	//childKeys();
	QList<int> qlTmp;

	//2.再依次取出 鍵值
	for (UINT32 i=0; i < qsListKeys.size(); i++)
	{
		HKEY hKey;
		wchar_t wsKeyName[256];	//鍵名陣列
		char sKeyVal[32];		//鍵值陣列
		DWORD ulKeyNameSize = sizeof(wsKeyName);
		DWORD ulKeyValSize  = sizeof(sKeyVal);

		RegOpenKeyEx(HKEY_LOCAL_MACHINE,TEXT("HARDWARE\\DEVICEMAP\\SERIALCOMM"),0,KEY_READ,&hKey);
		RegEnumValue(hKey,      /*要查詢的已開啟的鍵的控制代碼*/
			i,              /*索引號*/
			wsKeyName,      /*返回所讀取的名稱*/
			&ulKeyNameSize, /*返回讀取名稱的長度,不含chr(0)*/
			0,              /*保留*/
			0,              /*返回所讀取的資料型別*/
			(BYTE*)sKeyVal, /*返回所讀取的資料*/
			&ulKeyValSize); /*返回所讀取的資料長度*/

		//取出類似 COM3 COM20 這樣的鍵值
		//只取第3位以後的數字,放入list (方便排序)
		qlTmp.append( QString::fromUtf16((ushort*)sKeyVal).mid(3).toUInt() );
	}

	//3.排序
	//  因為字串排序 "COM12" < "COM3", 所以不能簡單地QStringList.sort()
	//  故先提取出數字, 再按數字排序, 再附加上字首COM
	qSort(qlTmp);
	for (UINT32 i=0; i<qsListKeys.size(); i++)
	{
		qslKeyValList->append(QString("COM%1").arg(qlTmp[i]));
	}

	//qDebug() << *qslKeyValList;
	return qsListKeys.size();

使用方法:
// 檢查本機串列埠裝置
	QStringList qslKeyValList;
	UINT32 uiComCount = comPortInfo(&qslKeyValList);
	if(uiComCount == 0)
		QMessageBox::about(NULL, "錯誤", "本機無串列埠裝置,請檢查串列埠線");
	qDebug() << QString("=== 本機有%1個串列埠:").arg(uiComCount) << qslKeyValList;