C++设备管理器


项目背景

我需要通过C++查询设备管理器中的某个设备是否存在,然后找到该设备的父节点和兄弟节点和子节点。所以我的code就是用来实现上面的内容。


一、代码

直接上代码

// DeviceManager.hpp
#include <iostream>
#include <Windows.h>
#include <cfgmgr32.h>
#include <setupapi.h>   
#include <vector>
#pragma comment(lib, "setupapi.lib")

class DeviceManager
{
public:
	/*
	* @brief	查询可以查到的所有设备信息
	* @param	parentInst - 当前节点
	*
	* @author 	Canliang Wu
	* @day		2024/01/02
	*/
	static bool GetAllDevices()
	{
		HDEVINFO hDevInfo = SetupDiGetClassDevs(NULL, NULL, NULL, (DIGCF_ALLCLASSES | DIGCF_PRESENT));
		if (INVALID_HANDLE_VALUE == hDevInfo)
			return false;

		SP_DEVINFO_DATA sDevInfoData;
		memset(&sDevInfoData, 0x00, sizeof(SP_DEVICE_INTERFACE_DATA));
		sDevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);

		// 遍历设备树
		for (int i = 0; SetupDiEnumDeviceInfo(hDevInfo, i, &sDevInfoData); i++)
		{
			TCHAR szDis[MAX_PATH * 4] = { 0x00 };// 存储设备实例ID
			DWORD nSize = 0;
			if (!SetupDiGetDeviceInstanceIdW(hDevInfo, &sDevInfoData, szDis, sizeof(szDis) / sizeof(szDis[0]), &nSize))
			{
				// 无效设备
				if (INVALID_HANDLE_VALUE != hDevInfo)
				{
					SetupDiDestroyDeviceInfoList(hDevInfo);
					hDevInfo = INVALID_HANDLE_VALUE;
				}

				return false;
			}

			// 获取友好名称
			TCHAR szFN[MAX_PATH * 4] = { 0x00 };
			SetupDiGetDeviceRegistryProperty(hDevInfo, &sDevInfoData, SPDRP_FRIENDLYNAME, NULL, (PBYTE)szFN, sizeof(szFN), NULL);
			std::wstring friendName(szFN);

			// 获取硬件ID(包含VID和PID的字符串)
			TCHAR szHID[MAX_PATH * 4] = { 0x00 }; // 存储设备硬件ID
			SetupDiGetDeviceRegistryProperty(hDevInfo, &sDevInfoData, SPDRP_HARDWAREID, NULL, (PBYTE)szHID, sizeof(szHID), NULL);
			std::wstring hardwareID(szHID);

			std::wcout << L"Friendly name: " << friendName << ", HID: " << hardwareID << std::endl;
		}

		if (hDevInfo != INVALID_HANDLE_VALUE)
		{
			SetupDiDestroyDeviceInfoList(hDevInfo);
			hDevInfo = INVALID_HANDLE_VALUE;
		}

		return true;
	}

	/*
	* @brief	查询当前节点的子节点、当前节点的子节点的子节点、当前节点的子节点的兄弟节点的设备信息
	* @param	parentInst - 当前节点
	*
	* @author 	Canliang Wu
	* @day		2024/01/02
	*/
	static bool QueryChildNode(const DEVINST& parentInst)
	{
		DEVINST childDevInst = NULL;

		// 获取第一个子节点
		if (CM_Get_Child(&childDevInst, parentInst, 0) != CR_SUCCESS) return false;

		// 遍历一层子节点
		while (childDevInst)
		{
			// 获取友好名称
			TCHAR str1[1024] = { '0' };
			ULONG len1 = sizeof(TCHAR) * 1024;
			auto errorCode = CM_Get_DevNode_Registry_Property(childDevInst, CM_DRP_FRIENDLYNAME, NULL, reinterpret_cast<PBYTE>(str1), &len1, 0);
			if (errorCode == CR_SUCCESS)
			{
				std::wstring friendName(str1);

				std::wcout << "Friendly name: " << friendName << std::endl;
			}

			// 获取设备描述
			TCHAR str2[1024] = { '0' };					// 注意,这里不能直接使用str1,否则会一旦友好名称查询失败,这里就会返回error=26
			ULONG len2 = sizeof(TCHAR) * 1024;
			errorCode = CM_Get_DevNode_Registry_Property(childDevInst, CM_DRP_DEVICEDESC, NULL, reinterpret_cast<PBYTE>(str2), &len2, 0);
			if (errorCode == CR_SUCCESS)
			{
				std::wstring deviceDesc(str2);

				std::wcout << "Device describe: " << deviceDesc << std::endl;
			}

			// 递归遍历设备的子节点
			QueryChildNode(childDevInst);

			// 获取下一个兄弟节点
			if (CM_Get_Sibling(&childDevInst, childDevInst, 0) != CR_SUCCESS)
			{
				break;
			}
		}

		return true;
	}
	
	/*
	* @brief	查询当前节点的父节点信息
	* @param	childData - 当前节点
	*
	* @author 	Canliang Wu
	* @day		2024/01/02
	*/
	static bool QueryParentNode(SP_DEVINFO_DATA childData)
	{
		DEVINST parentInst = NULL;
		if (CM_Get_Parent(&parentInst, childData.DevInst, 0) != CR_SUCCESS)
		{
			return false;
		}

		// 获取友好名称
		TCHAR str1[1024] = { '0' };
		ULONG len1 = sizeof(TCHAR) * 1024;
		auto errorCode = CM_Get_DevNode_Registry_Property(parentInst, CM_DRP_FRIENDLYNAME, NULL, reinterpret_cast<PBYTE>(str1), &len1, 0);
		if (errorCode == CR_SUCCESS)
		{
			std::wstring friendName(str1);

			std::wcout << "Friendly name: " << friendName << std::endl;
		}

		return true;
	}
};

二、遇到的问题

我遇到的问题在于这段代码:

// 获取友好名称
TCHAR str1[1024] = { '0' };
ULONG len1 = sizeof(TCHAR) * 1024;
auto errorCode = CM_Get_DevNode_Registry_Property(childDevInst, CM_DRP_FRIENDLYNAME, NULL, reinterpret_cast<PBYTE>(str1), &len1, 0);
if (errorCode == CR_SUCCESS)
{
	std::wstring friendName(str1);

	std::wcout << "Friendly name: " << friendName << std::endl;
}

// 获取设备描述
TCHAR str2[1024] = { '0' };					// 注意,这里不能直接使用str1,否则会一旦友好名称查询失败,这里就会返回error=26
ULONG len2 = sizeof(TCHAR) * 1024;
errorCode = CM_Get_DevNode_Registry_Property(childDevInst, CM_DRP_DEVICEDESC, NULL, reinterpret_cast<PBYTE>(str2), &len2, 0);
if (errorCode == CR_SUCCESS)
{
	std::wstring deviceDesc(str2);

	std::wcout << "Device describe: " << deviceDesc << std::endl;
}

假设两次调用CM_Get_DevNode_Registry_Property()都使用str1进行填充。
那么,如果我第一次调用CM_Get_DevNode_Registry_Property()查询友好名称失败(我的返回是 errorCode = CR_NO_SUCH_DEVICE_INTERFACE),那么第二次调用CM_Get_DevNode_Registry_Property()查询设备描述则一定失败(返回 errorCode = CR_WRONG_TYPE)。
我们知道,对于设备管理器的设备,并不是每一个设备都有友好名称和设备描述(可以通过设备管理器查看)。所以我猜测第一个返回的原因就是因为它没有友好名称。但是仍然不知道第二个错误是为什么产生的。但是改成str2就没问题了。

在这里插入图片描述


总结

上面的class可以直接复制使用。如果有人能解答我的问题,那就更好了!感谢!

  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
设备管理系统是一个很好的软件开发项目,可以帮助实验室管理人员更好地管理设备和维护设备。下面是一个简单的设备管理系统的C++实现: 1. 设备类(Device) 设备类包含设备名称、设备类型、设备编号、设备状态等属性,以及设备的借出、归还、报废等操作。 ```c++ class Device { private: string name; string type; string id; string status; // 1表示可用,0表示不可用 public: Device(string name, string type, string id, string status); string getName(); string getType(); string getId(); string getStatus(); void setStatus(string status); void borrowDevice(); void returnDevice(); void discardDevice(); }; ``` 2. 设备管理类(DeviceManager) 设备管理类包含设备列表、设备数量等属性,以及设备的添加、删除、查询、借出、归还、报废等操作。 ```c++ class DeviceManager { private: vector<Device> devices; int numDevices; public: DeviceManager(); void addDevice(Device device); void removeDevice(string id); void searchDevice(string name); void borrowDevice(string id); void returnDevice(string id); void discardDevice(string id); }; ``` 3. 主函数 主函数通过菜单的方式提供用户操作选项,实现设备管理系统的交互界面。 ```c++ int main() { DeviceManager dm; int choice; while (true) { cout << "1. Add device" << endl; cout << "2. Remove device" << endl; cout << "3. Search device" << endl; cout << "4. Borrow device" << endl; cout << "5. Return device" << endl; cout << "6. Discard device" << endl; cout << "7. Quit" << endl; cout << "Enter your choice: "; cin >> choice; switch (choice) { case 1: // 添加设备 string name, type, id, status; cout << "Enter device name: "; cin >> name; cout << "Enter device type: "; cin >> type; cout << "Enter device ID: "; cin >> id; cout << "Enter device status (1 for available, 0 for not available): "; cin >> status; Device device(name, type, id, status); dm.addDevice(device); break; case 2: // 删除设备 string idToRemove; cout << "Enter device ID to remove: "; cin >> idToRemove; dm.removeDevice(idToRemove); break; case 3: // 查询设备 string nameToSearch; cout << "Enter device name to search: "; cin >> nameToSearch; dm.searchDevice(nameToSearch); break; case 4: // 借出设备 string idToBorrow; cout << "Enter device ID to borrow: "; cin >> idToBorrow; dm.borrowDevice(idToBorrow); break; case 5: // 归还设备 string idToReturn; cout << "Enter device ID to return: "; cin >> idToReturn; dm.returnDevice(idToReturn); break; case 6: // 报废设备 string idToDiscard; cout << "Enter device ID to discard: "; cin >> idToDiscard; dm.discardDevice(idToDiscard); break; case 7: // 退出程序 return 0; default: cout << "Invalid choice. Please try again." << endl; break; } } } ``` 以上就是一个简单的设备管理系统的C++实现。当然,这只是一个初步的实现,如果要开发一个更完整、更稳定、更易用的设备管理系统,还需要考虑更多的细节和功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值