Announcement

Collapse

Forum Guidelines

This forum is for finished source code that is working properly. If you have questions about this or any other source code, please post it in one of the Discussion Forums, not here.
See more
See less

Online Update for Your Apps

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • PBWin Online Update for Your Apps

    This code was posted last week, but seems to have disappeared, so I'm putting it back online.

    The code below is a PowerBASIC remake of the code I've been using in my freeware/shareware
    apps for over 10 years. It's what I use in gbSnippets.

    It consists of 2 parts - one that goes in your app and a standalone app that you distribute with your application.
    The standalone app is call gbOnlineUpdate.exe The standalone app is NOT unique to each program. Once you've
    created it you can use it with all your apps.

    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 you 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 code for both parts is provided below, and is also available in the
    gbSnippets PowerBASIC source code library (snippet# gbs_00150 and
    gbs_00151). 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.

    This version does NOT provide status of the downloaded file. I'm working on a revision
    that includes that feature and will post it as soon as it is available. But this has worked
    so well for me that I thought I'd post it anyway.

    Finally, here's a direct link to the gbsnippets.pbr resource file use in this code:
    http://www.garybeene.com/files/gbsnippets.pbr

    Code:
    Online Update #1 - Check For Updates
    
    Allowing a user to download a new version of software is very common.
    Here's one way to do it. This approach has no security features, so it is
    best used for downloading freeware applications.
    
    Also, this approach only addresses online updating of the application EXE.
    It does not support downloading updated secondary/support files.
    
    The approach is pretty simple, but requiring only the following steps:
    1. On your server, place the latest EXE - but with an extension of
        "app.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 only the version/build
        number of the latest EXE. name it app.ver.
    
    3. In your app, place a menu item Help\CheckForUpdates which calls the
        CheckForUpdates procedure shown below
    
    4. Run "Check for Updates" - 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 function will  download the latest
        version of "app" (a file called "app.new"). CheckForUpdates also deletes,
        if they exist, the files "app.exe.old" and "app.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 another snippet in this 
        snippet library. Put the gbOnlineUpdate.exe file in the same folder
        as your application EXE.
    
        One final note: this approach uses the DownLoadURLToFile API to
        download files. The API does not provide download progress 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.  That routine verifies that a new version of itself (named xxx.new)
    is available from the server, downloads the new version, 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
    '#Bloat 1024
    #Dim All
    #Include "Win32API.inc"
    #Include "CommCtrl.inc"
    #Include "WinINET.inc"
    #Resource "gbsnippets.pbr"
    %ID_MenuHelpCheckForUpdates = 100 : %ID_DownloadTimer = 300 : %ID_Label = 400
    Global hDlg As Dword, hMenu As Dword, hMenuHelp As Dword, hWait as Long
    Global hMenuHelpCheckForUpdate As Dword
    
    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 ServerVer$, Style&, URLPath As Asciiz*%Max_Path, LocalPath As Asciiz*%Max_Path, pid???
       Local x As Long, y As Long, h As Long, w As Long, LocalVer$, app$, iResult&
    
       app$ = "app"     'the name of your application, without the EXE - use lowercase!
    
       URLPath = "http://www.garybeene.com/files/" + app$ + ".ver"    'use your own server information (mine does have app.ver for your use)
       LocalPath = Exe.Path$ + app$ + ".ver"
       LocalVer$ = "5.1"               'use a string representing a numerical value
    
       'get the .ver file from the server. if cannot get it tell user there was a problem and then exit sub
       iResult& = DeleteURLCacheEntry(URLPath)  '1 = success  clear the cache
       If URLDownloadToFile (ByVal 0, URLPath, LocalPath, 0, 0)  Then
          MsgBox "Update information not available!", %MB_Ok Or %MB_IconInformation, "Online Update"
          Exit Sub
       End If
    
       'check if server version is newer. if not, tell user and then exit sub
       Open Exe.Path$ + app$ + ".ver" For Input As #1
       Line Input #1, ServerVer$  'get version of app that is on the server
       Close #1
       If Val(ServerVer$) <= Val(LocalVer$) Then   'check to see if the server version is newer than the local version
          MsgBox "You have the latest update!"
          Exit Sub
       End If
    
       'server version is newer than local version
       'ask user for permission to proceed with download of "app.new"
       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(Exe.Path$ + app$ + ".exe.old") Then Kill Exe.Path$ + app$ + ".exe.old"  'kill .old to clear the way
       If IsFile(Exe.Path$ + app$ + ".new") Then Kill Exe.Path$ + app$ + ".new"          'kill .new to clear the way
    
       'now download the new version to same folder as the application
       URLPath = "http://www.garybeene.com/files/" + app$ + ".new"  'get the new app from the server
       LocalPath = Exe.Path$ + app$ + ".new"  'download as app.new
    
       iResult& = DeleteURLCacheEntry(URLPath)  '1 = success  clear the cache
    
       DisplayWaitDialog
       If URLDownloadToFile (ByVal 0, URLPath, LocalPath, 0, 0)  Then
          Dialog End hWait
          'download failed. tell the user then exit sub
          MsgBox "Download of updated version of App failed!", %MB_Ok Or %MB_IconInformation, "Online Update"
          Exit Sub
       Else
          Dialog End hWait
          '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
          'then close app.EXE
          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)) 
          'note: use 1 or more spaces to separate gbOnlineUpdate command line arguments
          Sleep 350   'strictly for effect - gbOnlineUpdate appears briefly on top of app
          Dialog End hDlg  'quit this application - gbOnlineUpdate is now running
       End If
    
    End Sub
    
    Sub DisplayWaitDialog()
       Local x As Long, y As Long, w As Long, h As Long, wX As Long, wY As Long
       Dialog Get Client hDlg To w,h
       wX = 150 : wY = 60
       x = (w-wX)/2    'gets left position of WaitDialog to center over app
       y = (h-wY)/2    'gets top position of WaitDialog to center over app
       Dialog New Pixels, hDlg, "", x, y, wX, wY, %WS_Popup To hWait
       Control Add Label, hWait, %ID_Label, "Please wait ... ", 0, 0, wX, wY, %SS_Center Or %SS_CenterImage Or %WS_Border
       Control Set Color hWait, %ID_Label, %Black, %White
       Dialog Show Modeless hWait
    End Sub 
    
    'gbs_00050
    Code:
    Online Update #2 - gbOnlineUpdate.exe
    
    This is code for the standalone application, which I call gbOnlineUpdate, 
    which you distribute with your app,
    
    In general, your original app downloads a new version of itself from a 
    server. It calls gbUpdate and then closes itself. gbUpdate removes the 
    old EXE and installs the new EXE, then starts the new EXE.
    
    When calling gbUpdate, your application passes command line data
    consisting of the application's name, size, and position. gbUpdate
    locates/resizes itself relative to your application.
    
    'Primary Code:
    This code confirms that the command line used to call gbUpdate has 
    valid data - a valid file called myapp.new, the original file called myapp.exe,
    and legal dialog dimensions. 
    
    Function VerifyCommandLineAndFiles(x as long, y as long, w as long, h as long) As Long 
       'get the five parameters from command line used to start gbUpdate
       AppName$ = Command$(1) : x = Val(Command$(2)) : y = Val(Command$(3)) : w = Val(Command$(4)) : h = Val(Command$(5))
       'verify that needed files .new/.exe are present, check validity of passed size/location arguments
       If IsFile(Exe.Path$ + AppName$ + ".exe") = %False Then
          MsgBox "Invalid application specified! gbUpdate closing. ", %MB_Ok + %MB_IconExclamation, AppName$ + " Online Update"
       ElseIf IsFile(Exe.Path$ + AppName$ + ".new") = %False Then
          MsgBox "Application update file missing! gbUpdate closing. ", %MB_Ok + %MB_IconExclamation, AppName$ + " Online Update"
       ElseIf x<=10 Or y<=10 Or w<=10 Or h<=10 Then
          MsgBox "Invalid application data specified! gbUpdate closing. ", %MB_Ok + %MB_IconExclamation, AppName$ + " Online Update"
       Else
          Function = 1
       End If
    End Function
    
    'This additional code is used in the gbUpdate Callback function to install/run the new app
          Case %WM_Command
             Select Case CB.Ctl
                Case %IdOk
                   'renames the old EXE as .old, then renames the downloaded file from .NEW to .EXE
                   If IsFile(Exe.Path$ + AppName$ + ".exe.old") Then Kill Exe.Path$ + AppName$ + ".exe.old"
                   Name Exe.Path$ + AppName$ + ".exe" As Exe.Path$ + AppName$ + ".exe.old"
                   Name Exe.Path$ + AppName$ + ".new" As Exe.Path$ + AppName$ + ".exe"
                   Dialog End hDlg
             End Select
          Case %WM_Destroy
             Control Get Check hDlg, %IDCheckBox To iResult
             If iResult = 1 Then  pid??? = Shell (Exe.Path$ + AppName$ + ".exe")   'runs
    
    'Compilable Example:
    #Compile Exe
    #Dim All
    #Include "Win32API.inc"
    #Resource "gbsnippets.pbr"
    
    %IDLabel = 500 : %IDCheckBox = 501 : %IDImage = 502
    Global hDlg As Dword, AppName$
    
    Function PBMain() As Long
       Local x As Long, y As Long, h As Long, w As Long
       If VerifyCommandLineAndFiles(x,y,w,h) = 0 Then Exit Function
       Dialog New Pixels, 0, AppName$ + " Online Update",x+w/2-150,y+h/2-75,300,150, %WS_OverlappedWindow To hDlg
       Dialog Set Icon hDlg, "logo"
       Control Add Image, hDlg, %IDImage, "gbupdate", 20, 10, 265, 70, %WS_Border
       Control Add Label, hDlg, %IDLabel, "Ready to install " + AppName$ + ". Continue?", 20,90,270,20, %SS_Center
       Control Add Button, hDlg, %IdOk,"Ok", 30,115,30,25
       Control Add Button, hDlg, %IdCancel,"Cancel", 70,115,50,25
       Control Add Checkbox, hDlg, %IDCheckBox,"Start on exit", 150,115,150,20
       Control Set Check hDlg, %IDCheckBox, 1   'optional (start on exit)
       Dialog Show Modal hDlg Call DlgProc
    End Function
    
    CallBack Function DlgProc() As Long
       Dim pid???, iResult As Long
       Select Case CB.Msg
          Case %WM_Command
             Select Case CB.Ctl
                Case %IdOk
                   If IsFile(Exe.Path$ + AppName$ + ".exe.old") Then Kill Exe.Path$ + AppName$ + ".exe.old"
                   Name Exe.Path$ + AppName$ + ".exe" As Exe.Path$ + AppName$ + ".exe.old"
                   Name Exe.Path$ + AppName$ + ".new" As Exe.Path$ + AppName$ + ".exe"
                   Dialog End hDlg
                Case %IdCancel
                   Dialog End hDlg
             End Select
          Case %WM_Destroy
             Control Get Check hDlg, %IDCheckBox To iResult
             If iResult = 1 Then  pid??? = Shell (Exe.Path$ + AppName$ + ".exe")
       End Select
    End Function
    
    Function VerifyCommandLineAndFiles(x as long, y as long, w as long, h as long) As Long
       'get the five parameters from command line used to start gbUpdate
        AppName$ = Command$(1) : x = Val(Command$(2)) : y = Val(Command$(3)) : w = Val(Command$(4)) : h = Val(Command$(5))
       If IsFile(Exe.Path$ + AppName$ + ".exe") = %False Then
          MsgBox "Invalid application specified! gbUpdate closing. ", %MB_Ok + %MB_IconExclamation, AppName$ + " Online Update"
       ElseIf IsFile(Exe.Path$ + AppName$ + ".new") = %False Then
          MsgBox "Application update file missing! gbUpdate closing. ", %MB_Ok + %MB_IconExclamation, AppName$ + " Online Update"
       ElseIf x<=0 Or y<=0 Or w<=0 Or h<=0 Then
          MsgBox "Invalid application data specified! gbUpdate closing. ", %MB_Ok + %MB_IconExclamation, AppName$ + " Online Update"
       Else
          Function = 1
       End If
    End Function
    
    'gbs_00051
    Last edited by Gary Beene; 5 Oct 2009, 09:37 PM.
Working...
X