在C ++非GUI应用程序中检测USB插入/删除

时间:2013-04-25 12:26:37

标签: c++ windows usb

我想通过在后台运行并且没有GUI的C ++应用程序来检测特定(自定义)USB设备的插入/删除。

我看到很多问题及其解决方案RegisterDeviceNotification也在MSDN

上提供示例代码

但是这些应用程序都有一些Window / Form / GUI。我的申请没有。 如何在我的应用程序中使用它?

我的最后一个选择是创建一个不可见的窗口......但还有其他出路吗?

5 个答案:

答案 0 :(得分:5)

创建message-only window。尽管名称,它实际上只是一个消息队列。

答案 1 :(得分:3)

#define ANSI
#define WIN32_LEAN_AND_MEAN
#define _WIN32_WINNT   0x0501

#include <windows.h>
#include <winuser.h>
#include <Dbt.h>

#include <string>
#include <iostream>
#include <stdexcept>

#define HID_CLASSGUID {0x4d1e55b2, 0xf16f, 0x11cf,{ 0x88, 0xcb, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30}}
#define CLS_NAME "DUMMY_CLASS"
#define HWND_MESSAGE     ((HWND)-3)

LRESULT message_handler(HWND__* hwnd, UINT uint, WPARAM wparam, LPARAM lparam)
{
    switch (uint)
    {
    case WM_NCCREATE: // before window creation
        return true;
        break;

    case WM_CREATE: // the actual creation of the window
    {
        // you can get your creation params here..like GUID..
        LPCREATESTRUCT params = (LPCREATESTRUCT) lparam;
        GUID InterfaceClassGuid = *((GUID*)params->lpCreateParams);
        DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;
        ZeroMemory(&NotificationFilter, sizeof(NotificationFilter));
        NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
        NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
        NotificationFilter.dbcc_classguid = InterfaceClassGuid;
        HDEVNOTIFY dev_notify = RegisterDeviceNotification(hwnd, &NotificationFilter,
                                                           DEVICE_NOTIFY_WINDOW_HANDLE);
        if(dev_notify == NULL)
        {
            throw std::runtime_error("Could not register for devicenotifications!");
        }
        break;
    }

    case WM_DEVICECHANGE:
    {
        PDEV_BROADCAST_HDR lpdb = (PDEV_BROADCAST_HDR) lparam;
        PDEV_BROADCAST_DEVICEINTERFACE lpdbv = (PDEV_BROADCAST_DEVICEINTERFACE) lpdb;
        std::string path;
        if (lpdb->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
        {
            path = std::string(lpdbv->dbcc_name);
            switch (wparam)
            {
            case DBT_DEVICEARRIVAL:
                std::cout << "new device connected: " << path << "\n";
                break;

            case DBT_DEVICEREMOVECOMPLETE:
                std::cout << "device disconnected: " << path << "\n";
                break;
            }
        }
        break;
    }

    }
    return 0L;
}

int main(int argc, char* argv[])
{
    HWND hWnd = NULL;
    WNDCLASSEX wx;
    ZeroMemory(&wx, sizeof(wx));

    wx.cbSize = sizeof(WNDCLASSEX);
    wx.lpfnWndProc = reinterpret_cast<WNDPROC>(message_handler);
    wx.hInstance = reinterpret_cast<HINSTANCE>(GetModuleHandle(0));
    wx.style = CS_HREDRAW | CS_VREDRAW;
    wx.hInstance = GetModuleHandle(0);
    wx.hbrBackground = (HBRUSH)(COLOR_WINDOW);
    wx.lpszClassName = CLS_NAME;

    GUID guid = HID_CLASSGUID;

    if (RegisterClassEx(&wx))
    {
        hWnd = CreateWindow(CLS_NAME, "DevNotifWnd", WS_ICONIC,
                            0, 0, CW_USEDEFAULT, 0, HWND_MESSAGE,
                            NULL, GetModuleHandle(0), (void*)&guid);
    }

    if(hWnd == NULL)
    {
        throw std::runtime_error("Could not create message window!");
    }

    std::cout << "waiting for new devices..\n";

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

这个简单的程序创建了一个不可见的窗口,它的消息处理程序也接收'RegisterDeviceNotification'的通知。

答案 2 :(得分:2)

外部USB存储设备检测器

此程序(C ++)检测笔式驱动器存储卡&amp; 外置硬盘(每当插入新的 USB存储设备时) -

#include <stdio.h>
#include <time.h>
#include <windows.h>
#include <string>

using namespace std;

string allDrives;

char getRemovableDisk();

int main(void){

    char driveLetter = getRemovableDisk();
    while(1){
        driveLetter = getRemovableDisk();
        if(driveLetter!='0'){
            printf("%c \n", driveLetter);
        }

        Sleep(1000);
    }

    return 0;
}

char getRemovableDisk(){
    char drive='0';

    char szLogicalDrives[MAX_PATH];
    DWORD dwResult = GetLogicalDriveStrings(MAX_PATH, szLogicalDrives);

    string currentDrives="";

    //cout << dwResult << endl;
    for(int i=0; i<dwResult; i++)
    {
        if(szLogicalDrives[i]>64 && szLogicalDrives[i]< 90)
        {
            currentDrives.append(1, szLogicalDrives[i]);

            if(allDrives.find(szLogicalDrives[i]) > 100)
            {
                drive = szLogicalDrives[i];
            }
        }
    }

    allDrives = currentDrives;

    return drive;
}

备注:此代码段只能检测一个新设备(即使一次插入多个设备)。但是,当然,您也可以通过稍微改变来实现多重检测。 :)

答案 3 :(得分:0)

首先创建服务,然后在RegisterDeviceNotification中,提供该服务的句柄而不是窗口句柄。

同时相应地调整RegisterDeviceNotification的第三个参数。

答案 4 :(得分:0)

此c ++代码检测两个USB存储设备的插入和删除。

这还将检测同时插入和移除USB设备。

c ++代码:已在VISUAL STUDIO 2015中进行了测试

您还可以检查是否有其他类型的设备可以卸下和插入。 只需将传递的char数组填充到函数 getUSBStorageDeviceList()

中的代码的if else中的其他类型的设备上
    #include "stdafx.h"
    #include <stdio.h>
    #include <time.h>
    #include <windows.h>
    #include <string>
    #include<iostream>

    using namespace std;

    #define MAX_LETTER 26
    char PREV_DRIVE_LIST[MAX_LETTER];
    char NEW_DRIVE_LIST[MAX_LETTER];

    /* To GET DRIVE LIST in char ARRAY */
    void getUSBStorageDeviceList(char drive[]) {

        int count = 0;

        char szLogicalDrives[MAX_PATH];
        size_t size = strlen(szLogicalDrives) + 1;
        wchar_t* text = new wchar_t[size];

        size_t outSize;
        mbstowcs_s(&outSize, text, size, szLogicalDrives, size - 1);

        DWORD dwResult = GetLogicalDriveStrings(MAX_PATH, text); // text = szLogicalDrives
        WCHAR* szSingleDrive = text;

        while (*szSingleDrive)
        {
            UINT nDriveType = GetDriveType(szSingleDrive);

        //  printf("\nFUNC: getRemovableDisk, Drive Name%d= %s", ++count, szSingleDrive);

            if (nDriveType == DRIVE_UNKNOWN) {
            //  cout << "\nDrive type : Unknown: The drive type cannot be determined." << endl;
            }
            else if (nDriveType == DRIVE_NO_ROOT_DIR) {
            //  cout << "\nDrive type : Invalid Root Directory Media: The root path is invalid." << endl;
            }
            else if (nDriveType == DRIVE_REMOVABLE) {
            //  cout << "\nDrive type :  Removable Media:" << endl;
                char letter = szSingleDrive[0];
                drive[letter - 65] = letter;
            }
            else if (nDriveType == DRIVE_FIXED) {
                //cout << "\nDrive type : Fixed Media: " << endl;
            }
            else if (nDriveType == DRIVE_REMOTE) {
                //cout << "\nDrive type : Remote Media: The drive is a remote (network) drive.." << endl;
            }
            else if (nDriveType == DRIVE_CDROM) {
                //cout << "\nDrive type : CD ROM:   The drive is a CD-ROM drive." << endl;
            }
            else if (nDriveType == DRIVE_RAMDISK) {
                //cout << "\nDrive type : RAM Disk: The drive is a RAM disk." << endl;
            }

            szSingleDrive += wcslen(szSingleDrive) + 1; // next drive 
        }
    }

    int main(void) {

        int count = 0;
        for (int i = 0; i < MAX_LETTER; i++) {
            PREV_DRIVE_LIST[i] = '0';
            NEW_DRIVE_LIST[i] = '0';
        }
        // initial drive list which is already attached 
        getUSBStorageDeviceList(PREV_DRIVE_LIST);

        while (1) {

            getUSBStorageDeviceList(NEW_DRIVE_LIST);
            count = 1;

            /* Check for insertion and removabal*/

            for (int i = 0; i < MAX_LETTER; i++) {
                // check for new drive
                if ((NEW_DRIVE_LIST[i] >= 65 && NEW_DRIVE_LIST[i] <= 89) && (PREV_DRIVE_LIST[i] == '0')) {

                    printf("\nNew Device Inserted%d : %c", count++, NEW_DRIVE_LIST[i]);
                    PREV_DRIVE_LIST[i] = NEW_DRIVE_LIST[i];
                }
            }
                // fill ALl zero 
                for (int i = 0; i < MAX_LETTER; i++) {
                    NEW_DRIVE_LIST[i] = '0';
                }
                // update NEW drive list
                getUSBStorageDeviceList(NEW_DRIVE_LIST);

                for (int i = 0; i < MAX_LETTER; i++) {
                    // check for removed drive
                    if ((PREV_DRIVE_LIST[i] >= 65 && PREV_DRIVE_LIST[i] <= 89) && (NEW_DRIVE_LIST[i] == '0')) {
                        printf("\nDevice Removed%d : %c", count++, PREV_DRIVE_LIST[i]);
                        PREV_DRIVE_LIST[i] = NEW_DRIVE_LIST[i];
                    }
            }
                Sleep(500);
        }

        return 0;
    }