来自ShellExecuteEx的意外/不一致行为 我创建了一个自配置的软件工具,在QualC++(2015)中使用QT来运行其他第三方安装程序。当软件发现它需要不可用的库或驱动程序时,它将使用ShellExecuteEx调用相应的安装程序以打开相应的可执行文件

来自ShellExecuteEx的意外/不一致行为 我创建了一个自配置的软件工具,在QualC++(2015)中使用QT来运行其他第三方安装程序。当软件发现它需要不可用的库或驱动程序时,它将使用ShellExecuteEx调用相应的安装程序以打开相应的可执行文件,c++,winapi,visual-c++,shellexecuteex,C++,Winapi,Visual C++,Shellexecuteex,如果只需要安装一件东西(ShellExecuteEx只运行一次),那么一切都会正常运行。如果两个东西需要同时安装,那么大约25%的时间,一次安装程序将正确运行,另一个将打开包含可执行文件的文件夹,而不是运行可执行文件。对于是否正确运行第一个或第二个操作,没有一致性 ShellExecuteEx声称在这两种情况下都正确运行(返回true)。我已经验证了每次都提供了可执行文件(和工作目录)的正确路径。我尝试在ShellExecuteEx中同时使用动词“open”和“NULL”,但没有改变行为 如果有

如果只需要安装一件东西(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
     ...
}
if(dummy1Required&!dummy1Present){

ShellExecuteInfo执行信息;//有一件事您没有做,那就是确保在使用前将结构(如
ShellExecuteInfo
)归零。您永远不应该使用未初始化的结构,设置一些成员,然后再使用它。WinAPI调用很可能使用了未设置成员的垃圾值。
ShellExecuteInfo执行信息={};
--这将自动将结构置零。如果这样做,函数是否一致工作?在C中,可以使用
={0};