Online Updates with VB.NET

Introduction

Programmers often split larger applications into smaller, manageable DLLs. Often, shortly after release one or more of the DLLs show minor problems and require bug fixes. However, it is not always easy to get the bug fixes to all the software users. Fortunately, in today’s workplace, almost everyone has some connection to the Internet. You are going to look at using this connection to deliver an update.

As difficult as it sounds, I soon found out after been tasked to write an auto updater for some of our larger applications, that it’s reasonably simple. There is simply a short list of tasks to follow, and everything needed is already included in .NET.

  1. Check for an active Internet connection.
  2. Check whether there are updates available for this application.
  3. Download the files to their respective locations.
  4. Start the updated application.

The Code

First, you need to set a few defaults and locations.


‘Project name
Public Const AppName As String = “Hex Editor”

‘ Unique Project ID —
Public Const UpdateID As String = “HexEdit”

‘ The Application’s Root Path “C:Dir1Dir2” (No trailing backslash)
Public Const AppPath As String = “C:Program FilesHex_edit”

‘ The Application’s Exe “Dir3Prog.exe” (from the root path.
‘ No leading Backslash)
Public Const AppEXE As String = “Hex_edit.EXE”

‘ Other startup defaults
‘ Last update loaded…
Public Const LastUpdate As Integer = 0
‘ Wait time to connect to Update Site in seconds
Public Const TimeOutlen As Integer = 60
‘ Default site to download updates from
Public Const UpdateSite As String = “updates.mysite.com”

Because the Auto Updater is written as a general application, and you want to be able to add it to any project without having to modify large blocks of code, anything that is specifically related to the project is stored in variables.

The above defaults relate to first time usage, and should be stored in a file or the Registry. This I will leave up to you to decide where to store the info.

Your first task is to check whether you have an open connection to the Internet. For that, you add a Standard WebBrowser object to your form. And, make it reasonably large enough to hold relevant details about the update site. By using the WebBrowser, you can automatically use the details set in Internet Explorer to connect to the Internet, and not hassle the user for details about gateways, proxies, and firewalls. The WebBrowser also has a Document Completed event that will trigger when the page has completed loading.

The website that will be hosting the updates will have two requirements:

First, the default page must always stay with the same name. You can alter the page content, but keep the name constant. Second, use a Fixed Page Title to identify the page. Once the page has completed loading, you use the Document Title to verify that you are at the right site.


Private WithEvents Timer As Windows.Forms.Timer
Private TimeDelay As Integer ‘ Timeout in seconds
Private HttpWait As Boolean ‘ Wait for Http page to load
Private Retry As Boolean ‘ Retry to load failed connection
Private TimeOut As Boolean ‘ Wait has timed out
Private Canceled As Boolean ‘ Cancel button Clicked
Private Closeme As Boolean ‘ Close the form
Private Updated As Boolean ‘ Files were updated

Private Sub WBData_DocumentCompleted(ByVal sender As System.Object, _
ByVal e As System.Windows.Forms.WebBrowserDocumentCompletedEventArgs) _
Handles WBData.DocumentCompleted
HttpWait = True
If WBData.DocumentTitle.ToUpper <> “MY UPDATE SITE” Then _
TimeOut = True
End Sub

Private Sub Timer_Tick(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles Timer.Tick
If TimeDelay = 0 Or Canceled Then
TimeOut = True
Timer.Enabled = False
Else
TimeDelay -= 1
End If

End Sub

Private Sub Cancel_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button3.Click
Canceled = True
End Sub

Private Sub StartUpdate()
Dim Updaterfile As String
Dim Serverfile As String
Dim TotalUpdates As Integer
Dim LastUpdate As Integer
Dim msgresult As MsgBoxResult

Me.Show()
LblText.Text = “Connecting to Remote Server” & vbCrLf & _
“Please ensure that your internet connection is active”
Me.Refresh()
WBData.Url = _
New System.Uri(“http://” & UpdateSite & “/Default.html”)
HttpWait = False
TimeDelay = TimeOutlen
Timer = New Windows.Forms.Timer
Timer.Interval = 1000
Timer.Enabled = True
While Not (HttpWait Or TimeOut Or Canceled)
System.Windows.Forms.Application.DoEvents()
……………..

As you can see, when the document has completed loading you check whether the document title matches your preset title. If the title does not match, you have not connected successfully to your update site. You also have a countdown timer running to make sure that you don’t wait too long for a connection. Just remember: The more complex your web page, the longer to load it. So, keep you update web page small.

You also have a cancel button on your form so that, if the user does have a slow Internet connection, or just does not want to worry about the update right now they can skip the update. From here, quickly jump to Task #4, starting the application. Why jump ahead? At this point, you may need to start the application without ever completing an update check. The update could be cancelled or timed out, so you want to start the main application.


Private Sub AutoUpdater_FormClosing(ByVal sender As Object, _
ByVal e As System.Windows.Forms.FormClosingEventArgs) _
Handles Me.FormClosing
If Not Closeme Then
e.Cancel = True
End If
End Sub

Private Sub LoadApp()
Shell(AppPath & “” & AppEXE, AppWinStyle.NormalFocus)
Closeme = True
Me.Close()
End Sub

Here, you simply use the Shell command to start the main application and exit the updater. Not much more can be said for this task. However, many may ask, “Why not do all this within my main application?” If you late bound just about everything in your application I’m sure you could; however, you still would not really be able to update the primary EXE file of the project. Using a second application to update and run the main application gives you the ability to update just about everything in a single pass and start the application without the need to stop and restart.

Now that loading the Main Application is taken care of, get back to what happens when the Connection times out, or the user clicks Cancel.


………..
If TimeOut Then
LblText.Text = “Connection to Remote Server Failed” & _
vbCrLf & “Application will continue in 10 seconds”
Button1.Enabled = True
TimeOut = False
TimeDelay = 10
Timer.Interval = 1000
Timer.Enabled = True
Retry = False
While Not (TimeOut Or Retry Or Canceled)
System.Windows.Forms.Application.DoEvents()
End While
If Retry Then
LblText.Text = “Reconnecting to Remote Server” & _
vbCrLf & ” Please ensure that your Internet connection _
is active”
Button1.Enabled = False
TimeOut = False
HttpWait = False
TimeDelay = TimeOutlen
Timer.Interval = 1000
Timer.Enabled = True
Else
LoadApp()
Exit Sub
End If
End If
End While
……………

Inside the While Wend loop, you check whether a timeout occurred. If so, you give the user an opportunity to retry; if the user decides against retrying to connect, of the retry timer runs out, you simply open the Main application and exit. By putting your retry code within the original Timeout loop, the user can have multiple retries at connecting to the server.

Now, you are at the point where you’ve successfully connected to the Internet and contacted your Update site; the user has not clicked Cancel. You want to check whether there are outstanding updates for this application. The easiest method I found to do this was simply by downloading a file, using the Unique UpdateID constant that you set earlier.


……………
If Not Canceled Then
LblText.Text = “Connection to Remote Server completed” & _
vbCrLf & ” Please wait while checking for new updates”
GBLbl.Refresh()
Updaterfile = AppPath & “UpdateLog.xml”
Serverfile = “http://” & UpdateSite & “/” & UpdateID & “.XML”
Try
If File.Exists(Updaterfile) Then File.Delete(Updaterfile)
My.Computer.Network.DownloadFile(Serverfile, Updaterfile)
…………….

More by Author

Must Read