You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Windows下数据传输时禁用USB存储设备的技术方案求助

解决USB传输数据时无法禁用的替代方案

原因分析

原代码依赖SetupDiCallClassInstaller执行DIF_PROPERTYCHANGE来禁用设备,但当USB驱动器处于数据传输中时,系统会因为设备被进程占用而拒绝操作,返回错误码13(资源占用/权限冲突)。

替代方案

1. 强制卸载设备(使用CM_Request_Device_Eject)

此API可尝试强制弹出设备,即使有数据传输正在进行,但会直接中断传输,可能导致数据丢失,需谨慎使用。

代码示例:

#include <Cfgmgr32.h>
#pragma comment(lib, "Cfgmgr32.lib")

BOOL ForceEjectUsbDevice(LPCWSTR deviceInstanceId) {
    DEVINST devInst;
    CONFIGRET cr = CM_Locate_DevNode(&devInst, deviceInstanceId, CM_LOCATE_DEVNODE_NORMAL);
    if (cr != CR_SUCCESS) {
        return FALSE;
    }

    // 执行强制弹出操作
    cr = CM_Request_Device_Eject(devInst, NULL, NULL, 0, 0);
    return cr == CR_SUCCESS;
}

注意:操作前需提示用户数据会中断,避免损失。

2. 终止占用进程后再禁用

先找到并终止正在访问USB驱动器的进程,消除资源占用后再执行原禁用逻辑。

步骤:

  • 获取目标USB的盘符(如D:)
  • 枚举系统所有进程
  • 检查每个进程是否打开了该盘符下的文件句柄
  • 终止关联进程后,调用原代码禁用设备

代码片段(简化版进程检查):

#include <Windows.h>
#include <Psapi.h>
#pragma comment(lib, "Psapi.lib")

BOOL TerminateProcessesUsingDrive(char driveLetter) {
    DWORD processIds[1024];
    DWORD bytesReturned;
    if (!EnumProcesses(processIds, sizeof(processIds), &bytesReturned)) {
        return FALSE;
    }

    int numProcesses = bytesReturned / sizeof(DWORD);
    char drivePath[4] = {driveLetter, ':', '\\', 0};
    
    for (int i = 0; i < numProcesses; i++) {
        HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_TERMINATE, FALSE, processIds[i]);
        if (hProcess) {
            // 尝试打开驱动器,判断是否被占用
            HANDLE hDrive = CreateFileA(drivePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
            if (hDrive == INVALID_HANDLE_VALUE && GetLastError() == ERROR_SHARING_VIOLATION) {
                TerminateProcess(hProcess, 0);
            }
            if (hDrive != INVALID_HANDLE_VALUE) CloseHandle(hDrive);
            CloseHandle(hProcess);
        }
    }
    return TRUE;
}

注意:终止进程可能导致系统不稳定或数据丢失,需确认操作必要性。

3. 注册表/组策略全局禁用USB存储

通过修改系统注册表,从服务层面禁用所有USB存储设备,不受当前设备状态影响。

注册表操作代码:

#include <Windows.h>

BOOL DisableUsbStorageGlobally() {
    HKEY hKey;
    LONG result = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\USBSTOR", 0, KEY_SET_VALUE, &hKey);
    if (result != ERROR_SUCCESS) {
        return FALSE;
    }

    DWORD startValue = 4; // 4=禁用USB存储服务,3=恢复启用
    result = RegSetValueExA(hKey, "Start", 0, REG_DWORD, (BYTE*)&startValue, sizeof(DWORD));
    RegCloseKey(hKey);
    return result == ERROR_SUCCESS;
}

注意:需要管理员权限,且会禁用所有USB存储设备(包括未连接的)。

4. WMI禁用设备

通过WMI的Win32_PnPEntity类执行禁用操作,部分场景下可绕过临时资源占用问题。

代码示例:

#include <comdef.h>
#include <Wbemidl.h>
#pragma comment(lib, "wbemuuid.lib")

BOOL DisableUsbDeviceViaWMI(LPCWSTR deviceInstanceId) {
    HRESULT hres = CoInitializeEx(0, COINIT_MULTITHREADED);
    if (FAILED(hres)) return FALSE;

    hres = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);
    if (FAILED(hres)) { CoUninitialize(); return FALSE; }

    IWbemLocator* pLoc = NULL;
    hres = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID*)&pLoc);
    if (FAILED(hres)) { CoUninitialize(); return FALSE; }

    IWbemServices* pSvc = NULL;
    hres = pLoc->ConnectServer(_bstr_t(L"ROOT\\CIMV2"), NULL, NULL, 0, NULL, 0, 0, &pSvc);
    if (FAILED(hres)) { pLoc->Release(); CoUninitialize(); return FALSE; }

    hres = CoSetProxyBlanket(pSvc, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE);
    if (FAILED(hres)) { pSvc->Release(); pLoc->Release(); CoUninitialize(); return FALSE; }

    // 查询目标设备并执行禁用
    IEnumWbemClassObject* pEnumerator = NULL;
    wchar_t query[256];
    swprintf_s(query, L"SELECT * FROM Win32_PnPEntity WHERE DeviceID='%s'", deviceInstanceId);
    hres = pSvc->ExecQuery(_bstr_t(L"WQL"), _bstr_t(query), WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator);
    if (FAILED(hres)) { pSvc->Release(); pLoc->Release(); CoUninitialize(); return FALSE; }

    IWbemClassObject* pclsObj = NULL;
    ULONG uReturn = 0;
    BOOL success = FALSE;
    while (pEnumerator) {
        HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
        if (uReturn == 0) break;

        VARIANT vtResult;
        hr = pclsObj->ExecMethod(_bstr_t(L"Disable"), 0, NULL, NULL, &vtResult);
        if (SUCCEEDED(hr)) success = TRUE;
        
        VariantClear(&vtResult);
        pclsObj->Release();
    }

    pEnumerator->Release();
    pSvc->Release();
    pLoc->Release();
    CoUninitialize();
    return success;
}

注意:需要管理员权限,部分设备可能不支持WMI禁用操作。

内容的提问来源于stack exchange,提问作者Ashwin arjunan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 13:40:39