AGS provides the component @autoit-gui-skeleton/ags-component-check-for-updates in order to add the feature to check for updates to an AutoIt application
How to install AGS-component-check-for-updates ?
We assume that you have already install Node.js and Yarn, for example with Chocolatey, and to install this package AGS-component-http-request, you can use the dependencies manager for AutoIt provides in AGS. So just type in the root folder of your project where the package.json
is stored:
yarn add @autoit-gui-skeleton/ags-component-check-for-updates --modules-folder vendor
All project dependencies, as well as daughter dependencies of parent dependencies, are installed in the ./vendor/@autoit-gui-skeleton/
directory.
All AGS packages hosted in this npmjs repository belong to the organization @autoit-gui-skeleton organization. Indeed in order to simplify the management of the dependencies of an AutoIt project built with AGS framework, we have diverted form its initial use the dependency manager npm, and its evolution Yarn. This allows us to manage the dependencies of an AGS project with other AutoIt libraries, and to share these AutoIt packages from the npmjs.org repository.
How to use AGS-component-check-for-updates ?
Description
With AGS-component-check-for-updates, you can create an AutoIt application with a feature to check its own updates. It then provides a link to download the latest version of the installer, and another link to the release notes.
To work, it compares the local version of the application installed on the user’s PC with the repository of the published versions of the application. This repository is a json file, RELEASES.json
, which is therefore hosted on a remote server. So we need to connect to the Internet to send an HTTP request to retrieve this file, and we need a JSON parse. This component therefore depends on other AGS components: ags-wrapper-json and ags-component-http-request. If you want to simulate different scenarios ofcheck for updates, you just need to change the value of the application version set in ./src/GLOBALS.au3
.
The remote file RELEASES.json
looks like this:
{
"name": "ApplicationWithCheckForUpdates",
"description": "Example to implementation of AGS-component-check-for-updates",
"license": "MIT",
"homepage": "https://autoit-gui-skeleton.github.io",
"releases": [
{
"version": "1.0.0",
"state": "stable",
"downloadSetup": "https://myApplication.com/v1.0.0/setup_myApplication_v1.0.0.exe",
"published": "2018-10-07",
"releaseNotes": "https://myApplication.com/v1.0.0/README.md"
},
{
"version": "0.1.0",
"state": "prototype",
"downloadSetup": "undefined",
"published": "2014-03-21",
"releaseNotes": "undefined"
}
]
}
Example of an application that implements AGS-component-check-for-updates
Take a look of this example ApplicationWithCheckForUpdates. This application has interesting features:
- Check update on startup AutoIt application ;
- Check update from the menu “? > Check for update” ;
- Change settings application from the view “Configuration > Settings”. Values are persisted into the configuration file ./config/parameters.ini. In this view, we can set proxy parameters to specify how this application try to connect to internet.
If the option for checking the update of the application at each start is enabled, and if a new version of this application is available, then when the user starts the application, he gives this information in a window child.
Available methods
This library provides few methods:
Methods | Description |
---|---|
json_decode_from_file($filePath) |
Decode JSON from a given local file. |
json_decode_from_url($jsonfileUrl, $proxy = "") |
Decode JSON from a given URL. |
RELEASES_JSON_get_all_versions($jsonObject) |
Parse all defined version(s) persisted in a decoded RELEASES.json file given. |
RELEASES_JSON_get_last_version($jsonObject) |
Get last version persisted in RELEASES.json |
CheckForUpdates($currentApplicationVersion, $remoteUrlReleasesJson, $proxy = "") |
Compare the current version with the last version persisted in an remote RELEASES.json file, in order to check if an update is available. |
_GUI_launch_CheckForUpdates($main_GUI, $context) |
Launch a check for updates. The build of a GUI exposing the results depends on the context when the check for update is launch : with an user interaction from menu or on startup application. We store the option to search update on starup in the configuration file ./config/parameters.ini in parameter LAUNCH_CHECK_FOR_UPDATE_ON_STARTUP . |
_GUI_build_view_to_CheckForUpdates($main_GUI, $resultCheckForUpdate, $context = "") |
Create a child GUI use to expose the result of a check updater. It exposes if an update of current application is available. The child GUI is related to a given main GUI of application. If this method is execute on startup, we built this child GUI only if an update is available. And when this method is called by a user interaction, we built this child GUI in any case : no update available, new update or experimental. |
Configure the component AGS-component-check-for-updates
Create configuration file ./config/parameters.ini
With AGS, you must have the configuration file ./config/parameters.ini
. This file must not save with control version. You can use ./config/parameters.ini.dist
as a “template” of what your parameters.ini file should look like. Set parameters here that may be different on each application. Only this file is save with control version and push on remote server.
To configure the behavior of this component, you can set its options in this configuration file. You can enable or disable the search of a new update when the application starts, with the LAUNCH_CHECK_FOR_UPDATE_ON_STARTUP
variable of the section AGS_CHECK_FOR_UPDATES
.
[AGS_CHECK_FOR_UPDATES]
; [REQUIRED] Enable/disable the search of a new update on start-up.
LAUNCH_CHECK_FOR_UPDATE_ON_STARTUP=1
In this component we use an another component AGS-component-http-request. This library is used to send HTTP request in GET or POST method, and with or wihtout behind a corporate proxy, in order to get the remote RELEASES.json
. So you can also configure this component. For example, you can set a proxy for all HTTP connections, or set different types of timeouts. By default, this component looks in the configuration file if a proxy is defined in the PROXY
variable in the AGS_HTTP_REQUEST
section.
[AGS_HTTP_REQUEST]
; [OPTIONAL] Use a proxy for http connexion or choose NONE to disable it
# PROXY=NONE
PROXY=http://myProxy.com:20100
Set constants in ./src/GLOBALS.au3
All constants and global variables are set in one place ./src/GLOBALS.au3
, with the exception to global variables of graphic elements which are set in each specific view file. AGS-component-check-for-udpates use the constant $APP_REMOTE_RELEASES_JSON
to specifiy where the repository RELEASES.json
is hosted.
This json file must be persisted in a remote server available via internet, and without restriction. For example, you can use Github to host this file, like this:
Global Const $APP_REMOTE_RELEASES_JSON = "https://raw.githubusercontent.com/autoit-gui-skeleton/AGS-component-check-for-updates/master/example/ApplicationWithCheckForUpdates/RELEASES.json"
How to perform a check-for-updates on startup ?
In the _main_GUI()
method of the main manager of graphic user interface ./src/GUI.au3
, it just add a call to the method _GUI_launch_CheckForUpdates
like this.
;; ./src/GUI.au3 ;;
Func _main_GUI()
Global $main_GUI = GUICreate($APP_NAME, $APP_WIDTH, $APP_HEIGHT, -1, -1)
_GUI_Init_Menu()
_GUI_Init_Footer()
_GUI_Init_View_Welcome()
_GUI_Init_View_About()
_GUI_Init_View_Settings()
; Set configuration application : icon, background color
_GUI_Configuration()
; Show Welcome view on startup
_GUI_ShowHide_View_Welcome($GUI_SHOW)
GUISetState(@SW_SHOW)
; Launch a check for updates on startup, the check is performed
; only if LAUNCH_CHECK_FOR_UPDATE_ON_STARTUP is enable in
; the configuration file './config/parameters.ini'
_GUI_launch_CheckForUpdates($main_GUI, "ON_STARTUP")
; Handle all user interactions and events
_GUI_HandleEvents()
GUIDelete()
Exit
EndFunc
How to perform a check-for-updates from an item menu ?
Into the GUI_Init_Menu
method, we add a new menu item for check-for-udpates.
;; ./src/GUI.au3 ;;
Func _GUI_Init_Menu()
(...)
; Création 'About' menu
Global $menu_About = GUICtrlCreateMenu("?")
Global $menuitem_Help = GUICtrlCreateMenuItem("Help", $menu_About)
Global $menuitem_CheckForUpdate = GUICtrlCreateMenuItem("Check for update", $menu_About)
EndFunc
And we handle events clicks on menu about like this:
;; ./src/GUI.au3 ;;
Func _GUI_HandleEvents_Menu_About($msg)
Switch $msg
Case $menuitem_Help
ConsoleWrite('Click on "? > Help"' & @CRLF)
Case $menuitem_CheckForUpdate
_GUI_launch_CheckForUpdates($main_GUI, "ON_MENU")
EndFunc
user can change the settings directly in the application
You can create a view into application in order to change settings. All values are persisted into the configuration file ./config/parameters.ini
. In this view, we can set proxy parameters to specify how this application try to connect to internet and if the application searchs an update on startup.
When the user click on save button, it uses the service ./src/services/ParametersIni.au3
, which call IniWrite
method on configuration file ./config/parameters.ini
to persist values.
;====================================================================================
; Save values choose by user in 'Setting' views, and launch with 'save' button
;
; @params void
; @return void
;====================================================================================
Func _save_parameters_ini()
; Save proxy settings
IniWrite($APP_PARAMETERS_INI, "AGS_HTTP_REQUEST", "PROXY", GUICtrlRead($input_HTTP_Proxy))
IniWrite($APP_PARAMETERS_INI, "AGS_HTTP_REQUEST", "RESOLVE_TIMEOUT", GUICtrlRead($input_HTTP_Resolve_Timeout))
IniWrite($APP_PARAMETERS_INI, "AGS_HTTP_REQUEST", "CONNECT_TIMEOUT", GUICtrlRead($input_HTTP_Connect_Timeout))
IniWrite($APP_PARAMETERS_INI, "AGS_HTTP_REQUEST", "SEND_TIMEOUT", GUICtrlRead($input_HTTP_Send_Timeout))
IniWrite($APP_PARAMETERS_INI, "AGS_HTTP_REQUEST", "RECEIVE_TIMEOUT", GUICtrlRead($input_HTTP_Receive_Timeout))
; Startup settings
If (GUICtrlRead($checkbox_STARTUP_CHECK_UPDATE) = $GUI_CHECKED) Then
IniWrite($APP_PARAMETERS_INI, "AGS_CHECK_FOR_UPDATES", "LAUNCH_CHECK_FOR_UPDATE_ON_STARTUP", "1")
Else
IniWrite($APP_PARAMETERS_INI, "AGS_CHECK_FOR_UPDATES", "LAUNCH_CHECK_FOR_UPDATE_ON_STARTUP", "0")
EndIf
EndFunc
And the source code of the manager of the “Settings” view.
;; ./src/views/View_Settings.au3 ;;
#include-once
;====================================================================================
; Create element for the 'Settings' view
;
; @param void
; @return void
;====================================================================================
Func _GUI_Init_View_Settings()
GUISetFont(20, 800, 0, "Arial Narrow")
Global $label_title_settings = GUICtrlCreateLabel("Settings", 20, 30, 400)
GUICtrlSetColor($label_title_settings, 0x85C4ED)
GUICtrlSetBkColor($label_title_settings, $GUI_BKCOLOR_TRANSPARENT)
Local $height = 120
Local $heightStep = 30
Local $margin_top = 50
; Proxy settings
GUISetFont(9, 800, 0, "Arial")
Local $height_group_proxy_settings = (5 * $heightStep) + 30
Global $group_proxy_settings = GUICtrlCreateGroup(" Proxy ", 30, $height - 30, ($APP_WIDTH - 60), $height_group_proxy_settings)
GUISetFont(9, 400, 0, "Arial")
Local $PROXY = IniRead($APP_PARAMETERS_INI, "AGS_HTTP_REQUEST", "PROXY", "")
Local $RESOLVE_TIMEOUT = Int(IniRead($APP_PARAMETERS_INI, "AGS_HTTP_REQUEST", "RESOLVE_TIMEOUT", 0))
Local $CONNECT_TIMEOUT = Int(IniRead($APP_PARAMETERS_INI, "AGS_HTTP_REQUEST", "CONNECT_TIMEOUT", 60000))
Local $SEND_TIMEOUT = Int(IniRead($APP_PARAMETERS_INI, "AGS_HTTP_REQUEST", "SEND_TIMEOUT", 30000))
Local $RECEIVE_TIMEOUT = Int(IniRead($APP_PARAMETERS_INI, "AGS_HTTP_REQUEST", "RECEIVE_TIMEOUT", 30000))
Global $label_HTTP_Proxy = GUICtrlCreateLabel("HTTP / HTTPS Proxy", 50, $height)
Global $input_HTTP_Proxy = GUICtrlCreateInput($PROXY, 200, $height - 2, 400, 20)
Global $label_HTTP_Resolve_Timeout = GUICtrlCreateLabel("Timeout for HTTP resolve", 50, $height + $heightStep)
Global $input_HTTP_Resolve_Timeout = GUICtrlCreateInput($RESOLVE_TIMEOUT, 200, $height + $heightStep - 2, 100, 20)
Global $label_HTTP_Connect_Timeout = GUICtrlCreateLabel("Timeout for HTTP connect", 50, $height + 2 * $heightStep)
Global $input_HTTP_Connect_Timeout = GUICtrlCreateInput($CONNECT_TIMEOUT, 200, $height + 2 * $heightStep - 2, 100, 20)
Global $label_HTTP_Send_Timeout = GUICtrlCreateLabel("Timeout for HTTP send", 50, $height + 3 * $heightStep)
Global $input_HTTP_Send_Timeout = GUICtrlCreateInput($SEND_TIMEOUT, 200, $height + 3 * $heightStep - 2, 100, 20)
Global $label_HTTP_Receive_Timeout = GUICtrlCreateLabel("Timeout for HTTP receive", 50, $height + 4 * $heightStep)
Global $input_HTTP_Receive_Timeout = GUICtrlCreateInput($RECEIVE_TIMEOUT, 200, $height + 4 * $heightStep - 2, 100, 20)
GUICtrlCreateGroup("", -1, -1, 1, 1)
; Startup settings
$height = $height + $height_group_proxy_settings
GUISetFont(9, 800, 0, "Arial")
Global $group_startup_settings = GUICtrlCreateGroup(" Start-up ", 30, $height, ($APP_WIDTH - 60), (1 * $heightStep) + 30)
GUISetFont(9, 400, 0, "Arial")
Global $checkbox_STARTUP_CHECK_UPDATE = GUICtrlCreateCheckbox( _
"Search update on application startup ?", _
50, $height + $heightStep, Default, 20, $BS_RIGHTBUTTON _
)
Local $LAUNCH_CHECK_FOR_UPDATE_ON_STARTUP = Int(IniRead($APP_PARAMETERS_INI, "AGS_CHECK_FOR_UPDATES", "LAUNCH_CHECK_FOR_UPDATE_ON_STARTUP", "NotFound"))
If ($LAUNCH_CHECK_FOR_UPDATE_ON_STARTUP = 1) Then
GUICtrlSetState($checkbox_STARTUP_CHECK_UPDATE, $GUI_CHECKED)
Else
GUICtrlSetState($checkbox_STARTUP_CHECK_UPDATE, $GUI_UNCHECKED)
EndIf
GUICtrlCreateGroup("", -1, -1, 1, 1)
Global $button_save_settings = GUICtrlCreateButton("Save", ($APP_WIDTH - 150) / 2, $APP_HEIGHT - 100, 150)
; Setter of tips and cursors
_GUI_SetCursorAndTip_View_Settings()
; Hide all elements by default
_GUI_ShowHide_View_Settings($GUI_HIDE)
EndFunc
;====================================================================================
; Setter tips and cursor for elements in 'Settings' view
;
; @param void
; @return void
;====================================================================================
Func _GUI_SetCursorAndTip_View_Settings()
GUICtrlSetCursor($label_HTTP_Proxy, 4)
GUICtrlSetTip($label_HTTP_Proxy, @CRLF & "Configuration of proxy to allow internet connection" & @CRLF & @CRLF & "Example : http(s):\\myProxy.com:8080", "HTTP/HTTPS Proxy", 1)
GUICtrlSetCursor($checkbox_STARTUP_CHECK_UPDATE, 4)
GUICtrlSetTip($checkbox_STARTUP_CHECK_UPDATE, @CRLF & "To allow the search of an update of the application at each start." & @CRLF & "This search requires an internet connection, and therefore" & @CRLF & "potenially need a configuration of a proxy.", "Check for update on start-up", 1)
GUICtrlSetCursor($button_save_settings, 0)
EndFunc
;====================================================================================
; Handler for display element on 'Settings' view
;
; @param {int} $action, use GUIConstantsEx $GUI_SHOW or $GUI_HIDE
; @return void
;====================================================================================
Func _GUI_ShowHide_View_Settings($action)
Switch $action
Case $GUI_SHOW
_GUI_Hide_all_view()
; Define here all elements to show when user come into this view
GUICtrlSetState($label_title_settings, $GUI_SHOW)
GUICtrlSetState($group_proxy_settings, $GUI_SHOW)
GUICtrlSetState($label_HTTP_Proxy, $GUI_SHOW)
GUICtrlSetState($input_HTTP_Proxy, $GUI_SHOW)
GUICtrlSetState($label_HTTP_Resolve_Timeout, $GUI_SHOW)
GUICtrlSetState($input_HTTP_Resolve_Timeout, $GUI_SHOW)
GUICtrlSetState($label_HTTP_Connect_Timeout, $GUI_SHOW)
GUICtrlSetState($input_HTTP_Connect_Timeout, $GUI_SHOW)
GUICtrlSetState($label_HTTP_Send_Timeout, $GUI_SHOW)
GUICtrlSetState($input_HTTP_Send_Timeout, $GUI_SHOW)
GUICtrlSetState($label_HTTP_Receive_Timeout, $GUI_SHOW)
GUICtrlSetState($input_HTTP_Receive_Timeout, $GUI_SHOW)
GUICtrlSetState($group_startup_settings, $GUI_SHOW)
GUICtrlSetState($checkbox_STARTUP_CHECK_UPDATE, $GUI_SHOW)
GUICtrlSetState($button_save_settings, $GUI_SHOW)
Case $GUI_HIDE
; Define here all elements to hide when user leave this view
GUICtrlSetState($label_title_settings, $GUI_HIDE)
GUICtrlSetState($group_proxy_settings, $GUI_HIDE)
GUICtrlSetState($label_HTTP_Proxy, $GUI_HIDE)
GUICtrlSetState($input_HTTP_Proxy, $GUI_HIDE)
GUICtrlSetState($label_HTTP_Resolve_Timeout, $GUI_HIDE)
GUICtrlSetState($input_HTTP_Resolve_Timeout, $GUI_HIDE)
GUICtrlSetState($label_HTTP_Connect_Timeout, $GUI_HIDE)
GUICtrlSetState($input_HTTP_Connect_Timeout, $GUI_HIDE)
GUICtrlSetState($label_HTTP_Send_Timeout, $GUI_HIDE)
GUICtrlSetState($input_HTTP_Send_Timeout, $GUI_HIDE)
GUICtrlSetState($label_HTTP_Receive_Timeout, $GUI_HIDE)
GUICtrlSetState($input_HTTP_Receive_Timeout, $GUI_HIDE)
GUICtrlSetState($group_startup_settings, $GUI_HIDE)
GUICtrlSetState($checkbox_STARTUP_CHECK_UPDATE, $GUI_HIDE)
GUICtrlSetState($button_save_settings, $GUI_HIDE)
EndSwitch
EndFunc
;====================================================================================
; Handler for events in 'Settings' view
;
; @param $msg, event return with GUIGetMsg method, i.e. the control ID of the control sending the message
; @return @void
;====================================================================================
Func _GUI_HandleEvents_View_Settings($msg)
Switch $msg
Case $button_save_settings
ConsoleWrite('Click on "$button_save_settings"' & @CRLF)
_save_parameters_ini()
EndSwitch
EndFunc
How to test differents case with the check-for-updates
In this example of remote RELEASES.json, we set two releases like this:
{
"name": "ApplicationWithCheckForUpdates",
"description": "Example to implementation of AGS-component-check-for-updates",
"license": "MIT",
"homepage": "https://autoit-gui-skeleton.github.io",
"releases": [
{
"version": "1.0.0",
"state": "stable",
"downloadSetup": "https://myApplication.com/v1.0.0/setup_myApplication_v1.0.0.exe",
"published": "2018-10-07",
"releaseNotes": "https://myApplication.com/v1.0.0/README.md"
},
{
"version": "0.9.0",
"state": "prototype",
"downloadSetup": "undefined",
"published": "2014-03-21",
"releaseNotes": "undefined"
}
]
}
If you want to simulate different scenarios on check updater, you just need to change the value of the application version set in ./src/GLOBALS.au3
. For example to simulate the case of:
-
new version available set it to :
Global Const $APP_VERSION = "0.9.0"
-
application have not update available :
Global Const $APP_VERSION = "1.0.0"
-
application is experimental:
Global Const $APP_VERSION = "1.1.0"
Continue reading ?