Auto Update

You can automate updates to an existing Genero Desktop Client (GDC) installation.

Along with the GDC installer files, a zip archive (available on the Products download page of the Four Js Web site) is provided for each operating system.
Warning: Auto Update allows the update application to perform operations on your system. Please review the security steps and recommendations listed in the Security section of this document, to ensure your network and systems are properly protected.

The auto-update application

A Genero BDL application is needed to start the update.

The application can perform tasks to ensure that update is needed. For example, this API call checks the version of the installed GDC:

ui.interface.getFrontEndVersion()

The actual update starts with a front call:

CALL ui.interface.frontcall( "monitor", "update",
  [ path-to-update-file [, warning-text [, elevation-prompt ] ] ], result)

The path-to-update-file parameter specifies the zip archive containing the update material. A pop-up warning window is displayed if applications (other than the update app) are running, which allows the user to cancel the update process. If applications are running and the user accepts the pop-up warning, the update process closes all applications, exits the monitor, and performs the update.

The second parameter (warning-text) can be used to customize the warning message displayed to the end user. The following pop-up warning message is displayed by default:


Image shows default pop-up warning message
Note: Specifying a custom warning-text does not force the pop-up dialog to display. The pop-up warning is displayed only if the user has applications running when the update front call is called.
The third parameter (elevation-prompt) is a boolean that controls how the permission elevation prompt on Windows® platforms is used:
  • If the update process does not require administration permissions, the elevation-prompt parameter is ignored.
  • If the update process requires administration permissions:
    • when the elevation-prompt parameter is true, the system shows the elevation prompt dialog.
    • when the elevation-prompt parameter is not specified or set to false, the GDC update fails.
The aim of the updater is to have a clean installation after the update, based on the content of the update material (the zip archive). All files not listed in the update material zip archive will be lost. To provide additional files, add them to the standard update material zip archive, and use this customized zip archive in your update process. If the updater detects files previously installed but modified by the user, they will be preserved.
Important: The zip archive file must be on the same host as the GDC. The easiest way to place the file on the same host is with a file transfer, such as FGL_PUTFILE.

How the update process works

The front call displays a dialog box asking the user to close all his applications. If the user cancels the dialog, nothing happens and the update attempt ends. If the user accepts the dialog, the monitor closes all remaining applications and then closes itself. It also stops the GDC from listening on the port, so that new applications cannot connect to it. An update pop-up then displays, showing the progress of the update.

Note: Aside from responding to the prompt, this does not require any action on your part.
  1. On Windows platforms, you are prompted by UAC to accept to run the gdc updater binary (fjsupdater).
  2. It unzips the zip archive containing the update material into a temporary directory.
  3. It checks the customer modified files in the current installed GDC. It then copies and renames the modified files in the same temporary directory. For example:

    $GDCDIR/etc/mymodifiedfile.xxx -> $TEMPPATCHDIR/etc/mymodifiedfile.xxx.[Year-Month-Day-Hour-Minute]

  4. It closes the GDC process, then removes the installed GDC.
  5. It moves the temporary directory (containing the new GDC) into the same path as the previous installed one.

When the update completes, the GDC is launched with same arguments as it was started previously. An informational dialog displays with the results of the update process.

If the update is unsuccessful, a dialog is displayed informing of the failure. When you click OK, the old version of the GDC is launched.

Include custom files in the archive

An archive can be modified by adding custom files to it. Added custom files are copied along with the core GDC files by the update process.

To construct an archive, use the "-ry" zip command parameter ("-y" keeps symbolic links).
Warning: Four Js does not support files added using this process. Files may be overwritten by future updates. Use at your own risk.

Simple Auto Update Application

This is a simple example. You may wish to investigate alternate (better) ways to get the information necessary for your application, such as:
  • The server-side path to the archive containing the file to update.
  • The local path where to copy the file with the FGL_PUTFILE, for example. In this example, the local path is hard-coded.
  • The version of GDC contained in the archive, in order to compare to the current GDC. The comparison could be excluded completely, if you want to force the update.
IMPORT os

MAIN
    DEFINE pathToServerSideUpdateArchive STRING
    LET pathToServerSideUpdateArchive = checkForUpdate()
    IF pathToServerSideUpdateArchive IS NULL THEN
        MENU "AutoUpdate check" ATTRIBUTES(STYLE="dialog",COMMENT="No need for an update, you are running the last version")
            ON ACTION accept
                 EXIT MENU
        END MENU
    ELSE
        MENU "AutoUpdate check" ATTRIBUTES(STYLE="dialog",COMMENT="There is a new GDC version available, would like to update your installation?")
            ON ACTION accept
                CALL doUpdate(pathToServerSideUpdateArchive)
                 EXIT MENU
            ON ACTION cancel
                 EXIT MENU
        END MENU
     END IF
END MAIN

-- checkForUpdate
-- Return the path to the update archive or NULL if there is no update required
FUNCTION checkForUpdate()
    DEFINE currentFrontEndVersion STRING
    DEFINE currentFrontEndOsType STRING
    DEFINE updateArchivePath STRING
    -- Retrieve front end information
    LET currentFrontEndVersion = ui.interface.getFrontEndVersion()
    CALL ui.Interface.frontcall("standard", "feinfo", ["ostype"], [currentFrontEndOsType])
    -- Compute the path to the update archive
    LET updateArchivePath = computeServerSideUpdateArchivePath(currentFrontEndVersion, currentFrontEndOsType)
    RETURN updateArchivePath
END FUNCTION

-- computeServerSideUpdateArchivePath
-- Compute the path to the update archive stored on your server
-- TODO this function need to be implemented accordingly to your wish
FUNCTION computeServerSideUpdateArchivePath(currentFrontEndVersion, currentFrontEndOsType)
    DEFINE currentFrontEndVersion STRING
    DEFINE currentFrontEndOsType STRING
    DEFINE updateArchivePath STRING
    -- TODO --
    RETURN updateArchivePath
END FUNCTION

-- doUpdate
-- Do the update using the provided archive
FUNCTION doUpdate(pathToServerSideUpdateArchive)
    DEFINE pathToServerSideUpdateArchive STRING
    DEFINE pathToClientSideUpdateArchive STRING
    DEFINE res STRING
    -- Compute the path to the update archive on the client and prepare the client
    LET pathToClientSideUpdateArchive = computeClientSideUpdateArchivePath()
    -- Transfer the archive on the client
    CALL FGL_PUTFILE(pathToServerSideUpdateArchive, pathToClientSideUpdateArchive)
    -- Run the update
    CALL ui.Interface.frontCall("monitor", "update", [pathToClientSideUpdateArchive], [res])
END FUNCTION

-- computeClientSideUpdateArchivePath
-- Make sure the working dir for the update is empty on the client side
-- Return the path for the archive on the client side
FUNCTION computeClientSideUpdateArchivePath()
    DEFINE osType STRING
    DEFINE workingDirPath STRING
    DEFINE ret STRING
    CALL ui.Interface.frontcall("standard", "feinfo", ["ostype"], [osType])
    IF ostype = "WINDOWS" THEN
        LET workingDirPath = "c:\\fourjs.tmp"
        CALL ui.Interface.frontCall("standard", "execute", ["cmd /C rd /S /Q " || workingDirPath, TRUE], [ret])
        CALL ui.Interface.frontCall("standard", "execute", ["cmd /C md " || workingDirPath, TRUE], [ret])
        RETURN "c:\\fourjs.tmp\\updateArchive.zip"
    ELSE
        LET workingDirPath = "/tmp/fourjs.tmp"
        CALL ui.Interface.frontCall("standard", "execute", ["rm -rf " || workingDirPath, TRUE], [ret])
        CALL ui.Interface.frontCall("standard", "execute", ["mkdir -p " || workingDirPath, TRUE], [ret])
        RETURN "/tmp/fourjs.tmp/updateArchive.zip"
    END IF
END FUNCTION