Click here to Skip to main content
Click here to Skip to main content

Application Auto Update in VB.NET

By , 19 Dec 2005
 

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 ' the program that called the auto update
        Dim RemoteUri As String ' the web location of the files
        Dim Files() As String ' the list of files to be updated
        Dim Key As String ' the key used by the program when called back 
                          ' to know that the program was launched by the 
                          ' Auto Update program
        Dim CommandLine As String ' the command line passed to the original 
                                  ' program if is the case
        Dim myWebClient As New WebClient ' the web client
        Try
            ' Get the parameters sent by the application
            Dim param() As String = Split(Microsoft.VisualBasic.Command(), "|")
            ExeFile = param(0)
            RemoteUri = param(1)
            ' the files to be updated should be separeted by "?"
            Files = Split(param(2), "?") 
            Key = param(3)
            CommandLine = param(4)
        Catch ex As Exception
            ' if the parameters wasn't right just terminate the program
            ' this will happen if the program wasn't called by the system 
            ' to be updated
            Exit Sub
        End Try
        Try
            ' Process each file 
            For i As Integer = 0 To Files.Length - 1
                Try
                    ' try to rename the current file before download the new one
                    ' this is a good procedure since the file can be in use
                    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 = "&**#@!" ' any unique sequence of characters
        ' the file with the update information
        Dim sfile As String = "update.dat" 
        ' the Assembly name 
        Dim AssemblyName As String = _
                System.Reflection.Assembly.GetEntryAssembly.GetName.Name
        ' here you need to change the web address 
        Dim RemotePath As String = _
            "http://[the web address for the update folder root]/"
        ' where are the files for a specific system
        Dim RemoteUri As String = RemotePath & AssemblyName & "/"

        ' clean up the command line getting rid of the key
        CommandLine = Replace(Microsoft.VisualBasic.Command(), Key, "")
        ' Verify if was called by the autoupdate
        If InStr(Microsoft.VisualBasic.Command(), Key) > 0 Then
            Try
                ' try to delete the AutoUpdate program, 
                ' since it is not needed anymore
                System.IO.File.Delete(_
                            Application.StartupPath & "\autoupdate.exe")
            Catch ex As Exception
            End Try
            ' return false means that no update is needed
            Return False
        Else
            ' was called by the user
            Dim ret As Boolean = False ' Default - no update needed
            Try
                Dim myWebClient As New System.Net.WebClient 'the webclient
                ' Download the update info file to the memory, 
                ' read and close the stream
                Dim file As New System.IO.StreamReader( _
                    myWebClient.OpenRead(RemoteUri & sfile))               
                Dim Contents As String = file.ReadToEnd()
                file.Close()
                ' if something was read
                If Contents <> "" Then
                    ' Break the contents 
                    Dim x() As String = Split(Contents, "|")
                    ' the first parameter is the version. if it's 
                    ' greater then the current version starts the 
                    ' update process
                    If x(0) > Application.ProductVersion Then
                        ' assembly the parameter to be passed to the auto 
                        ' update program
                        ' x(1) is the files that need to be 
                        ' updated separated by "?"
                        Dim arg As String = Application.ExecutablePath & "|" & _
                                    RemoteUri & "|" & x(1) & "|" & Key & "|" & _
                                    Microsoft.VisualBasic.Command()
                        ' Download the auto update program to the application 
                        ' path, so you always have the last version runing
                        myWebClient.DownloadFile(RemotePath & "autoupdate.exe", _
                            Application.StartupPath & "\autoupdate.exe")
                        ' Call the auto update program with all the parameters
                        System.Diagnostics.Process.Start( _
                            Application.StartupPath & "\autoupdate.exe", arg)
                        ' return true - auto update in progress
                        ret = True 
                    End If
                End If
            Catch ex As Exception
                ' if there is an error return true, 
                ' what means that the application
                ' should be closed
                ret = True 
                ' something went wrong... 
                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.

    ' The variable with the command line (to replace the 
    ' Microsoft.VisualBasic.Command() function)
    Public CommandLine As String

    Public Sub Main()
        ' if you are using class create it
        Dim MyAutoUpdate As New AutoUpdate        
        ' test if an update is needed and quit the program if so.    
        If MyAutoUpdate.AutoUpdate(CommandLine) Then Exit Sub
        ' here goes your regular code in the main 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.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Eduardo Oliveira
Web Developer
Canada Canada
Member
Eduardo Oliveira graduated in Computer Systems Analysis in Rio de Janeiro - Brazil in 1990.
He has been working as Programmer Analyst since.
In 2001 immigrated to Canada and today lives in Calgary and works with .NET and SQL server/Sybase, developing Client/Server applications and ASP.NET server controls for CMS.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralMy vote of 5memberVitorHugoGarcia8 Feb '13 - 3:47 
muito bom !
QuestionHow to create this .dat file and autoexecmemberwaqarkayani21 Jan '13 - 2:30 
Hello,
 
This looks very nice code to me for auto update applications. I have windows setup project for the application which creates only setup.exe and setup.msi for the installation. I also take some files with the installation such as style files and icon etc. Now I don't understand how to create an update for my project and where to find this update.dat file plus the autoupdate files you are talking about in the system?
 
Thanks
GeneralMy vote of 1memberhghhhhghg22 Dec '11 - 7:34 
...
GeneralMy vote of 4memberbhavik.vaishnani17 May '11 - 17:38 
hot is work's
GeneralUnable to locate application file 'Autoupdater.msi'.memberrowter17 Sep '10 - 6:43 
Hi,
 
I tried your code and i am getting this error message.
 

Unable to locate application file 'Autoupdater.msi'.
 
See the setup log file located at 'C:\Users\Test\AppData\Local\Temp\VSD36A8.tmp\install.log' for more information.
******
Where should i save the autoupdater.msi? In the remote folder or in the application startup folder? I have it in both.
But, i am still getting this error.
 

 

Here is the log file asociated with.
The following properties have been set:
Property: [AdminUser] = true {boolean}
Property: [ProcessorArchitecture] = Intel {string}
Property: [VersionNT] = 6.0.1 {version}
Running checks for package 'Windows Installer 3.1', phase BuildList
The following properties have been set for package 'Windows Installer 3.1':
Running checks for command 'WindowsInstaller3_1\WindowsInstaller-KB893803-v2-x86.exe'
Result of running operator 'VersionGreaterThanOrEqualTo' on property 'VersionMsi' and value '3.1': true
Result of checks for command 'WindowsInstaller3_1\WindowsInstaller-KB893803-v2-x86.exe' is 'Bypass'
'Windows Installer 3.1' RunCheck result: No Install Needed
Running checks for package '.NET Framework 3.5', phase BuildList
Reading value 'Install' of registry key 'HKLM\Software\Microsoft\NET Framework Setup\NDP\v3.5\1033'
Read integer value 1
Setting value '1 {int}' for property 'DotNet35InstallSuccess'
The following properties have been set for package '.NET Framework 3.5':
Property: [DotNet35InstallSuccess] = 1 {int}
Running checks for command 'DotNetFX35\dotNetFx35setup.exe'
Result of running operator 'ValueEqualTo' on property 'DotNet35InstallSuccess' and value '1': true
Result of checks for command 'DotNetFX35\dotNetFx35setup.exe' is 'Bypass'
'.NET Framework 3.5' RunCheck result: No Install Needed
Launching Application.
Error: Unable to locate application file 'Autoupdater.msi'.
 
Thanks
GeneralPerfect!memberdarksauft8 Jun '09 - 14:51 
Thank you very much! Great job on this. I've been needing a simpler way to update my application and this is perfect! It was easy to install and worked flawlessly (after changing the "exit sub" to "me.close" under your "Using the Code."
Generalautoupdate filememberngoc thuy13 May '09 - 21:14 
How to update file with winform in vb net?
 
thuy

Questionbut how do i update databasememberk550i21 Feb '09 - 4:49 
As you mention above database update are as critical as application updates so what about that
I am also facing same problem & how do you update database
GeneralGoodmemberammar7923 Jan '09 - 21:34 
Thanks for the quality code. It made my life easier with out using ClickOnce.
GeneralPretty Cool,, butmembermelvin19746 Oct '08 - 9:38 
Thats pretty slick. The ClickOnce installer kind of annoys me.
 
I did have one issue.... is after it updated it i have both forms open... should the old window close?
AnswerRe: Pretty Cool,, butmemberdarksauft8 Jun '09 - 14:47 
It's been a while since this was posted but I feel the need to address this issue.
 
Yes, but you need to change a bit of code. You'll notice an "exit sub" under his "Using the Code" section. You need to change that to "me.close" and it should work perfectly.
QuestionHow to start thismemberandyd2738 Sep '08 - 5:15 
I may be a little dense, but I just want to make sure that I'm understanding...
Is this code something that I can add directly to my current project, or do I have to create a separate second project just to do the updates for this program?
 
For some reason I'm having a hard time wrapping my brain around your article, and this is something that I really want to be able to understand and use.
AnswerRe: How to start thismemberEduardo Oliveira8 Sep '08 - 11:41 
This one you need a program to do the update. Take a look at the other article www.codeproject.com/KB/vb/Auto_Update_Revisited.aspx
GeneralRe: How to start thismemberandyd27310 Sep '08 - 4:48 
Ah, I'll just check that out then. It does look interesting.
Hm, is it saying that I have to keep track of all the files that I update each time?
Or just keep track of all the files that could be updated each time, so the program can check them?
QuestionStandard user and permissionsmemberCBFlo22 Jul '08 - 4:01 
Hi!
 
Thank you very much for this very informative article.
 
I got one question.
 
How does your updater handle standard users (Builtin\User) trying to update (Win XP SP2 / Vista)? Since a standard user can not access the program files (and underlying directories), there would be an error trying to delete the existing files, wouldn´t it?
 
Thanks for your answer in advance...
 
Flo
GeneralInternetmemberkclark5824 Mar '08 - 5:24 
Are you able to use this via the internet? I am trying to auto update handheld devices, via a wireless internet connection. I know you said it is only intended for intranet, for security reasons, but is there anything stopping it from working on the internet, and also working for a handheld device? Thanks!
AnswerRe: Internetmemberdarksauft8 Jun '09 - 14:54 
The only thing that would stop you is your host's security. All that means is you'll need to get a host with less security. Currently, there are some hosts this will work on.
Question(404) not foundmemberLolkereltje26 Dec '07 - 6:38 
Hey,
 
I get this error:

There was a problem running the Auto Update.
Please Contact us at (my contact info)
The external server has returned an error: (404) Not found

 
But I really did change the RemotePath to my file root in my website.
 
The changes I made in the files:
 
AutoUpdate.dll | Contact info
AutoUpdate.exe | Contact info
AutoUpdateTest.exe | The RemotePath (http://mywebsite.com/updates/)
update.dat | From 1.1|test.txt to 1.2|test.txt
 
I want to update the file test.txt, so my web folder looks like this:
 
+updates <--- rootfolder
- test.txt
- update.dat
+test <--- subfolder
- test.txt
- update.dat
 
Frown | :( What did I do wrong?
 
Thanks!
Generalserver requirementmemberrobin1smart11 Jul '07 - 5:45 
I am new to VB.NET. I really like this program. I have a question abt the server requirement for this program? Is IIS required to supports this program?
AnswerRe: server requirementmemberdarksauft8 Jun '09 - 14:52 
Not exactly; you can host your files on FreeWebs and this code will work.
QuestionUpdate versions sequentiallymemberprankster6245 Jul '07 - 22:19 
I need my program to upgrade through each version in order. For instance, if you have version 1.0 and the latest version is 3.0 then it will upgrade to 2.0 first. Is that possible with this code?
AnswerRe: Update versions sequentiallymemberEduardo Oliveira6 Jul '07 - 6:14 
create a different location in your webserver for each version. Then change the remoteURI variable to point to the correspondent folder.
NewsI have modify the original version to ADD the recursivity in folders (update and manifest)memberCerealkilCH5 Jul '07 - 7:07 
View my code in :
http://www.vbfrance.com/codes/APPLICATION-AUTO-UPDATE-IN-VB-NET_43355.aspx
GeneralThe request failed with HTTP status 407: Proxy Authentication RequiredmemberFernando Velazco24 Apr '07 - 7:42 
I have a error "The request failed with HTTP status 407: Proxy Authentication Required", any coments about the error ?
 
Fernando.
 
Fernando.

GeneralRe: The request failed with HTTP status 407: Proxy Authentication Requiredmembersochorii2 Aug '07 - 3:46 
Try to add after the creation of WebClient the default credentials on both projects, like this:
 
Dim myWebClient As New WebClient ' the web client
myWebClient.Proxy.Credentials = _
system.Net.CredentialCache.DefaultCredentials
 

PD: Eduardo, muito obrigado, works great!!

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130516.1 | Last Updated 19 Dec 2005
Article Copyright 2005 by Eduardo Oliveira
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid