wwCodeUpdate

Copyright: West Wind Technologies, 2002
License: Free to distribute

Please note: This class is part of the West Wind Client Tools and West Wind Web Connection and made available here for free distribution. This free license applies only to the wwCodeUpdate class directly. The support classes wwHTTP, wwUtils, wwAPI etc. are included here are free to be distributed only in conjunction with the wwCodeUpdate class and the use in conjunction with it. If you use these support classes for other purposes you have to register one of the products that they are part of.

For more info, please visit the following sites:

West Wind Web Connection

West Wind Client Tools

These sites also include full documentation for the support classes.

© West Wind Technologies, 2002


Requirements

Requirements

The wwCodeupdate class is fairly self contained, but there are a couple of dependencies that you need to consider.

An Internet Connection
Obviously you need an Internet connection to check for the Web version resource and download the update file. If no connection is available the checks will simply fail quickly and not affect your application other than a short delay. Timeouts will determine how long the app waits in the worst case scenario where there is a network connection, but no Internet connection. Use nConnectTimeout to set the length of time waited before timing out.

MS Common Dialogs Active X control
MSCOMCTL.OCX is required for the progress bar dialog and should be installed with your application. Most desktop applications use these controls anyway.

Windows Scripting Host
This software should be installed on all current versions of Windows starting with Windows 98SE and later and any machine that has IE 5.0 or later installed. Generally you won't have to worry about this, but to be safe you might want to require your application to have IE 5.0 installed. You can check from within your application with whether the Scripting Host is installed by using IsComObject("Wscript.Shell"). IsComObject() is contained in wwUtils which is included in the source code. You can avoid this dependency by creating an Exe file of your own - a VFP Exe or if you don't want any dependencies a C++ or Delphi Exe.

A Zip Self-Extractor or the like
The wwCodeUpdate class assumes that you have a self-extracting ZIP file that contains the update. Specifically it relies on WinZip's Self-Extractor, but you can change the command line to fit any other self-extractor in the SwapExe() method of the wwCodeUpdateClass. You can get WinZip from www.winzip.com. The advantage of using a ZIP file is that you can store multiple files and actual directory structures inside of the file.

Last Updated: 06/26/02


Setting up the sample

Setting up the sample

This distribution contains a small sample application that consists of:

Application Files:
SampleAppMain.prg - Mainline prg
SampleApp.scx - Form where all the work happens
SampleApp.ini - Configuration file for the app

WebVirtual Directory:
Sampleapp.xml - Web Resource to update
SampleApp_Update.zip - Zip file with the higher version
SampleApp_Update.exe - The self-extracting version

Setup:
Copy the WebVirtual folder to a Web server accessible directory that allows downloading of EXE files (ie. no execute rights).

Change the VersionUrl in the INI file to point to this Web directory and the SampleApp.xml file.

Compile the SampleApp project into an EXE file which will be Version 1.0 - the version number is stored in the nVersion property of the form. Run the EXE from Explorer or the command prompt. You should see the update dialog pop up. If you have problems your URL is probably wrong in the INI file - you can step through the code by running SampleAppMain.prg and stepping through the code.

Once the application has updated it should be version 1.1. You can revert back to version 1.0 simply by recompiling the project to repeat the process.

Last Updated: 06/26/02


Class wwCodeUpdate

Class wwCodeUpdate

The wwCodeUpdate class can be used in Fat Client applications to perform application updates over the Web. The class provides the version checking tools to check against an XML version resource file, the ability to download the update and the ability to swap out the running application by executing a script file to update the running application file and any others that might have changed.

In addition to the information in this help topic tree please see:
http://www.west-wind.com/presentations/wwCodeupdate/codeupdate.asp

for a detailed article on this class and the application update process.

Based on: Relation
Stored in: wwCodeupdate.prg
Dependencies:
wwUtils.prg
wwHTTP.prg
wwDialogs.vcx
wconnect.h

Properties, Events and Methods

Name | Type | Description
CreateHTTPClient Method Creates an instance of the oHTTP member of the class.
o.CreateHTTPClient()
DownloadUpdate Method Downloads the actual update file from the Web site.
o.DownloadUpdate(llCheckforExistingVersion)
GetVersionInfo Method Retrieves the online XML resource specified in cVersionUrl and parses the content into object properties.
o.GetVersionInfo()
RunUpdateExe Method This method fires the Update Exe or script application by taking a full command line to the external app or script. Runs the app and then QUITs the current instance of Visual FoxPro.
o.RunUpdateExe(lcUpdateExe)
SwapExes Method Hot swaps an EXE file by running a Zip Exe file that unzips the update files.
o.SwapExes(lcUpdateFile)
cApplicationName | Property | Name of the application. Used for display in dialogs.
cDownloadPath Property

cErrorMsg  |    Property  | Error Message if a method failed or lError is .T.

cExeFile  |    Property  | Name of the main application Exe file.

cOnlineFileUrl  |    Property  | The URL to the update file to download. Set after a successful call to GetVersionInfo().

cUserMessage  |    Property  | User message retrieved from the XML resource file.

cVersionType  |    Property  | Type of the version to be retured in vOnlineVersion, vOnlineMinVersion and as the return value from GetVersionInfo().

cVersionUrl  |    Property  | The URL to the online XML version resource file.

cXML  |    Property  | Contains the full XML resource string after a call to GetVersionInfo().

lError  |    Property  | Error flag. Check cErrorMsg if .T.

lShowDialog  |    Property  | Determines whether the file download displays a progress dialog.

nConnectTimeout  |    Property  | The HTTP timeout before a request is considered cancelled. Applies to wait time connecting and downloading.

nFileSize  |    Property  | The filesize retrieved from the XML resource file, so you can display info about the size of the file before actually grabbing it.

oHTTP  |    Property  | Reference to an wwHTTP object that can be configured after a call to CreateHTTPClient().

vOnlineMinVersion  |    Property  | Contains the minimum version number that is allowed to update after a call to GetVersionInfo(). Value is either string or numeric depending on the cVersionType setting.

vOnlineVersion  |    Property  | Contains the version number after a call to GetVersionInfo(). Value is either string or numeric depending on the cVersionType setting.

Last Updated: 06/26/02


How wwCodeUpdate works

Related Topics
Class wwCodeUpdate
How wwCodeUpdate works

The wwCodeUpdate class provides a number of features including the ability to check a specific version resource in XML format and retrieving its content into class properties, downloading the update file to the local machine and a generic script file that can be used to swap the running application. The class helps manage this process making it very easy to plug in this functionality into any Fat client application.

Let's walk through the process.

The class provides an interface to check an online XML resource file which is in the folloging format:

<?xml version="1.0"?>
<codeupdate>
    <version>4.21</version>
    <fileurl>http://www.west-wind.com/files/updates/wwreader_update.exe</fileurl>
    <size>372</size>
   <usermessage>Version 4.21 of the West Wind Message Reader
is now available for download.</usermessage>
</codeupdate>

The class can then be used to access this XML resource and retrieve the content from it into properties of this class. Once the version info is retrieved with the GetVersionInfo() method, you can download the update from the Web site into a specified location on the local machine with the DownloadUpdate() method. You then run the RunUpdateExe() method to run an external application - an Exe or Script that you create or use our default versions - to cause the application to be swapped. RunUpdateExe() launches the swapping application and quits the current application.

The process for the client application looks like this:

* SampleAppForm :: CheckForNewVersion()
LOCAL loUpdate, loAPI, lcURL, lnVersion

lcUrl = WWREADER_VERSIONUPDATEURL  && from .H file
lnAppVersion = WWREADER_VERSION

loUpdate=CREATEOBJECT("wwCodeUpdate")

*** Url where to check for new versions (XML file)
loUpdate.cVersionUrl = lcUrl
loUpdate.cVersionType = "N"   && Numeric Type

*** Name of the application's Exe file to hotswap
loUpdate.cExeFile = "wwReader70.exe"

*** Returns the current available version from the XML file
*** Sets properties of the loUpdate object with the XML info
lnVersion = loUpdate.GetVersionInfo()

*** If no version we couldn't get the info from
*** the Web Server
IF lnVersion = 0
   *** Couldn't retrieve version info - just exit
   *** You can also display error info: loUpdate.cErrorMsg
   RETURN
ENDIF

*** Compare the version number against
*** the app's version number - here a property of the form
*** Usually you'd use a .H setting, database field or Config object
IF lnVersion > lnAppVersion
   *** Display message for the user and ask to download
   IF MessageBox(loUpdate.cUserMessage + CHR(13) + CHR(13) +;
                 "Would you like to download and install it now? (" + ;
                 LTRIM(TRANSFORM(loUpdate.nFileSize,"999,999,999")) + ;
                 "kb)",32+4,"West Wind Technologies") = 6

      IF !loUpdate.DownloadUpdate()
         MessageBox(loUpdate.cErrorMsg,48,"Download Error")
      ELSE
         *** Shutdown VFP
         CLEAR EVENTS
         RELEASE THISFORM

         *** Run the generic CodeUpdate Exe and quit application
        loUpdate.RunUpdateExe(;
                   [WSCRIPT CodeUpdate.vbs "wwReader70.exe" "] + ;
                   SYS(5) + CURDIR() +;
                   [codeupdate\wwReader_Update.exe /auto ] + ;
                   SYS(5) + CURDIR() + [" ] + ;
                   ["West Wind Message Reader"])
       ENDIF
   ENDIF
ENDIF

RETURN

This code runs the CodeUpdate.vbs Windows Scripting Host file which swaps the Exe file and then restarts it. The code to this generic script looks like this:

if WScript.Arguments.Length < 3 then
   WScript.Echo("Invalid number of parameters passed." + vbcrlf + _
                "Syntax: WSCRIPT CodeUpdate.vbs <ExeFile> <UpdateFile> <ApplicationName>")
   Wscript.Quit(1)
end if

lcExe = WScript.Arguments(0)
lcUpdateExe = WScript.Arguments(1)
lcAppName = WScript.Arguments(2)

Set oShell = Wscript.CreateObject("Wscript.Shell")

'*** Wait for 5 seconds for app to shut down
lnResult = oShell.Popup("Waiting for application to shut down...    ",5,lcAppName + "Update              ",64)

'*** Run the Update Exe
oShell.Exec(lcUpdateExe)

lnResult = oShell.Popup("Updating Exe File... ",5,lcAppName + "Update              ",64)

'*** Check that the Exe exists
Set oFile = CreateObject("Scripting.FileSystemObject")
if not oFile.FileExists(lcExe) then
    lnResult = oShell.Popup("Updating Exe File......  ",5,lcAppName + "Update              ",64)
end if

oShell.Exec(lcExe)

The script expects three parameters:

WSCRIPT CodeUpdate.vbs "SampleApp.exe"
"d:\sampleapp\codeupdate\sampleapp_update.exe /auto d:\sampleapp"
"Sample Application"

1. lcExeFile
The filename of the Exe file that runs. This is used to restart the Exe file when the update is complete. Example: SampleApp.exe (path is optional as long as it's visible from the current directory via PATH)
2. lcUpdateCommandLine
This is the full command line that is used to run the self-extracting Zip file. You should use full paths for all paths provided, which includes the name of the Exe and the update directory. The /auto flag on the Zip file is used to cause the Zip file to unzip without any user interaction.
Example: d:\sampleapp\codeupdate\SampleApp_Update.exe /auto d:\sampleapp
3. lcApplicationName
The name of the application which is used in display dialogs.

The update file that is downloaded should be a self-extracting ZIP file. I use WinZip and the WinZip self-extractor but any self extractor will work as long as it can extract into a specific directory without user intervention. When you create the Zip file you can include subdirectories as necessary. What I like to do is set up an update directory for my application and copy all the files to update into it, then run WinZip against that to create my Zip file. Check 'Include Subdirectories' and make sure not to check 'Save full path info'.

After you've created the Zip file you will need to create a self-extracting Zip file and you can use the WinZip Self-Extractor for creating a self-extracting Exe. It's very important that you set up the Exe in such a way that no prompts occur and so you should use all the default settings (simply click Next on each step of the Wizard until you see Finish). Once created the Exe can be extracted by using the /auto option to run without user interface.

See also:

Class wwCodeUpdate |
Last Updated: 06/26/02


Quick Update Checklist

Quick Update Checklist

To add auto update to your application follow these quick steps:

1. Create code similar to the code shown in How wwCodeUpdate works
to check for updates and download them.

2. Copy CodeUpdate.vbs or compile and create CodeUpdate.exe into your application
directory and ship it with your application.

3. Update your application's 'hard' version number that you compare against.
This typically will be a header file constant or a value stored in a file.

4. Create an update structure on your harddrive that makes up
all the files that need updating.

5. Create a Self-Extracting Zip Exe file of your update file(s).

6. Copy the Self-Extracting file to the Web server in the proper
Web download directory.

7. Create or update the XML Web Resource file and copy it
to the Web server server. See Listing 2 for content.

8. Test the update process preferably separately from the live version.

Last Updated: 06/26/02


wwCodeUpdate::CreateHTTPClient

Class wwCodeUpdate
wwCodeUpdate::CreateHTTPClient

Creates an instance of the oHTTP member of the class.

Use this method to create the instance and customize it before making calls that access the Web. Configure things like proxy setup, timeouts etc.

Syntax:

o.CreateHTTPClient()
Example:
loUpdate = CREATE("wwCodeUpdate")
loUpdate.CreateHTTPClient()

loHttp = loUpdate.oHttp
loHttp.nConnectTimeout = 10
loHttp.nHttpConnectType = 3
loHttp.cHttpProxyName = "proxy.west-wind.com:8080"

...

See also:

Class wwCodeUpdate |
Last Updated: 06/25/02


wwCodeUpdate::DownloadUpdate

Class wwCodeUpdate
wwCodeUpdate::DownloadUpdate

Downloads the actual update file from the Web site.

Syntax:

o.DownloadUpdate(llCheckforExistingVersion)
Return: .T. or .F.
Parameters: llCheckforExistingVersion
Optional - if .T. checks for an existing version in the download directory and if the same uses that instead of redownloading.
Remarks: Should be called after GetVersionInfo() was called.


wwCodeUpdate::GetVersionInfo

Class wwCodeUpdate
wwCodeUpdate::GetVersionInfo

Retrieves the online XML resource specified in cVersionUrl and parses the content into object properties.

Syntax:

o.GetVersionInfo()


wwCodeUpdate::RunUpdateExe

Class wwCodeUpdate
wwCodeUpdate::RunUpdateExe

This method fires the Update Exe or script application by taking a full command line to the external app or script. Runs the app and then QUITs the current instance of Visual FoxPro.

Syntax:

o.RunUpdateExe(lcUpdateExe)
Parameters: lcUpdateExe
A full command line for the EXE to run.

Example (all on one line):

CodeUpdate "SampleApp.exe"
                     "d:\sampleapp\codeupdate\sampleapp_update.exe /auto d:\sampleapp"
                     "Sample Application"
Example:
loUpdate.RunUpdateExe([WSCRIPT CodeUpdate.vbs "wwReader70.exe" "] + ;
                   SYS(5) + CURDIR() +;
                   [codeupdate\wwReader_Update.exe /auto ] + ;
                   SYS(5) + CURDIR() + [" ] + ;
                   ["West Wind Message Reader"])


wwCodeUpdate::SwapExes

Class wwCodeUpdate
wwCodeUpdate::SwapExes

Hot swaps an EXE file by running a Zip Exe file that unzips the update files.

Syntax:

o.SwapExes(lcUpdateFile)
Parameters: lcUpdateFile
The full command line to the Exe or script that performs the application swapping


wwCodeUpdate::cApplicationName

Class wwCodeUpdate
wwCodeUpdate::cApplicationName

Name of the application. Used for display in dialogs.

Values: Initial value: the application


wwCodeUpdate::cDownloadPath

Class wwCodeUpdate
wwCodeUpdate::cDownloadPath

      Values:

    Initial value: .\CodeUpdate\


wwCodeUpdate::cErrorMsg

Class wwCodeUpdate
wwCodeUpdate::cErrorMsg

Error Message if a method failed or lError is .T.


wwCodeUpdate::cExeFile

Class wwCodeUpdate
wwCodeUpdate::cExeFile

Name of the main application Exe file.

This path does not need a full path if the application and update program are all running in the same directory. Otherwise path info is required.


wwCodeUpdate::cOnlineFileUrl

Class wwCodeUpdate
wwCodeUpdate::cOnlineFileUrl

The URL to the update file to download. Set after a successful call to GetVersionInfo().


wwCodeUpdate::cUserMessage

Class wwCodeUpdate
wwCodeUpdate::cUserMessage

User message retrieved from the XML resource file.


wwCodeUpdate::cVersionType

Class wwCodeUpdate
wwCodeUpdate::cVersionType

Type of the version to be retured in vOnlineVersion, vOnlineMinVersion and as the return value from GetVersionInfo().

Values: Initial value: 'C'
'N'


wwCodeUpdate::cVersionUrl

Class wwCodeUpdate
wwCodeUpdate::cVersionUrl

The URL to the online XML version resource file.


wwCodeUpdate::cXML

Class wwCodeUpdate
wwCodeUpdate::cXML

Contains the full XML resource string after a call to GetVersionInfo().


wwCodeUpdate::lError

Class wwCodeUpdate
wwCodeUpdate::lError

Error flag. Check cErrorMsg if .T.

Values: Initial value: .F.


wwCodeUpdate::lShowDialog

Class wwCodeUpdate
wwCodeUpdate::lShowDialog

Determines whether the file download displays a progress dialog.

Values: Initial value: .T.


wwCodeUpdate::nConnectTimeout

Class wwCodeUpdate
wwCodeUpdate::nConnectTimeout

The HTTP timeout before a request is considered cancelled. Applies to wait time connecting and downloading.

Values: Initial value: 10


wwCodeUpdate::nFileSize

Class wwCodeUpdate
wwCodeUpdate::nFileSize

The filesize retrieved from the XML resource file, so you can display info about the size of the file before actually grabbing it.

Values: Initial value: 0


wwCodeUpdate::oHTTP

Class wwCodeUpdate
wwCodeUpdate::oHTTP

Reference to an wwHTTP object that can be configured after a call to CreateHTTPClient().

Values: Initial value: NULL


wwCodeUpdate::vOnlineMinVersion

Class wwCodeUpdate
wwCodeUpdate::vOnlineMinVersion

Contains the minimum version number that is allowed to update after a call to GetVersionInfo(). Value is either string or numeric depending on the cVersionType setting.

This property is not used by the class, but is useful for the calling information to determine whether an update should proceed or whether an intermediate update is required.


wwCodeUpdate::vOnlineVersion

Class wwCodeUpdate
wwCodeUpdate::vOnlineVersion

Contains the version number after a call to GetVersionInfo(). Value is either string or numeric depending on the cVersionType setting.