Introduction
This code enables an application to update itself when there is a new version available. The auto update is transparent to the user and checks for new updates every time the user launches the program. This code was written to be used in a controlled environment (intranet) and is not intended to be used through the internet due to security issues.
Background
I've been developing client/server systems for a long time, and the worst part of the software life cycle is to update it in all users' machine. The worst scenario is when you need to make a database change, and all the users are required have the latest version, otherwise the system will crash.
Today a lot of systems offer the ability to auto update, what makes the programmer's and the user's life easier. Looking through the internet, I couldn't find any code that I could use in my projects in a simple way, so I decided to write my own code.
Some points that I'd like to have in an auto update program are:
- Easy to implement and use.
- Transparent to the user.
- Ability to upgrade the system and also the auto update program.
- A code that doesn't need change when used by different systems and could be compiled in a library.
How it works
In the program that you want to be auto updateable, you just need to call the AutoUpdate
function in the Main
procedure. The AutoUpdate
function will check the version with the one read from a file located in a web site. If the program version is lower than the one read the program downloads the auto update program and launches it and the function returns True
, which means that an auto update will run and the current program should be closed. The auto update program receives several parameters from the program to be updated and performs the auto update necessary and after that launches the updated system.
The code
The auto update program
This is the code for the auto update program. The program is a windowless application with only one Main
procedure. Here the only change that needs to be made is the error message at the end:
Imports System.IO
Imports System.Net
Module Main
Public Sub Main()
Dim ExeFile As String
Dim RemoteUri As String
Dim Files() As String
Dim Key As String
Dim CommandLine As String
Dim myWebClient As New WebClient
Try
Dim param() As String = Split(Microsoft.VisualBasic.Command(), "|")
ExeFile = param(0)
RemoteUri = param(1)
Files = Split(param(2), "?")
Key = param(3)
CommandLine = param(4)
Catch ex As Exception
Exit Sub
End Try
Try
For i As Integer = 0 To Files.Length - 1
Try
File.Move(Application.StartupPath & "\" & Files(i), _
Application.StartupPath & "\" & _
Now.TimeOfDay.TotalMilliseconds & ".old")
Catch ex As Exception
End Try
' download the new version
myWebClient.DownloadFile(RemoteUri & Files(i), _
Application.StartupPath & "\" & Files(i))
Next
' Call back the system with the original command line
' with the key at the end
System.Diagnostics.Process.Start(ExeFile, CommandLine & Key)
' do some clean up - delete all .old files (if possible)
' in the current directory
' if some file stays it will be cleaned next time
Dim S As String = Dir(Application.StartupPath & "\*.old")
Do While S <> ""
Try
File.Delete(Application.StartupPath & "\" & S)
Catch ex As Exception
End Try
S = Dir()
Loop
Catch ex As Exception
' something went wrong...
MsgBox("There was a problem runing the Auto Update." & vbCr & _
"Please Contact [contact info]" & vbCr & ex.Message, _
MsgBoxStyle.Critical)
End Try
End Sub
End Module
The auto update class/function
This is the class with the AutoUpdate
function that checks if an update is needed. This can be directly copied to your code or can be in a library (DLL). If it's on your code, doesn't need to be a class.
This function receives a parameter by reference, the command line passed to the program, and can be the original command line or the one passed by the Auto Update program. If it was sent by the Auto Update program, the Key
will be cleaned from the command line, so you must use the returned parameter instead of the original command line.
Here you need to change the RemotePath
variable to point to your update web folder and the error message at the end:
Public Class AutoUpdate
Public Function AutoUpdate(ByRef CommandLine As String) As Boolean
Dim Key As String = "&**#@!"
Dim sfile As String = "update.dat"
Dim AssemblyName As String = _
System.Reflection.Assembly.GetEntryAssembly.GetName.Name
Dim RemotePath As String = _
"http://[the web address for the update folder root]/"
Dim RemoteUri As String = RemotePath & AssemblyName & "/"
CommandLine = Replace(Microsoft.VisualBasic.Command(), Key, "")
If InStr(Microsoft.VisualBasic.Command(), Key) > 0 Then
Try
System.IO.File.Delete(_
Application.StartupPath & "\autoupdate.exe")
Catch ex As Exception
End Try
Return False
Else
Dim ret As Boolean = False
Try
Dim myWebClient As New System.Net.WebClient
Dim file As New System.IO.StreamReader( _
myWebClient.OpenRead(RemoteUri & sfile))
Dim Contents As String = file.ReadToEnd()
file.Close()
If Contents <> "" Then
Dim x() As String = Split(Contents, "|")
If x(0) > Application.ProductVersion Then
Dim arg As String = Application.ExecutablePath & "|" & _
RemoteUri & "|" & x(1) & "|" & Key & "|" & _
Microsoft.VisualBasic.Command()
myWebClient.DownloadFile(RemotePath & "autoupdate.exe", _
Application.StartupPath & "\autoupdate.exe")
System.Diagnostics.Process.Start( _
Application.StartupPath & "\autoupdate.exe", arg)
ret = True
End If
End If
Catch ex As Exception
ret = True
MsgBox("There was a problem runing the Auto Update." & vbCr & _
"Please Contact [contact info]" & vbCr & ex.Message, _
MsgBoxStyle.Critical)
End Try
Return ret
End If
End Function
End Class
The auto update web folder
The auto update web folder should have a folder for each system you want to upgrade. The root folder is the one that you will refer on the RemotePath
variable. The AutoUpdate.exe program should be on this folder. Each subfolder should be named as the assembly name (normally the program name without the extension). Inside the program folder you save the files that you want to update and the file update.dat with the last file version and the files that you want to update. The first parameter is the version and the second parameter separated by a "|" are the files that you want to update, which are separated by "?" as follows:
1.2.1234.5543|MyProgram.exe?file1.txt?file2.cfg
Using the code
Well, now to use the code is very simple. In the application where you want to enable the auto update, just call the AutoUpdate
function. You must declare a variable CommandLine
that will hold the arguments passed to the program and use it, if you need, instead of the Microsoft.VisualBasic.Command()
function.
Public CommandLine As String
Public Sub Main()
Dim MyAutoUpdate As New AutoUpdate
If MyAutoUpdate.AutoUpdate(CommandLine) Then Exit Sub
End Sub
Points of interest
This auto update was written with the intention to always check for a new version, since the application involved can have problems if it runs in an old version. It guarantees that everyone who is using the application is running the latest version. This can be easily changed to update if something is available but don�t crash if it�s not.
This program works fine for small sized programs and a few files. If you need to download large files I suggest you to open a splash screen and give a message to the user that something is happening.
Limitations
- The original command line can't have the character "|", since it is used as a delimiter in the Auto Update program.
- The user must have permission to write files in the application install folder.
- The main program should use the variable
CommandLine
instead of the original command line, since it can have the key
attached to it.