gpt4 book ai didi

c++ - 来自 ShellExecuteEx 的意外/不一致行为

转载 作者:行者123 更新时间:2023-11-28 04:25:35 27 4
gpt4 key购买 nike

我正在使用 Qt 在 Visual C++ (2015) 中创建自配置软件工具,根据需要运行其他几个第 3 方安装程序。当软件发现它需要一个不可用的库或驱动程序时,它将使用 ShellExecuteEx 调用适当的安装程序来打开适当的可执行文件。

如果只需要安装一个东西(ShellExecuteEx 只运行一次)一切正常。如果需要同时安装两个 东西,那么大约有 25% 的时间,安装程序将正确运行一次,而另一个将打开包含可执行文件的文件夹,而不是运行可执行文件。关于正确运行的是第一个还是第二个操作,没有一致性。

ShellExecuteEx 声称在这两种情况下都能正确运行(返回 true)。我已验证每次都提供了可执行文件(和工作目录)的正确路径。我尝试在 ShellExecuteEx 中同时使用动词“open”和“NULL”,但行为没有变化。

如果重要的话,两个可执行文件都需要管理权限。当一切正常时,他们都会按预期进行。当失败时,它不会请求管理员权限。

我找不到任何人遇到类似问题的记录,这可能意味着我以某种基本方式滥用了 ShellExecuteEx,但我没有看到它。在此先感谢您的任何建议或建议。

代码如下:

if(dummy1Required && !dummy1Present){
SHELLEXECUTEINFOA execinfo = {};
execinfo.cbSize = sizeof(SHELLEXECUTEINFOA);
execinfo.fMask = NULL;
execinfo.hwnd = NULL;
execinfo.lpVerb = NULL;
execinfo.lpFile = QDir::toNativeSeparators(QCoreApplication::applicationDirPath() + "/Drivers/dummy1/install.bat").toLocal8Bit().data();
execinfo.lpParameters = NULL;
execinfo.lpDirectory = QDir::toNativeSeparators(QCoreApplication::applicationDirPath() + "/Drivers/dummy1").toLocal8Bit().data();
printf("Dummy1 Executing: %s\n In directory:%s\n", QDir::toNativeSeparators(QCoreApplication::applicationDirPath() + "/Drivers/dummy1/install.bat").toLocal8Bit().data(), QDir::toNativeSeparators(QCoreApplication::applicationDirPath() + "/Drivers/dummy1").toLocal8Bit().data());
fflush(stdout);
execinfo.nShow = SW_SHOW;
execinfo.hInstApp = NULL;
execinfo.fMask = execinfo.fMask | SEE_MASK_NOCLOSEPROCESS;
if(ShellExecuteExA(&execinfo)){
WaitForSingleObject(execinfo.hProcess,INFINITE);
CloseHandle(execinfo.hProcess);
}else{
printf("Failed to launch dummy1 installer because...%lu\n", GetLastError());
fflush(stdout);
}
}

if(dummy2Required && !dummy2Present){
SHELLEXECUTEINFOA execinfo = {};
execinfo.cbSize = sizeof(SHELLEXECUTEINFOA);
execinfo.fMask = NULL;
execinfo.hwnd = NULL;
execinfo.lpVerb = NULL;
execinfo.lpFile = QDir::toNativeSeparators(QCoreApplication::applicationDirPath() + "/Drivers/dummy2/setup.exe").toLocal8Bit().data();
execinfo.lpParameters = "setupParamters.ini /qb /acceptlicenses y /norestart";
execinfo.lpDirectory = QDir::toNativeSeparators(QCoreApplication::applicationDirPath() + "/Drivers/dummy2").toLocal8Bit().data();
printf("Dummy2 Executing: %s\n In directory:%s\n", QDir::toNativeSeparators(QCoreApplication::applicationDirPath() + "/Drivers/dummy2/setup.exe").toLocal8Bit().data(), QDir::toNativeSeparators(QCoreApplication::applicationDirPath() + "/Drivers/dummy2").toLocal8Bit().data());
fflush(stdout);
execinfo.nShow = SW_SHOW;
execinfo.hInstApp = NULL;
execinfo.fMask = execinfo.fMask | SEE_MASK_NOCLOSEPROCESS;
if(ShellExecuteExA(&execinfo)){
WaitForSingleObject(execinfo.hProcess,INFINITE);
CloseHandle(execinfo.hProcess);
}else{
printf("Failed to launch dummy2 installer because...%lu\n", GetLastError());
fflush(stdout);
}
}

编辑:我错了。如果只运行一个可执行文件,我将观察到这种行为的频率要低得多,因此它与运行两个操作没有内在联系。

编辑 2:PaulMckenzie 指出我没有正确初始化结构,这很尴尬。不幸的是,修复它并没有改变行为。不过谢谢!

最佳答案

发布的代码中至少有两个错误。

if(dummy1Required && !dummy1Present){
SHELLEXECUTEINFOA execinfo; // <-- Uninitialized
...
}

if(dummy2Required && !dummy2Present){
SHELLEXECUTEINFOA execinfo; // <-- Uninitialized
...
}

然后你去设置SHELLEXECUTEINFOA的一些成员,但是你设置了所有的成员吗?如果您错过了一些成员怎么办?

对于许多需要使用结构的 Windows API 函数,例如 SHELLEXECUTEINFOA,应该在设置任何成员之前通过清零所有成员来初始化该结构。由于该结构是一个局部变量,因此当以这种方式声明时,它会保持未初始化状态。

不稳定行为的可能原因是此结构包含您可能不知道存在但 Win32 API 将使用的成员。如果这些成员未初始化,API 函数将使用未初始化成员持有的任何值。

初始化结构的最简单方法是简单地使用大括号初始化:

SHELLEXECUTEINFOA execInfo = {};

如果您看到 Win32 API C 编程示例,可能会遇到将 struct 清零的另一种方法是使用 ZeroMemory。 .但是对于 C++,由于 C++ 中存在 { } 初始化语法,因此不需要这样做。

关于c++ - 来自 ShellExecuteEx 的意外/不一致行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54396138/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com