Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can Qt Installer Framework return a failure exit code?

I want to abort a Qt Installer Framework process, which can be done in multiple ways (follow the examples Qt provides for this, or throw an uncaught exception, or just inject an invalid command to cause a hard crash...). But no matter what, it seems like the exit code is 0 (i.e. "success")! Is there any way to make it 1 (or something else)?

I can think of some ugly, kludgy alternatives for programmatically evaluating the success of this process, but I really hope that's not necessary...

like image 966
BuvinJ Avatar asked Apr 10 '19 01:04

BuvinJ


People also ask

What is QT installer framework?

The Qt Installer Framework provides a set of tools and utilities to create installers once, and deploy them across all the supported desktop Qt platforms without rewriting the source code. The installers will have the native look and feel on the platform where they are run: Linux, Microsoft Windows, and macOS.

How do I download QT installer framework?

Using a prebuilt version The current prebuilt release version is available from the downloads page https://download.qt.io/official_releases/qt-installer-framework/ (GPL/LPGL license), or from your Qt Account (commercial license).


1 Answers

I found no real solution, so I did this instead...

Basically, my workaround is to throw an uncaught exception, and to write an error log file under "exit on failure" conditions. The presence of the log indicates that a problem occurred. If there is no such log, then the installation was successful. If you only care about pass/fail, just check for the file existence. Else, read the file for the details.

In my solution, I allow the client to pass an argument to the installer, specifying a specific path / name for the error log. If that is not provided, it writes to a default path on the temp directory.

Note that unless I'm wrong, I don't see a means for directly writing files, deleting them, or resolving temp paths in a straight forward manner within QtIFW scripting. So, I just use shell operations. The way I use them, I return back the path resolutions from the shell, thereby implicitly allowing the use of environmental variables in the file path.

  • Paste the following into your QtIFW QScript:

This is the full Windows specific solution:

function clearErrorLog() {
    var path = installer.value( "errlog", "%temp%\\installer.err" );
    var deleteCmd = "echo off && del \"" + path + "\" /q\necho " + path + "\n";
    var result = installer.execute( "cmd.exe", ["/k"], deleteCmd );
    if( result[1] != 0 ) 
        throw new Error("Clear error log failed.");
    try{
        var cmdOutLns = result[0].split("\n");
        path = cmdOutLns[cmdOutLns.length-2].trim();
    }
    catch(e){ path = ""; }
    if( path=="" || installer.fileExists( path ) ) 
        throw new Error("Clear error log failed. (file exists)");
    console.log("Cleared error log: " + path);
}

function writeErrorLog( msg ) {
    var path = installer.value( "errlog", "%temp%\\installer.err" );
    var writeCmd = "echo off && echo " + msg + " > \"" + path + "\"\necho " + path + "\n";
    var result = installer.execute( "cmd.exe", ["/k"], writeCmd );
    if( result[1] != 0 ) 
        throw new Error("Write error log failed.");
    try{
        var cmdOutLns = result[0].split("\n");
        path = cmdOutLns[cmdOutLns.length-2].trim();
    }
    catch(e){ path = ""; }
    if( path=="" || !installer.fileExists( path ) ) 
        throw new Error("Write error log failed. (file does not exists)");
    console.log("Wrote error log to: " + path);
}

function silentAbort( msg ) {
    writeErrorLog( msg );
    throw new Error( msg );
}

At the start of the script, clear the log.

function Controller() {
    clearErrorLog();
   ...
}
  • For macOS or Linux (most distros ought to be happy at least):

Replace the first lines in clearErrorLog() with:

var path = installer.value( "errlog", "/tmp/installer.err" );
var deleteCmd = "rm \"" + path + "\";echo " + path;
var result = installer.execute( "sh", ["-c", deleteCmd] );

And replace the first lines in writeErrorLog() with:

var path = installer.value( "errlog", "/tmp/installer.err" );
var writeCmd = "echo " + msg + " > \"" + path + "\";echo " + path;
var result = installer.execute( "sh", ["-c", writeCmd] );

If you want to check for the platform, systemInfo.kernelType will return "winnt", "linux", or "darwin" (for macOS) among other possible values.

  • When you want to invoke the mechanism, call silentAbort( msg ).

In QtIWF scripting, there is no master exception handler, or whatnot, so as long as you don't have that silentAbort function nested inside a try block, the Exception will effectively terminate the program immediately.

In order to explicitly state what path to use, launch the installer with an "errlog" key as an argument like this: myinstaller.exe errlog=mylog.err. If you don't include a full path, the current working directory will be used.

It's up to you to delete the log if you want. It's pretty common to also leave garbage in the temp directory, of course (not that I'm really a fan of that...).

like image 192
BuvinJ Avatar answered Oct 02 '22 12:10

BuvinJ