【问题标题】:Enable and disable USB port启用和禁用 USB 端口
【发布时间】:2013-10-10 08:28:38
【问题描述】:

谁能告诉我如何使用 C/C++ 启用和禁用 USB 端口。

我已经搜索了一种方法来做到这一点..使用 Windows 注册表,但它存在一些问题。

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\USBSTOR

将start值改为3----解除阻塞 4----块

它在 Windows 7 上没有显示正确的行为。例如- 当我将起始值的值更改为 4 时,它会禁用 USB 端口,但再次启用我们需要重新启动系统,并且在禁用所有端口后还有一件事被禁用,但我们仍然能够使用已经插入的设备。

还有其他方法吗?

【问题讨论】:

  • "It does not show correct behavior on windows 7." 详细说明。
  • @Raghav Guar 你试过这个吗?打开注册表编辑器,导航到 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\USBSTOR,键入 4,按 OK。它有效吗?如果是,您可以使用 win api 来处理注册表
  • @Qwerty:我已经使用了你的方法,我也在我的问题中描述了它。这种方法在 windows xp 中运行良好,但在 windows 7 中不行。
  • @jonathon Reinhart:当我将 start 值更改为 4 时,它会禁用 USB 端口,但再次启用我们需要重新启动系统,并且在禁用所有端口后还有一件事被禁用但仍然我们可以使用设备,已经插入..
  • 找到了这个话题:social.msdn.microsoft.com/Forums/vstudio/en-US/…。好像是USB的问题,不能禁用?

标签: c++ c windows


【解决方案1】:

我已经找到了另一种使用 devcon 实用程序的解决方案。 它提供了各种命令来启用和禁用 USB 设备。

http://msdn.microsoft.com/en-us/library/windows/hardware/ff544746(v=vs.85).aspx#ddk_example_31_disable_devices_by_device_instance_id_tools

但它需要管理权限才能运行命令,而我没有这方面的源代码。

所以我想问你一件事.. 我听说过用于为 USB 设备编写 prog 的 libusb-win32 库。

所以有人知道吗..

任何帮助将不胜感激..

谢谢大家..

【讨论】:

  • Libusb 允许您通过安装过滤器驱动程序与 USB 设备通信。您将无法使用它禁用 USB 端口。
  • @Pete:感谢您的回复...但我还想问一件事..是否可以在使用 libusb-win32 从系统中插入或删除设备时获得中断。
  • 我不认为它有这样的功能。使用 RegisterDeviceNotification 等:msdn.microsoft.com/en-us/library/aa363431(VS.85).aspx
  • 您可以解析 DEV_BROADCAST_DEVICEINTERFACE::dbcc_name 以获取您设备的 VID 和 PID。硬件 ID 将包含字符串“\USB”、“VID_1234”和“PID_1234”。其中的数字显然会因设备而异。
  • 您可能还想注册特定界面 GUID 的通知。我想你可以在你的 libusb 设备的 inf 文件中看到这一点。
【解决方案2】:

这真的是在回答问题 r.e.设备检测。

在您的控制台应用程序中创建一个隐藏窗口。

此示例假设您有一个名为 DevNotifier 的类,并带有一个 HWND hidden_wnd_; 成员变量:

static TCHAR const        s_window_class[] = _T("Device notification window");
static TCHAR const* const s_window_title   = s_window_class;

LRESULT CALLBACK 
DevNotifierWndProc(
    HWND    hWnd, 
    UINT    message, 
    WPARAM  wParam, 
    LPARAM  lParam
) {
    DevNotifier* dn = (DevNotifier*) ::GetWindowLongPtr(hWnd, GWLP_USERDATA);
    switch (message)
    {
    case WM_DEVICECHANGE:
        dn->onWM_DEVICECHANGE(
            wParam,
            lParam
        );
    break;
    default:
        return ::DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

void
DevNotifier::createHiddenWindow()
{
        HINSTANCE hinstance = ::GetModuleHandle(NULL);

        if ((hinstance == 0) || (hinstance == INVALID_HANDLE_VALUE))
        {
            throw Exception("Failed to get application instance handle.");
        }

        // register window class

        WNDCLASSEX wcex;

        ::memset(&wcex, 0, sizeof(wcex));

        wcex.cbSize = sizeof(WNDCLASSEX);

        wcex.style          = 0;
        wcex.lpfnWndProc    = &DevNotifierWndProc;
        wcex.cbClsExtra     = 0;
        wcex.cbWndExtra     = 0;
        wcex.hInstance      = hinstance;
        wcex.hIcon          = 0;
        wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
        wcex.hbrBackground  = 0;
        wcex.lpszMenuName   = 0;
        wcex.lpszClassName  = s_window_class;
        wcex.hIconSm        = 0;

        (void) ::RegisterClassEx(&wcex);

        // Create the window

        hidden_wnd_ = ::CreateWindow(
            s_window_class, 
            s_window_title,
            WS_POPUP,
            CW_USEDEFAULT, 
            CW_USEDEFAULT, 
            CW_USEDEFAULT, 
            CW_USEDEFAULT, 
            NULL, 
            NULL, 
            hinstance, 
            NULL
        );

        if (!hidden_wnd_) {
            throw Exception("Failed to create device notification window");
        }
    #ifdef _WIN64
        ::SetWindowLongPtr(static_cast<HWND>(hidden_wnd_), GWLP_USERDATA, (LONG_PTR)this);
    #else
        ::SetWindowLongPtr(static_cast<HWND>(hidden_wnd_), GWLP_USERDATA, (LONG)this);
    #endif
        ::ShowWindow(static_cast<HWND>(hidden_wnd_), SW_HIDE);
}

您可以在 hidden_​​wnd_ 上注册通知。
例如

    DEV_BROADCAST_DEVICEINTERFACE filter;
    ZeroMemory(&filter, sizeof(filter));
    filter.dbcc_size = sizeof(filter);
    filter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
    filter.dbcc_classguid = /* SOME INTERFACE GUID */;
    HDEVNOTIFY hdn = ::RegisterDeviceNotification(
        hidden_wnd_, 
        &filter, 
        DEVICE_NOTIFY_WINDOW_HANDLE
    );

您需要实现处理 WM_DEVICE_CHANGE 消息的函数:

bool
DevNotifier::onWM_DEVICECHANGE(WPARAM wparam, LPARAM lparam)
{
    DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*)lparam;
    // Note dbh will NOT always be valid, depending upon the value of wparam.

    if (wparam == DBT_DEVNODES_CHANGED) {
        // Do some stuff here
        return true;
    }
    else if (wparam == DBT_DEVICEARRIVAL) {
        DEV_BROADCAST_HDR* hdr = (DEV_BROADCAST_HDR*)lparam;
        if (hdr->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) {
            DEV_BROADCAST_DEVICEINTERFACE* devinterface = 
                (DEV_BROADCAST_DEVICEINTERFACE*)hdr;

            // Do some stuff here
        }       
    }
    else if (wparam == DBT_DEVICEREMOVEPENDING) {
    }
    else if (wparam == DBT_DEVICEREMOVECOMPLETE) {
        HANDLE h = INVALID_HANDLE_VALUE;
        DEV_BROADCAST_HDR* phdr = (DEV_BROADCAST_HDR*) lparam;
        if (phdr->dbch_devicetype == DBT_DEVTYP_HANDLE) {
            DEV_BROADCAST_HANDLE* pdbh = (DEV_BROADCAST_HANDLE*) lparam;
            h = pdbh->dbch_handle;
        }
        else if (phdr->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) {
            DEV_BROADCAST_DEVICEINTERFACE* devinterface = 
                (DEV_BROADCAST_DEVICEINTERFACE*)phdr;

            // Do some stuff here
        }
        // Maybe do some stuff here too.
    }
    return false;
}

在您的控制台应用程序中,您将不得不运行消息泵以使 Windows 消息正常工作。如果您在应用程序等待消息时还有其他事情要做,那么您也需要在这里处理。

while (GetMessage(&message, NULL, 0, 0) > 0) {
  TranslateMessage(&message);
  DispatchMessage(&message);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-18
    • 2015-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多