在 Qt 中运行可执行文件失败,在 Windows cmd 中运行成功

发布于 2025-01-11 00:59:46 字数 1766 浏览 0 评论 0原文

我想在 Qt 应用程序中弹出可移动 USB 磁盘,并使用 Microsoft 的一个名为 Sync 的工具(download) ,用法是 sync.exe -e [E:]

所以我从 Qt 运行这个工具,代码如下:

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

运行后这段代码,可移动U盘是未弹出,如果我使用托盘图标弹出磁盘,它会警告磁盘正在使用中。

但是,如果我使用 Windows 资源管理器托盘图标或在 cmd 或 powershell 中运行sync.exe,它就能够弹出该设备。我是否缺少某些内容,或者在 shell 和 Qt 中运行 exe 之间存在差异。

这个问题困扰我好几天了,希望有人能帮忙。

提前致谢!

[2022-03-03更新]

经过测试,我缩小了问题的范围。 我的应用场景是这样的,首先点击QPushButton弹出可移动设备列表,然后选择要弹出的设备,点击菜单项,调用真正的弹出函数。 顺便说一句,设备列表小部件设置了 Qt::Popup 属性。

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

我发现如果我直接调用弹出设备功能,它执行正常,但如果单击具有相同代码的弹出菜单项失败。有什么区别?

成功:

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

失败:

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

I want to eject removable USB disk in Qt application, and was using a tool from Microsoft called Sync(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**
        });
}
....

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

_畞蕅 2025-01-18 00:59:46

我不认为是这样,但构建可执行文件路径的更好方法是

QStringjectToolPath = QDir(qApp->applicationDirPath()).filePath("sync.exe")

Qt 在 中构建应用程序>debug/release/ 文件夹(如果 Shadowbuild 被禁用)和 build-xxxx 文件夹(如果启用),您是否 100% 确定sync.exe 位于应用程序文件夹中?再次检查不会有什么坏处。

qDebug() << QFile(ejectToolPath).exists()

如果存在,则仅当 sync.exe 依赖的库之一不在 %PATH 中时,startDetached 才会启动失败%。

同步需要路径或驱动器号吗? E: 可能被视为无效路径,正确的版本是 E:\ - 带有强制尾部斜杠。

I dont think it's the case but better way to build path to executable is

QString ejectToolPath = QDir(qApp->applicationDirPath()).filePath("sync.exe")

Qt builds application in debug/ or release/ folder if shadowbuild is disabled and in build-xxxx folder if enabled, are you 100% sure sync.exe is in application folder? It wont hurt to check again.

qDebug() << QFile(ejectToolPath).exists()

If it's there startDetached can only fail to start if one of libraries that sync.exe depends on is not in %PATH%.

Does sync expect path or drive letter? E: may be considered as ivalid path, the correct version is E:\ - with mandatory trailing slash.

缪败 2025-01-18 00:59:46

这是我的问题。当我枚举可移动 USB 磁盘时,我忘记关闭设备句柄。这会导致设备正在使用,与Qt无关。
感谢您的帮助! @mugiseebrows

STORAGE_HOTPLUG_INFO HMStatusBarWidget::getDeviceType(char driveLetter)

{
STORAGE_HOTPLUG_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;

}

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;

}

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文