Auto Update
You can automate updates to an existing Genero Desktop Client (GDC) installation.
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:
- 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.
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.
- On Windows platforms, you are prompted by UAC to accept to run the gdc updater binary (fjsupdater).
- It unzips the zip archive containing the update material into a temporary directory.
- 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]
- It closes the GDC process, then removes the installed GDC.
- 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.
-ry
" zip command parameter
("-y
" keeps symbolic links).Simple Auto Update Application
- 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