As I promised, here's an update to last week's code - adding Online Update
capabilities to your apps - but this time with download status provided via a progress bar.
This time, I've only posted the part of the code that goes in your app (a single Sub).
The gbOnlineUpdate EXE that is distributed with your application is
unchanged - it works for both version of the code that is placed in your
app (the code was posted here
http://www.powerbasic.com/support/pb...ad.php?t=41612 )
This version work exactly the same as the first version - you place this Sub
in your application and distribute gbOnlineUpdate.exe with your application. Here
are a few more details (the code is heavily documented too).
To make it work, you put two files online:
- myapp.new 'the latest EXE, renamed with a .new extension.
- myapp.ver 'a single line of text with the latest version #
Then, your uses selects "Online Update" from your app. The app compares
it's version # with the one on the server (in myapp.ver). If a new version
is available, the user is allowed to download the new file (myapp.new).
The app then downloads the file. It then opens gbOnlineUpdate, passing it
information, and shuts itself down.
gbOnlineUpdate renames the old EXE as myapp.exe.old. It renames the
just-downloaded myapp.new as myapp.exe. It then (optionally) starts up
myapp.exe and shuts itself down - completing the online udpate.
The Sub for your app is provided below, and is also available in the
gbSnippets PowerBASIC source code library (snippet# gbs_00381). You
can get the entire library by downloading gbSnippets or you can view
individual snippets online.
gbSnippets home page: http://www.garybeene.com/sw/gbsnippets.htm
Online source code listings: http://www.garybeene.com/power/code/
If you've already installed gbSnippets, you can ensure that your local library
is synchronized with the latest snippets on the gbSnippets server by using
the "Actions/Synchronize with gbSnippets Server" menu.
Finally, here's a direct link to the gbsnippets.pbr resource file use in this code:
capabilities to your apps - but this time with download status provided via a progress bar.
This time, I've only posted the part of the code that goes in your app (a single Sub).
The gbOnlineUpdate EXE that is distributed with your application is
unchanged - it works for both version of the code that is placed in your
app (the code was posted here
http://www.powerbasic.com/support/pb...ad.php?t=41612 )
This version work exactly the same as the first version - you place this Sub
in your application and distribute gbOnlineUpdate.exe with your application. Here
are a few more details (the code is heavily documented too).
To make it work, you put two files online:
- myapp.new 'the latest EXE, renamed with a .new extension.
- myapp.ver 'a single line of text with the latest version #
Then, your uses selects "Online Update" from your app. The app compares
it's version # with the one on the server (in myapp.ver). If a new version
is available, the user is allowed to download the new file (myapp.new).
The app then downloads the file. It then opens gbOnlineUpdate, passing it
information, and shuts itself down.
gbOnlineUpdate renames the old EXE as myapp.exe.old. It renames the
just-downloaded myapp.new as myapp.exe. It then (optionally) starts up
myapp.exe and shuts itself down - completing the online udpate.
The Sub for your app is provided below, and is also available in the
gbSnippets PowerBASIC source code library (snippet# gbs_00381). You
can get the entire library by downloading gbSnippets or you can view
individual snippets online.
gbSnippets home page: http://www.garybeene.com/sw/gbsnippets.htm
Online source code listings: http://www.garybeene.com/power/code/
If you've already installed gbSnippets, you can ensure that your local library
is synchronized with the latest snippets on the gbSnippets server by using
the "Actions/Synchronize with gbSnippets Server" menu.
Finally, here's a direct link to the gbsnippets.pbr resource file use in this code:
Code:
'Online Update #1 - Check for Updates (w/Progress) 'Allowing a user to download a new version of software is very common. Here's one way to do it, 'based on using the TCP capabilities of PowerBASIC. This approach provides download status information. 'See the snippet http://gbl_00050 For a second approach that uses the URLDownloadToFile API. 'This approach only addresses online updating of the application EXE. As written, it does not 'include code to download secondary/support files. 'The approach is pretty simple, requiring only the following steps: '1. Place your latest EXE on your server, renamed as "yourapp.new". Using .new for an ' extension bypasses download constraints on downloading files with .EXE extensions ' and avoids downloading a file with the same name as your application. '2. On your server, place a text file which contains a single line, containing only the ' version/build number of the latest EXE. Name it "yourapp.ver". '3. In your app, place a menu item (I suggest Help\CheckForUpdates) which calls the ' CheckForUpdates procedure given below '4. Run "CheckForUpdates" - it will download "app.ver", read the content, and compare the local ' and server EXE versions. If a newer version is on the servers, and the user agrees, the Sub will ' download the latest version of "yourapp" (a file called "yourapp.new"). CheckForUpdates also deletes, if ' they exist, the files "yourapp.exe.old" and "yourapp.new", to make room for the new downloadable version. ' CheckForUpdates then starts a second application, gbOnlineUpdate, passing it the name of the application ' to be updated plus the position/size for displaying gbOnlineUpdate. 'gbOnlineUpdate source code is included in snippet http://gbl_00051. Put the gbOnlineUpdate.exe 'file in the same folder as your application EXE. 'This approach, based on the PowerBASIC TCP statements, is capable of providing download 'status information. 'Primary Code: 'To initiate an online update, a single procedure is all that must be added to your application. That 'procedure includes a local variable containing the current version/build# of the application. 'Because of length, the CheckForUpdates procedure is shown only once, in the compilable example below. 'Compilable Example: 'This code uses a menu item under HELP to call the CheckForUpdates routine. The routine verifies that 'a new version of the application is available from the server, downloads the new version file, and starts a 'second program called gbOnlineUpdate. The second program, gbOnlineUpdate, backs up the original EXE by 'renaming it as xxx.exe.old, then renames the download file as xxx.exe and optionally restarts the new program. #Compile Exe #Dim All #Include "Win32API.inc" #Include "CommCtrl.inc" #Include "WinINET.inc" %ID_MenuHelpCheckForUpdates = 100 : %ID_DownloadTimer = 300 %ID_Label = 400 : %ID_ProgressBar = 500 Global hDlg As Dword, hMenu As Dword, hMenuHelp As Dword, hWait as Long Function PBMain() As Long Dialog New Pixels, 0, "Test Code",300,300,200,200, %WS_OverlappedWindow To hDlg Control Add Label, hDlg, 500, "I am the original EXE", 20,20,140,20, %WS_Border Or %SS_Center AddMenu Dialog Show Modal hDlg Call DlgProc End Function CallBack Function DlgProc() As Long If CB.Msg = %WM_Command AND CB.Ctl = %ID_MenuHelpCheckForUpdates Then CheckForUpdates End Function Sub AddMenu Menu New Bar To hMenu Menu New Popup To hMenuHelp Menu Add Popup, hMenu, "&Help", hMenuHelp, %MF_Enabled Menu Add String, hMenuHelp, "&Check For Update", %ID_MenuHelpCheckForUpdates, %MF_Enabled Menu Attach hMenu, hDlg End Sub Sub CheckForUpdates Local app$, LocalVer$, LocalFilePath$, URLSite$, URLVerPath$, URLFilePath$, Buffer$, ServerVer$ Local ServerFileSize&, AllBytes$, x As Long, y As Long, h As Long, w As Long, Style&, pid As Dword Local LocalFilePathZ As Asciiz*%Max_Path 'local information app$ = "gbsnippets" 'the name of your application, without the EXE - use lowercase! LocalVer$ = "1.0" 'use a string representing a numerical value LocalFilePath = Exe.Path$ + app$ + ".new" 'location to put file on local PC LocalFilePathZ = LocalFilePath 'one of the API requires an AsciiZ version of the LocalFilePath 'server information URLSite$ = "www.garybeene.com" URLVerPath$ = "http://www.garybeene.com/files/" + app$ + ".ver" 'get the new app from the server URLFilePath$ = "http://www.garybeene.com/files/" + app$ + ".new" 'get the new app from the server 'clear the cache for the .new file DeleteURLCacheEntry(LocalFilePathZ) '1 = success clear the cache 'read the .ver file from the server (not save, just read content into buffer$) 'if cannot get it tell user there was a problem and then exit Sub Tcp Open "HTTP" AT URLSite$ AS #1 TIMEOUT 60000 Tcp Print #1, "GET " + URLVerPath$ + " HTTP/1.0" Tcp Print #1, "" Tcp Recv #1, 4096, ServerVer$ 'this gets the Header + Body Tcp Close #1 ServerVer$ = Remain$(ServerVer$, $crlf + $crlf) 'this returns just the body 'if ServerVer$ not newer, tell user and then exit Sub Select Case Val(ServerVer$) Case 0 MsgBox "Update information not available!", %MB_Ok Or %MB_IconInformation, "Online Update" Exit Sub Case <= Val(LocalVer$) MsgBox "You have the latest update!", %MB_Ok Or %MB_IconInformation, "Online Update" Exit Sub End Select 'server version is now verified as newer than local version 'ask user for permission to proceed with download Style& = %MB_OkCancel Or %MB_IconQuestion Or %MB_TaskModal If MsgBox ("Update available. Download and install?", Style&, "Online Update") = %IDCancel Then Exit Sub 'before downloading, remove the existing .old and .new files, if they exist If IsFile(LocalFilePath$ + ".old") Then Kill LocalFilePath$ + ".old" 'kill .old to clear the way If IsFile(LocalFilePath$) Then Kill LocalFilePath$ 'kill .new to clear the way 'Get file size to use in download display status Tcp Open "HTTP" At URLSite$ As #1 TimeOut 60000 Tcp Print #1, "HEAD " + URLFilePath$ + " HTTP/1.0" Tcp Print #1, "" : Tcp Recv #1, 4096, Buffer$ : Tcp Close #1 Buffer$ = Remain$(Buffer$, "Content-Length:") ServerFileSize& = Val(Extract$(Buffer$, $CrLf)) 'Exit Sub if filesize is zero (tell user of the problem) If ServerFileSize& = 0 Then MsgBox "Download file Not found!", %MB_Ok + %MB_IconExclamation, "Online Update" Exit Sub End If 'Display a Downloading ... PleaseWait dialog with a download status progress bar Dialog Get Client hDlg To w,h Local locX As Long, locY As Long, sizeX as Long, sizeY as Long sizeX = 170 : sizeY = 90 locX = (w-sizeX)/2 'gets left position of WaitDialog to center over app locY = (h-sizeY)/2 'gets top position of WaitDialog to center over app Dialog New Pixels, hDlg, "", locX, locY, sizeX, sizeY, %WS_Popup To hWait Control Add Label, hWait, %ID_Label, $crlf + "Downloading ... please wait !", 0, 0, sizeX, sizeY, %SS_Center Or %WS_Border Control Set Color hWait, %ID_Label, %Black, %White Control Add ProgressBar, hWait, %ID_ProgressBar,"", 10,sizeY-40,sizeX-20,20 'bottom of dialog, but on top of label Dialog Show Modeless hWait 'Download the file Tcp Open "http" AT URLSite$ AS #1 TIMEOUT 60000 'connect If Err Then Beep : Exit Sub Tcp Print #1, "GET " & URLFilePath$ & " HTTP/1.0" 'send the GET request Tcp Print #1, "" Do 'get bytes until no more available Tcp Recv #1, 4096, Buffer$ AllBytes$ = AllBytes$ + Buffer$ ProgressBar Set Pos hWait, %ID_ProgressBar, (100*Len(AllBytes$)/ServerFileSize&) Loop While IsTrue Len(Buffer$) AND IsFalse Err Tcp Close #1 'done, close the connection Dialog End hWait 'Remove the download status dialog If Len(AllBytes$) = 0 Then 'download failed. tell the user then exit sub MsgBox "Download of updated version failed!", %MB_Ok Or %MB_IconInformation, "Online Update" Exit Sub End If 'Save the file, but first take off the HTTP header from the received bytes AllBytes$ = Remain$(AllBytes$, $CrLf + $CrLf) Open LocalFilePath$ For Binary As #1 Put$ #1,AllBytes$ Close #1 'the new application was successfully downloaded, so start gbOnlineUpdate.EXE, passing app.exe 'dialog dimensions /top /left /width /height are passed so gbOnlineUpdate can be centered on currently running app.EXE 'note: use 1 or more spaces to separate gbOnlineUpdate command line arguments Dialog Get Loc hDlg To x,y : Dialog Get Size hDlg To w,h pid = Shell (Exe.Path$ + "gbOnlineUpdate.exe " + app$ + " " + Str$(x) + " " + Str$(y) + " " + Str$(w) + " " + Str$(h)) 'now close the appliciation and let gbOnlineUpdate do its work Sleep 350 'strictly for effect - gbOnlineUpdate appears briefly on top of app Dialog End hDlg 'quit this application - gbOnlineUpdate is now running End Sub 'gbs_00381