Wednesday, April 13, 2022

[SOLVED] Run executable in Qt failed while successful in windows cmd

Issue

I want to eject removable USB disk in Qt application, and was using a tool from Microsoft called Sync(rel="nofollow noreferrer">download) , the usage is sync.exe -e [E:]

So I was running this tool from Qt with code below:

QString ejectToolPath = QString("%1/sync.exe").arg(qApp->applicationDirPath());
QStringList params;
params << "-e" << driveLetter;
QProcess::startDetached(ejectToolPath, params);

after running this code, the removable Usb disk was not ejected, and if I use the tray icon to eject the disk, it warns the disk is in use.

But if I use the windows explorer tray icon or run the sync.exe in cmd or powershell, it was able to eject that device.Am I missing something or there is difference between run the exe in shell and in Qt.

This problem has tormented me for days, hope someone can help.

Thanks in advance!

[2022-03-03 update]

After testing, I narrowed down the scope of the problem. My application scenario is like this, First click the QPushButton to popup the removable device list, then select the device to eject, on click of the menu item, call the real eject function. By the way, the device list widget is set the Qt::Popup attribute.

setWindowFlags(windowFlags() | Qt::FramelessWindowHint | Qt::Popup);

I found if I directly call eject device function, it performs OK, but if fail on click the popup menu item with the same code. what was the difference?

SUCEESS:

void HMStatusBarWidget::onPluginButtonClick() {
ejectDevice("D:"); // **success**
/*QHash<QString, QString> deviceList;
if (deviceListWidget_ == nullptr) {
    deviceListWidget_ = new PopupListWidget(this);
    connect(deviceListWidget_, &PopupListWidget::textItemClicked, [=]() {
        ejectDevice("D:"); // **fail**
        });
}*/
....

FAILURE:

void HMStatusBarWidget::onPluginButtonClick() {
//ejectDevice("D:"); // **success**
QHash<QString, QString> deviceList;
if (deviceListWidget_ == nullptr) {
    deviceListWidget_ = new PopupListWidget(this);
    connect(deviceListWidget_, &PopupListWidget::textItemClicked, [=]() {
        ejectDevice("D:"); // **fail**
        });
}
....

Solution

It's my problem. When I was enumerating removable usb disks, I forget to close the device handle. This cause the device in use, It has nothing to do with Qt. Thanks for your help! @mugiseyebrows

STORAGE_HOTPLUG_INFO HMStatusBarWidget::getDeviceType(char driveLetter)

{ STORAGE_HOTPLUG_INFO Info = { 0 };

HANDLE hDevice = getDeviceHandle(driveLetter);
if (hDevice == INVALID_HANDLE_VALUE) {
    CloseHandle(hDevice);
    return Info;
}

DWORD bytesReturned = 0;
DeviceIoControl(hDevice, IOCTL_STORAGE_GET_HOTPLUG_INFO, 0, 0, &Info, sizeof(Info), &bytesReturned, NULL);
CloseHandle(hDevice);

return Info;

}



Answered By - Qiang Wang
Answer Checked By - Pedro (WPSolving Volunteer)