文章目录
  1. 1. 简单介绍
  2. 2. 例子

简单介绍

本篇介绍如何用C++编程做出检查USB设备的插拔状态以及读取相关信息的一个小工具。
毕业工作被安排的第一个任务就是做要用C或C++的关于硬件类的。都不是太熟且对硬件类不太感兴趣,但没办法还是得硬着头皮上。网上关于USB插拔的倒是有一点小例子,但是要读出USB设备信息的例子却很少。好不容易找到一个却是用MFC做的,而以前也从没用过C的MFC编程,生搬硬套最后还是做出了这种控制台显示USB插拔状态及设备信息的小工具。

例子

以下贴出其中一些核心代码,代码有些具体的地方还不怎么懂,以后熟悉了好好研究。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// Compute Device Class: this is used to get the tree contrl root icon
static const GUID GUID_DEVCLASS_COMPUTER =
{ 0x4D36E966, 0xE325, 0x11CE, { 0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18 } };

// Copy from HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\DeviceClasses
static const GUID GUID_DEVINTERFACE_LIST[] =
{
// GUID_DEVINTERFACE_USB_DEVICE
{ 0xA5DCBF10, 0x6530, 0x11D2, { 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED } },

// GUID_DEVINTERFACE_DISK
{ 0x53f56307, 0xb6bf, 0x11d0, { 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b } },

// GUID_DEVINTERFACE_HID,
{ 0x4D1E55B2, 0xF16F, 0x11CF, { 0x88, 0xCB, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30 } },

// GUID_NDIS_LAN_CLASS
{ 0xad498944, 0x762f, 0x11d0, { 0x8d, 0xcb, 0x00, 0xc0, 0x4f, 0xc3, 0x35, 0x8c } }

//// GUID_DEVINTERFACE_COMPORT
//{ 0x86e0d1e0, 0x8089, 0x11d0, { 0x9c, 0xe4, 0x08, 0x00, 0x3e, 0x30, 0x1f, 0x73 } },

//// GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR
//{ 0x4D36E978, 0xE325, 0x11CE, { 0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18 } },

//// GUID_DEVINTERFACE_PARALLEL
//{ 0x97F76EF0, 0xF883, 0x11D0, { 0xAF, 0x1F, 0x00, 0x00, 0xF8, 0x00, 0x84, 0x5C } },

//// GUID_DEVINTERFACE_PARCLASS
//{ 0x811FC6A5, 0xF728, 0x11D0, { 0xA5, 0x37, 0x00, 0x00, 0xF8, 0x75, 0x3E, 0xD1 } }
};

查找是否有设备

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
BOOL FindDevice(HDEVINFO& hDevInfo,
CString& szDevId,
SP_DEVINFO_DATA& spDevInfoData){

spDevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
for (int i = 0; SetupDiEnumDeviceInfo(hDevInfo, i, &spDevInfoData); i++) {
DWORD nSize = 0;
TCHAR buf[MAX_PATH];

if (!SetupDiGetDeviceInstanceId(hDevInfo, &spDevInfoData, buf, sizeof(buf), &nSize)) {

return FALSE;
}
if (szDevId == buf) {
// OK, device found
return TRUE;
}
}
return FALSE;
}

更新设备信息,打印输出。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
void UpdateDevice(PDEV_BROADCAST_DEVICEINTERFACE pDevInf, WPARAM wParam){
// pDevInf->dbcc_name:
// \\?\USB#Vid_04e8&Pid_503b#0002F9A9828E0F06#{a5dcbf10-6530-11d2-901f-00c04fb951ed}
// szDevId: USB\Vid_04e8&Pid_503b\0002F9A9828E0F06
// szClass: USB
CString szDevId = pDevInf->dbcc_name + 4;
//cout << szDevId.GetBuffer() << "hello" << endl;
int idx = szDevId.ReverseFind(_T('#'));
szDevId.Truncate(idx);
szDevId.Replace(_T('#'), _T('\\'));
szDevId.MakeUpper();
CString szClass;

idx = szDevId.Find(_T('\\'));
szClass = szDevId.Left(idx);

if (DBT_DEVICEARRIVAL == wParam) {
//cout << "Adding " << szDevId.GetBuffer() << endl;//szDevId输入框设备信息
insert = true;
}
else {
//cout << "Removing " << szDevId.GetBuffer() << endl;
insert = false;

}


DWORD dwFlag = DBT_DEVICEARRIVAL != wParam ?
DIGCF_ALLCLASSES : (DIGCF_ALLCLASSES | DIGCF_PRESENT);
HDEVINFO hDevInfo = SetupDiGetClassDevs(NULL, szClass, NULL, dwFlag);

if (INVALID_HANDLE_VALUE == hDevInfo) {

return;
}

SP_DEVINFO_DATA spDevInfoData;


if (FindDevice(hDevInfo, szDevId, spDevInfoData)){

DWORD DataT;
TCHAR buf[MAX_PATH];
DWORD nSize = 0;

// get Friendly Name or Device Description
if (SetupDiGetDeviceRegistryProperty(hDevInfo, &spDevInfoData,
SPDRP_FRIENDLYNAME, &DataT, (PBYTE)buf, sizeof(buf), &nSize)) {
}
else if (SetupDiGetDeviceRegistryProperty(hDevInfo, &spDevInfoData,
SPDRP_DEVICEDESC, &DataT, (PBYTE)buf, sizeof(buf), &nSize)) {
}
else {
lstrcpy(buf, _T("Unknown"));
}

// remove device
BOOL bFound = FALSE;
szDevId.Replace(_T('\\'), _T('#'));
if (insert){
cout << "usb_connected@" << szDevId<<"$"<<buf << endl;
}
else{
cout << "usb_disconnected@" << szDevId<<"$"<< buf << endl;
}
}

}

判断设备类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if (DBT_DEVICEARRIVAL == wParam || DBT_DEVICEREMOVECOMPLETE == wParam) {
PDEV_BROADCAST_HDR pHdr = (PDEV_BROADCAST_HDR)lParam;
PDEV_BROADCAST_DEVICEINTERFACE pDevInf;
PDEV_BROADCAST_HANDLE pDevHnd;
PDEV_BROADCAST_OEM pDevOem;
PDEV_BROADCAST_PORT pDevPort;
PDEV_BROADCAST_VOLUME pDevVolume;
switch (pHdr->dbch_devicetype) {
case DBT_DEVTYP_DEVICEINTERFACE:
pDevInf = (PDEV_BROADCAST_DEVICEINTERFACE)pHdr;
UpdateDevice(pDevInf, wParam);
break;
case DBT_DEVTYP_HANDLE:
pDevHnd = (PDEV_BROADCAST_HANDLE)pHdr;
break;

case DBT_DEVTYP_OEM:
pDevOem = (PDEV_BROADCAST_OEM)pHdr;
break;

case DBT_DEVTYP_PORT:
pDevPort = (PDEV_BROADCAST_PORT)pHdr;
break;

case DBT_DEVTYP_VOLUME:
pDevVolume = (PDEV_BROADCAST_VOLUME)pHdr;
break;
}
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}

主函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
int  main(int argc, TCHAR* argv[], TCHAR* envp[])
{

TCHAR szClassName[] = _T("MyApp");
WNDCLASS wndcls = { 0 };
wndcls.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndcls.hCursor = (HCURSOR)LoadCursor(NULL, IDC_ARROW);
wndcls.hIcon = (HICON)LoadIcon(NULL, IDI_APPLICATION);
wndcls.lpfnWndProc = WndProc;
wndcls.lpszClassName = szClassName;

if (!RegisterClass(&wndcls))
{
printf("RegisterClass Failed!\r\n");
return 0;
}

HWND hWnd = CreateWindow(szClassName, szClassName, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, NULL);
if (NULL == hWnd)
{
printf("CreateWindow Failed!\r\n");
return 0;
}

ShowWindow(hWnd, SW_HIDE);
UpdateWindow(hWnd);

//printf("WM_DEVICECHANGE=%d\n", WM_DEVICECHANGE);
//printf("显示USB设备插拔变动信息:\n");

HDEVNOTIFY hDevNotify;
DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;
ZeroMemory(&NotificationFilter, sizeof(NotificationFilter));
NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
for (int i = 0; i<sizeof(GUID_DEVINTERFACE_LIST) / sizeof(GUID); i++) {
NotificationFilter.dbcc_classguid = GUID_DEVINTERFACE_LIST[i];
hDevNotify = RegisterDeviceNotification(hWnd, &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE);
if (!hDevNotify) {
printf("Can't register device notification");
return FALSE;
}
}

MSG msg;
while (GetMessage(&msg, NULL, NULL, NULL))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}

return 0;
}

运行结果如图

文章目录
  1. 1. 简单介绍
  2. 2. 例子