Qt installer script execute



  • Hi,
    what is the correct syntax to run pnputil.exe to install inf driver in Windows in Qt installer framework script?

    I tried:

    //installscript.qs
    function Component()
    {
    }
    
    Component.prototype.createOperations = function()
    {
        component.createOperations();
    
        component.addOperation("Execute", "pnputil", "-i -a driver.inf");
    }
    

    but that ends with "execution failed: could not start proces failed to start: no such file or directory" during installation.

    I'm able to run pnputil -i -a driver.inf in my command line.



  • Hi @MartinD,

    component.addOperation("Execute", "pnputil", "-i -a driver.inf");
    

    I'm not familiar with Qt Installer Framework (hoping to start using it soon), but I first thing I'd try is:

    • add the .exe extension; and
    • separate out the arguments.

    Something like:

    component.addOperation("Execute", "pnputil.exe", "-i", "-a", "driver.inf");
    

    And if that didn't work, I'd fully-qualify both the .exe and .inf filenames too.

    Hopefully someone with more QIF experience can offer some better suggestions :)

    Cheers.



  • Hi Paul,
    unfortunately, I still have no luck in running external program. I tried e.g.:

    component.addOperation("Execute", "pnputil", "-i", "-a", "D:/usbserial.inf");
    component.addOperation("Execute", "C:/Windows/System32/pnputil.exe", "-i", "-a", "D:/usbserial.inf");
    component.addOperation("Execute", "C:/Windows/System32/PnPutil.exe");
    component.addOperation("Execute", installer.environmentVariable("SystemRoot") + "\\System32\\PnPutil.exe");
    component.addOperation("Execute", "cmd.exe"); // even cmd is not possible
    

    The last three commands produce "No program defined" error.





  • I have partial success in executing command.

    component.addOperation("Execute", "cmd", "/C", "PnPutil.exe", "-i", "-a", "@TargetDir@\\driver.inf");
    

    It produces:

    Execution failed(Unexpected exit code: 1): "cmd /C PnpUtil.exe -i -a D:\MyApp\driver.inf"
    

    However, cmd /C PnpUtil.exe -i -a D:\MyApp\driver.inf run directly in command prompt produces exit code 0. Does somebody know why the exit codes differs?

    I think I read the documentation and forum but command execution in Qt installer framework seems to be uncomprehensible to me. I don't have a clue why command execution mentioned here produces the errors, why I have to run pnputil.exe via cmd, etc.





  • @Paul-Colby Thanks. I added

    <RequiresAdminRights>true</RequiresAdminRights>
    

    to my package.xml

    and added elevated operation:

    component.addElevatedOperation("Execute", "cmd", "/C", "PnPutil.exe", "-i", "-a", "@TargetDir@\\driver.inf");
    

    Still the same - error code 1.



  • @MartinD
    Did you try full path forPnPutil.exe ?
    Also should it

    @TargetDir@\\driver.inf
    

    be

    @TargetDir@/driver.inf
    

    ?



  • @Ratzz Still exit code 1.

    I discovered that operation with nonexistent .exe

    component.addElevatedOperation("Execute", "cmd", "/C", "blabla", "-i", "-a", "@TargetDir@/dfdu.inf");
    

    still produces exit code 1 error in my installer.



  • I discoved this works:

    // launching python script in installer works
    component.addOperation("Execute", "C:/Python27/python.exe", "@TargetDir@/script.py", "workingdirectory=@TargetDir@");
    

    This doesn't work:

    // launching e.g. pnputil.exe or qmake.exe produces "no program defined" error
    component.addOperation("Execute", "C:/Windows/System32/pnputil.exe", "workingdirectory=@TargetDir@");
    component.addOperation("Execute", "C:/Qt/5.6/mingw49_32/bin/qmake.exe", "workingdirectory=@TargetDir@");
    

    Any idea why? (launching them in command line works of course)

    EDIT: I found that "No program defined" defined error is defined in qprocess.cpp:

    void QProcess::start(const QString &program, const QStringList &arguments, OpenMode mode)
    {
        Q_D(QProcess);
        if (d->processState != NotRunning) {
            qWarning("QProcess::start: Process is already running");
            return;
        }
        if (program.isEmpty()) {
            Q_D(QProcess);
            d->processError = QProcess::FailedToStart;
            setErrorString(tr("No program defined"));
            emit error(d->processError);
            return;
        }
    
        d->program = program;
        d->arguments = arguments;
    
        d->start(mode);
    }
    


  • @MartinD said:

    I discoved this works:

    // launching python script in installer works
    component.addOperation("Execute", "C:/Python27/python.exe", "@TargetDir@/script.py", "workingdirectory=@TargetDir@");
    

    This doesn't work:

    // launching e.g. pnputil.exe or qmake.exe produces "no program defined" error
    component.addOperation("Execute", "C:/Windows/System32/pnputil.exe", "workingdirectory=@TargetDir@");
    component.addOperation("Execute", "C:/Qt/5.6/mingw49_32/bin/qmake.exe", "workingdirectory=@TargetDir@");
    

    Any idea why?

    I suspect the reason is that the Python example has an argument (ignoring the workerdirectory bit) while the other two do not.

    The reason I suspect this, is that it looks (from trawling the code), that there's a bug in the Qt Installer Framework code specific to Q_OS_WIN and args.count() == 1.

    Let me explain...

    I found that "No program defined" defined error is defined in qprocess.cpp:

    That code / error indicates that QProcess::start is being called with an empty program name; ie the following check is being triggered.

    if (program.isEmpty()) {
    

    So, where is that coming from...

    Looking into the QIF's code, we see that ElevatedExecuteOperation (which seems to handle all Execute commands, not just the elevated one) uses QIF's QProcessWrapper class, which lightly wraps Qt's QProcess.

    That brings us to this bit of code, found in ElevatedExecuteOperation::Private::run:

    #ifdef Q_OS_WIN
        if (args.count() == 1) {
            process->setNativeArguments(args.front());
            qDebug() << "ElevatedExecuteOperation setNativeArguments to start:" << args.front();
            process->start(QString(), QStringList());
        } else
    #endif
        {
            process->start(args.front(), args.mid(1));
        }
    

    See that on Q_OS_WIN, if the args count is 1, then:

    1. the code uses QProcess::setNativeArguments (so, presumably, forward-to-back slash conversion is no longer in effect, etc) - this part is okay; then
    2. invokes QProcess::start with a null string!

    It's that second step which will always fail, as I read the code, since QProcess::start pays no attention to anything set via QProcess::setNativeArguments, so far as I can see, before checking the program name.

    The QProcess::setNativeArguments documentation is unclear, but numerous examples on github suggest that even when using it, the first argument to QProcess::start should still be the executable.

    So I'd:

    1. try adding another argument to your latest example (to fail the args.count() == 1 test);
    2. report this as a (potential) bug on bugreports.qt.io to see what the QIF's devs think.

    Cheers.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.