我有一个填充有QFileSystemModel的QTreeView,并将根路径设置为“ \”(作为“ \\”)。这工作得很好,并且可以看到本地驱动器和USB驱动器。我的问题是,当我使用DeviceIoControl(...,FSCTL_DISMOUNT_VOLUME,...)以编程方式弹出USB驱动器(我正在以信息亭模式为Win7应用程序编程,因此它需要处理Windows级活动)时,随后通过DeviceIoControl(...,IOCTL_STORAGE_EJECT_MEDIA,...),尽管两个函数都返回true,并且Windows系统服务托盘未显示USB图标,并且Windows资源管理器没有USB条目,但我的QFileSystemModel仍然看到驱动器。

我确实有一个从QSortFilterProxyModel派生的代理模型,并且正在过滤所看到的内容,因为我真的只想查看USB驱动器。这正在调用我的USBController类来检测已安装的可移动设备。该函数调用GetLogicalDrives(),它实际上返回我刚刚以编程方式弹出的USB的驱动器号。

我一直在寻找解决这个难题的方法,但是还没有解决这个难题。有没有人有什么建议?以下是相关代码:

来自UsbController.h的函数:

bool UsbController::ejectDrive(char driveletter, QString &errmsg)
{
    char devicepath[7];
    char format[] = "\\\\.\\?:";
    strcpy_s(devicepath, format);
    devicepath[4] = driveletter;
    errmsg = "";

    DWORD dwRet = 0;
    wchar_t wtext[7];
    size_t textlen = 7;
    mbstowcs_s(&textlen, wtext, devicepath,strlen(devicepath)+1);
    HANDLE hVol = CreateFile(wtext, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
    if (hVol == INVALID_HANDLE_VALUE)
    {
        FormatErrorMsg("CreateFile: ", errmsg);
        return false;
    }

    if(!DeviceIoControl(hVol, FSCTL_LOCK_VOLUME, 0, 0, 0, 0, &dwRet, 0))
    {
        FormatErrorMsg("Lock Volume: ", errmsg);
        return false;
    }

    if(!DeviceIoControl(hVol, FSCTL_DISMOUNT_VOLUME, 0, 0, 0, 0, &dwRet, 0))
    {
        FormatErrorMsg("Dismount Volume: ", errmsg);
        return false;
    }

    if (!DeviceIoControl(hVol, IOCTL_STORAGE_EJECT_MEDIA, 0, 0, 0, 0, &dwRet, 0))
    {
        FormatErrorMsg("Eject Media: ", errmsg);
        return false;
    }

    CloseHandle(hVol);
    return true;
}

QMap<QString,QString> UsbController::getMountedRemovables()
{
    DWORD test = GetLogicalDrives();
    DWORD mask = 1;
    UINT type = 0;
    WCHAR wdrive[] = L"?:\\"; // use as a drive letter template

    QMap<QString,QString> removables;
    for (int i = 0; i < 32; i++)
    {
        if (test & mask)
        {
            wdrive[0] = (char)('A' + i); // change letter in template
            type = GetDriveType(wdrive);
            switch (type) {
            case DRIVE_REMOVABLE:
            {
                QString qdrive = QString((char)('A' + i)) + ":";
                if (!removables.contains(qdrive))
                {
                    QString name = mountNameFromDriveLetter((char)('A' + i));
                    removables.insert(qdrive, name);
                }
                break;
            }
            default: break;
            }
        }
        mask = mask << 1;
    }

    return removables;
}


我的代理模型中的功能(数据使用了acceptedRemovables QMap,该QMap通过调用UsbController填充在detectMountedRemovables()中:

QVariant DriveFilterProxyModel::data(const QModelIndex & index, int role) const
{
    QVariant data = QSortFilterProxyModel::data(index, role);

    if (role == Qt::DisplayRole)
    {
        QString source = data.toString();

        for (int i = 0; i < acceptList.size(); i++)
        {
            if (source.contains(acceptList[i]))
            {
                QString drivestring = source;
                if (drivestring.contains('('))
                {
                    drivestring = drivestring.remove(0, drivestring.indexOf('(')+1);
                    drivestring = drivestring.remove(drivestring.indexOf(')'), drivestring.size()-drivestring.indexOf(')')+1);
                }
                QMap<QString,QString>::const_iterator iter = acceptedNonRemovables.find(drivestring);
                if (iter != acceptedNonRemovables.end())
                {
                    if (source.contains("Data")) // no path as yet applied
                    {
                        QString newsource(source);
                        newsource.replace("Data", iter.value());
                        qDebug() << "DriveFilterProxyModel::filterAcceptsRow(): Mapped drive: should replace \"Data\" with: " << iter.value() << " to produce: " << newsource;
                        return newsource;
                    }
                }
                else
                {
                    iter = acceptedRemovables.find(drivestring);
                    if (iter != acceptedRemovables.end())
                    {
                        if (!source.contains('(')) // no drive name found
                        {
                            QString newsource = QString("Removable Disk (%1)").arg(source);
                            qDebug() << "DriveFilterProxyModel::filterAcceptsRow(): USB drive: should change simple drive letter to: " << newsource;
                            return newsource;
                        }
                    }
                }
            }
        }
    }

    return data;
}

void DriveFilterProxyModel::detectMountedRemovables()
{
    acceptedRemovables = UsbController::getMountedRemovables();
    resetAcceptList();
}

最佳答案

我猜该驱动器仍可被系统识别,但仍处于退出模式。

看一下Enumerating all available drive letters in Windows问题,可能是您在那里找到了可行的解决方案。

关于c++ - c++ Qt/Win32-USB以编程方式弹出,但仍显示在QFileSystemModel和GetLogicalDrives()中,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/29102553/

10-11 22:53
查看更多