Вывод имени USB-девайса

184
21 января 2019, 16:50

Пытаюсь вывести имя нового USB-девайса, когда его подключают. Проблема в том, что при вставке флешки messagebox появляется, но на нем ничего нет. Где-то давно находил в интернете: "Когда приходит WM_DEVICECHANGE, смотрим, чтобы wParam был равен DBT_DEVICEARRIVAL. В lParam тогда будет указатель на DEV_BROADCAST_DEVICEINTERFACE. Если в его dbcc_devicetype будет значение DBT_DEVTYP_DEVICEINTERFACE, тогда в dbcc_name будет имя устройства." Я пытался что-то написать и как-то получить этот указатель из lParam (см. код ниже), но этот указатель не содержит поля-имени. Вообщем, я понятия не имею что нужно написать после проверки wParam и просто написал примерный код. Прошу помощи с решением этой задачи.

Глобальная часть:

#include <windows.h>
//DEV_BROADCAST_DEVICEINTERFACE struct
#include "dbt.h"
//contains initguid.h and usbiodef.h
#include "GUIDheader.h"
HDEVNOTIFY NotificationHande;
DEV_BROADCAST_DEVICEINTERFACE DeviceStruct;

Оконная процедура:

LRESULT CALLBACK WndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
    switch (uMsg)
    {
    case(WM_CREATE):
        DeviceStruct.dbcc_size = sizeof(DeviceStruct);
        DeviceStruct.dbcc_classguid = GUID_DEVINTERFACE_USB_DEVICE;
        DeviceStruct.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
        NotificationHande = RegisterDeviceNotification(hWnd, &DeviceStruct, DEVICE_NOTIFY_WINDOW_HANDLE | DEVICE_NOTIFY_ALL_INTERFACE_CLASSES);
        break;
    case (WM_DESTROY):
        PostQuitMessage(0);
        break;
    case(WM_DEVICECHANGE):
        if (wParam == DBT_DEVICEARRIVAL)
        {
            DEV_BROADCAST_HDR* NewDevice = (DEV_BROADCAST_HDR*)lParam;
            if (NewDevice->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
            {
                MessageBox(0,(LPCSTR)DeviceStruct.dbcc_name, (LPCSTR)"WOW", MB_OK);
            }
        }
        break;
    default:
        return DefWindowProc(hWnd, uMsg, wParam, lParam);
    }
    return 0;
}

Основная функция:

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    // Main window handle
    HWND hMainWnd;
    WNDCLASSEX wc;                      
    wc.cbSize = sizeof(wc);
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = WndProc;
    wc.lpszMenuName = NULL;             
    wc.lpszClassName = "WindowClass";           
    wc.cbWndExtra = NULL;
    wc.cbClsExtra = NULL;
    wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wc.hInstance = hInstance;
    wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
    wc.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    if (!RegisterClassEx(&wc))
    {
        MessageBox(0, "Cannot register class.", "Error", MB_OK);
        return 0;
    }
    hMainWnd = CreateWindowEx(0, "WindowClass", "", WS_SYSMENU, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, 0, 0, hInstance, 0);
    if (hMainWnd == 0)
    {
        MessageBox(0, "Cannot create window.", "Error", MB_OK);
        return 0;
    }
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    MSG message;
    while (GetMessage(&message, NULL, 0, 0))
    {
        TranslateMessage(&message);
        DispatchMessage(&message);
    }
    DestroyWindow(hMainWnd);
    UnregisterClass(wc.lpszClassName, hInstance);
    return 0;
}
Answer 1

У вас не из той структуры значение берется. Да и значение в структуре на самом деле не имя устройства, а путь к нему. Имя устройства еще нужно искать (проще всего, через реестр). Как-то так:

#include <Windows.h>
#include "dbt.h"
#include "initguid.h"
#include "usbiodef.h"
//...
HDEVNOTIFY NotificationHande;
DEV_BROADCAST_DEVICEINTERFACE DeviceStruct;
//получение имени устройства
bool GetDeviceName(const wchar_t* symlink, wchar_t* name, int cname) {
    if(symlink == NULL) return false;
    if (name == NULL) return false;
    if (wcslen(symlink) < 10) return false;
    //распарсим путь к устройству на составляющие
    const wchar_t* pEnum = symlink + 3;
    const wchar_t* pDeviceID = wcsstr(symlink, L"#");
    if(pDeviceID == NULL) return false;
    int lenEnum = pDeviceID - pEnum;
    pDeviceID++;
    const wchar_t* pInstID = wcsstr(pDeviceID, L"#");
    if (pInstID == NULL) return false;
    int lenDeviceID = pInstID - pDeviceID;
    pInstID++;
    const wchar_t* pEnd = wcsstr(pInstID, L"#");
    if (pEnd == NULL) return false;
    int lenInstID = pEnd - pInstID;
    //соберем из них путь к ключу реестра
    wchar_t path[1024] = L"SYSTEM\\CurrentControlSet\\Enum";    
    wcsncat_s(path, 1024, pEnum, lenEnum);
    wcsncat_s(path, 1024, L"\\", 1);
    wcsncat_s(path, 1024, pDeviceID, lenDeviceID);
    wcsncat_s(path, 1024, L"\\", 1);
    wcsncat_s(path, 1024, pInstID, lenInstID);
    //попытаемся получить имя или описание устройства из реестра
    HKEY hKey = NULL;
    LONG lRes = RegOpenKeyExW(HKEY_LOCAL_MACHINE, path, 0, KEY_READ, &hKey);
    if (ERROR_SUCCESS != lRes)
    {       
        return false;
    }
    WCHAR szBuffer[1024] = L"";
    DWORD dwBufferSize = sizeof(szBuffer);
    lRes = RegQueryValueExW(hKey, L"FriendlyName", 0, NULL, (LPBYTE)szBuffer, &dwBufferSize);
    if (ERROR_SUCCESS != lRes)
    {
        dwBufferSize = sizeof(szBuffer);
        lRes = RegQueryValueExW(hKey, L"DeviceDesc", 0, NULL, (LPBYTE)szBuffer, &dwBufferSize);
    }
    if (ERROR_SUCCESS != lRes)
    {       
        RegCloseKey(hKey);
        return false;
    }
    wcscpy_s(name, cname, szBuffer);
    return true;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_CREATE:
        {               
        DeviceStruct.dbcc_size = sizeof(DeviceStruct);
        DeviceStruct.dbcc_classguid = GUID_DEVINTERFACE_USB_DEVICE;
        DeviceStruct.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
        NotificationHande = RegisterDeviceNotification(hWnd, &DeviceStruct, DEVICE_NOTIFY_WINDOW_HANDLE | DEVICE_NOTIFY_ALL_INTERFACE_CLASSES);
        }
        break;
    case WM_DEVICECHANGE:
        if (wParam == DBT_DEVICEARRIVAL)
        {
            DEV_BROADCAST_HDR* NewDevice = (DEV_BROADCAST_HDR*)lParam;
            if (NewDevice->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
            {
                DEV_BROADCAST_DEVICEINTERFACE* pDev = (DEV_BROADCAST_DEVICEINTERFACE*)lParam;
                WCHAR name[1024] = L"";
                if(GetDeviceName(pDev->dbcc_name, name, 1024) != false)
                    MessageBoxW(hWnd, name, L"Device", MB_OK);
                else 
                    MessageBoxW(hWnd, pDev->dbcc_name, L"Device", MB_OK);
            }
        }
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}
READ ALSO
CLion отображение символов

CLion отображение символов

Неправильно отображаются символы в сообщениях об ошибках в терминале CLionСреди руководств в инете полезной информации не нашел, поэтому надеюсь...

144
Меню в консоли через C++

Меню в консоли через C++

заинтересовала одна вещь и возможность ее реализацииХочу создать меню выбора в Командной строке на C++, это должно выглядеть примерно так:

161
Найти максимальное значение массива

Найти максимальное значение массива

По условию задачи можно задать любой массив, так что я его рандомизировалСейчас только начал составлять код, при компиляции выдает кучу ошибок,...

310
libcurl проблема с прокси

libcurl проблема с прокси

В файле содержатся несколько прокси ip:portНе могу по циклу проверить каждый прокси на доступность к сайту

180