Question How do I make an update feature?

techwiz24

Well-known member
Joined
Jun 2, 2010
Messages
51
Programming Experience
Beginner
I am trying to inpliment an update feature where the program pulls the information from the <version></version> tag in an xml document on the users machine AND on my server, and then prints the values in two labels, and then compares them. If they match, then the update button remains disabled, and a label saying "No update is needed" is also shown. If they don't match, then the label with the no update msg is hidden and the update button is enabled. Once the button is clicked, the program downloads setup.exe form my server and runs it.

I don't know where to start :confused:
 
Here's how I would handle that. For every new version of the program I would create a new full installer (for the website/new users to download and install) and I would keep a version.xml file on the webserver that contains the version history as well as an installer for each version increment (the changed files). Then the app itself would download that version xml file, check it's version against what's in the file, then download the appropriate increment installer, run it, and close itself only if it's an old version.

If your app is small enough, then keeping the idea above in mind, create just the 1 full installer (no incremental installers) and the version xml file, check itself against the file and download the newest full installer, run it and close itself if it's an older version.

There's tons of code examples via a google search for downloading files and parsing xml.
 
Still not working...I can get the localVS to work fine. It appears to not be able to read the xml file on the server. Right now, the xml file on the server is an exact mirror copy of the local version with a different name

VB.NET:
Imports System.Xml
Imports System.IO
Imports System.Net
Imports System.Text
Public Class updateFRM

    Private Sub updateFRM_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Dim xmldoc As New XmlDataDocument()
        Dim xmlnode As XmlNodeList
        Dim i As Integer
        Dim str As String
        Dim fs As New FileStream("C:\Users\******\Documents\Visual Studio 2010\Projects\***** ****\***** ****\localversion.xml", FileMode.Open, FileAccess.Read)
        xmldoc.Load(fs)
        xmlnode = xmldoc.GetElementsByTagName("version")
        For i = 0 To xmlnode.Count - 1
            xmlnode(i).ChildNodes.Item(0).InnerText.Trim()
            str = xmlnode(i).ChildNodes.Item(0).InnerText.Trim()
            localVS.Text = str
        Next
        status.Text = "fetching server version"
        serverchk()
        status.Text = "waiting"
    End Sub

    Sub serverchk()
        Dim xmldoc As New XmlDataDocument()
        Dim xmlnode As XmlNodeList
        Dim i As Integer
        Dim str As String
        Dim fs As New FileStream("http://www.game-droid.co.cc/program/bin/serverVS.xml", FileMode.Open, FileAccess.Read)
        xmldoc.Load(fs)
        xmlnode = xmldoc.GetElementsByTagName("version")
        For i = 0 To xmlnode.Count - 1
            xmlnode(i).ChildNodes.Item(0).InnerText.Trim()
            str = xmlnode(i).ChildNodes.Item(0).InnerText.Trim()
            serverVS.Text = str
        Next
    End Sub
 
VB.NET:
xmldoc.Load("c:\...xml")
' and
xmldoc.Load("http://...xml")
this is probably simpler lookup that matches:
VB.NET:
serverVS / localVS .Text = xmldoc.SelectSingleNode("//version").InnerText
 
Thank you! I can successfully compare versions now. But the update is a little iffy. When the version doesn't match, the update now button is enabled. When clicked:
VB.NET:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        updateYN.Text = "Downloading updates"
        Button2.Enabled = False
        Dim request As WebRequest
        Dim response As WebResponse
        Dim reader As Stream
        Dim writer As Stream
        Dim data(1023) As Byte
        Dim count As Integer
        Dim total As Integer
        Application.DoEvents()
            request = WebRequest.Create("http://www.game-droid.co.cc/bin/setupGD.exe")
            response = request.GetResponse()
            reader = response.GetResponseStream()
            ProgressBar1.Maximum = CInt(response.ContentLength)
            ProgressBar1.Value = 0
            total = 0
            writer = File.Create(Application.StartupPath + "\Bin\temp\setupGD.exe")
            While True
                count = reader.Read(data, 0, 1024)
                If count <= 0 Then
                    Exit While
                End If
                writer.Write(data, 0, count)
                total += 1024
                If total < ProgressBar1.Maximum Then ProgressBar1.Value = total
                Application.DoEvents()
            End While
            reader.Close()
            writer.Close()
            Button2.Enabled = True
            updateYN.Text = "Update Downloaded"
            Dim result As MsgBoxResult
            MsgBox("Update downloaded, patch GameDroid Now?", MsgBoxStyle.YesNo, "Update now?")
            If result = MsgBoxResult.Yes Then
                System.Diagnostics.Process.Start(Application.StartupPath + "\Bin\temp\setupGD.exe")
                Me.Close()
                Form1.Close()
                subcat_selector.Close()
                OptionsForm.Close()
            ElseIf result = MsgBoxResult.No Then
                Me.Close()
            End If
    End Sub

But this:
VB.NET:
 ProgressBar1.Maximum = CInt(response.ContentLength)
throws an error that says: "Value of '-1' is not valid for 'Maximum'. 'Maximum' must be greater than or equal to 0."

anything I can do to change this? This is the last thing I need to do for the updater I think

EDIT
Interesting, it might be a problem on my server, I can't manually enter the url and download the file, but I can see it in FTP...Looking into this....
_________________________________________________________________
There appears to be file problems. I changed permissions on the file and temporary directory to 777 or read/write/exicute...but still having problems. I'll try with a file I know works
 
Last edited:
ok, i'm back...here's what happened. I moved servers, and same thing. I am going to stay on this server, just rename the update. but the xml file won't work now. Here's the whole code for the update.vb (code only, not designer)
VB.NET:
Imports System.Xml
Imports System.IO
Imports System.Net
Imports System.Text
Public Class updateFRM
    Private Sub updateFRM_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        localVS.Text = "0.7.1"
        status.Text = "re-buffering feed"
        status.Text = "fetching server version"
        serverchk()
        status.Text = "comparing"
        version_comp()
    End Sub
    Sub serverchk()
        Dim xmldoc As New XmlDataDocument()
        Dim xmlnode As XmlNodeList
        Dim i As Integer
        Dim str As String
        Dim fs As String
        fs = "http://game-droid.co.cc/program/bin/serverVS.xml"
        xmldoc.Load(fs)
        xmlnode = xmldoc.GetElementsByTagName("version")
        For i = 0 To xmlnode.Count - 1
            xmlnode(i).ChildNodes.Item(0).InnerText.Trim()
            str = xmlnode(i).ChildNodes.Item(0).InnerText.Trim()
            serverVS.Text = str
        Next

    End Sub
    Sub version_comp()
        If localVS.Text = serverVS.Text = False Then
            Button1.Enabled = True
            updateYN.Text = "Update required. Click Update Now to update"
        ElseIf localVS.Text = serverVS.Text = True Then
            Button1.Enabled = False
            updateYN.Text = "No updates. Please click Cancel"
        End If
    End Sub
    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        Me.Close()
    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        updateYN.Text = "Downloading updates"
        Button2.Enabled = False
        updateYN.Text = "Checking temporary directory"
        If System.IO.Directory.Exists(Application.StartupPath + "\Bin\temp\") Then
            updateYN.Text = "directory exists"
        ElseIf System.IO.Directory.Exists(Application.StartupPath + "\Bin\temp\") = False Then
            updateYN.Text = "directory doesn't exist, creating"
            System.IO.Directory.CreateDirectory(Application.StartupPath + "\Bin\temp\")
            updateYN.Text = "directory created"
        End If
        status.Text = "Begining Download"
        Dim request As WebRequest
        Dim response As WebResponse
        Dim reader As Stream
        Dim writer As Stream
        Dim data(1023) As Byte
        Dim count As Integer
        Dim total As Integer
        Application.DoEvents()
        updateYN.Text = "connecting to update server"
        request = WebRequest.Create("http://www.game-droid.co.cc/program/bin/setupGD.exe")
        response = request.GetResponse()
        reader = response.GetResponseStream()
        updateYN.Text = "connected, fetching file size"
        ProgressBar1.Maximum = CInt(response.ContentLength)
        ProgressBar1.Value = 0
        total = 0
        updateYN.Text = "writing file to temporary directory"
        writer = File.Create(Application.StartupPath + "\Bin\temp\setupGD.exe")
        While True
            count = reader.Read(data, 0, 1024)
            If count <= 0 Then
                Exit While
            End If
            writer.Write(data, 0, count)
            total += 1024
            If total < ProgressBar1.Maximum Then ProgressBar1.Value = total
            Application.DoEvents()
        End While
        reader.Close()
        writer.Close()
        Button2.Enabled = True
        updateYN.Text = "Update Downloaded"
        MsgBox("Update downloaded, patch GameDroid Now?", MsgBoxStyle.YesNo, "Update now?")
        If MsgBoxResult.Yes Then
            System.Diagnostics.Process.Start(Application.StartupPath + "\Bin\temp\setupGD.exe")
            Me.Close()
            Form1.Close()
            subcat_selector.Close()
            OptionsForm.Close()
        Else
            Me.Close()
        End If
    End Sub
End Class

it won't read the serverVS.xml file on the server, but if I click the link, it's fine...any suggestions? is their a better or easier way of doing this?
 
Your new server requires the UserAgent header to be sent with the request. This means you have to create and configure the request yourself, it is easy to do using WebClient or WebRequest, for example:
VB.NET:
Dim url As String = "http://game-droid.co.cc/program/bin/serverVS.xml"
Dim web As New Net.WebClient
web.Headers(Net.HttpRequestHeader.UserAgent) = "Anything"
Try
    Dim s As Stream = web.OpenRead(url)
    Dim doc As New Xml.XmlDocument
    doc.Load(s)
    s.Close()
    Dim version As String = doc.SelectSingleNode("/version").InnerText
    Debug.WriteLine(version)
Catch ex As Exception
    Debug.WriteLine(ex.Message)
End Try
 
Ok, so the version successfully compares now. When I click update, I get an error on the line
VB.NET:
response = request.GetResponse()
saying 403 forbidden. Why? I can download the file using any other download mannager and then rename it correctly, but this has me stumped.

VB.NET:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        updateYN.Text = "Downloading updates"
        Button2.Enabled = False
        updateYN.Text = "Checking temporary directory"
        If System.IO.Directory.Exists(Application.StartupPath + "\Bin\temp\") Then
            updateYN.Text = "directory exists"
        ElseIf System.IO.Directory.Exists(Application.StartupPath + "\Bin\temp\") = False Then
            updateYN.Text = "directory doesn't exist, creating"
            System.IO.Directory.CreateDirectory(Application.StartupPath + "\Bin\temp\")
            updateYN.Text = "directory created"
        End If
        status.Text = "Begining Download"
        Dim request As WebRequest
        Dim response As WebResponse
        Dim reader As Stream
        Dim writer As Stream
        Dim data(1023) As Byte
        Dim count As Integer
        Dim total As Integer
        Application.DoEvents()
        updateYN.Text = "connecting to update server"
        Dim url As String = "http://game-droid.co.cc/program/bin/setupGD.UPDATE"
        Dim web As New Net.WebClient
        web.Headers(Net.HttpRequestHeader.UserAgent) = "Update Request"
        request = WebRequest.Create(url)
        response = request.GetResponse()
        reader = response.GetResponseStream()
        updateYN.Text = "connected, fetching file size"
        ProgressBar1.Maximum = CInt(response.ContentLength)
        ProgressBar1.Value = 0
        total = 0
        updateYN.Text = "writing file to temporary directory"
        writer = File.Create(Application.StartupPath + "\Bin\temp\setupGD.exe")
        While True
            count = reader.Read(data, 0, 1024)
            If count <= 0 Then
                Exit While
            End If
            writer.Write(data, 0, count)
            total += 1024
            If total < ProgressBar1.Maximum Then ProgressBar1.Value = total
            Application.DoEvents()
        End While
        reader.Close()
        writer.Close()
        Button2.Enabled = True
        updateYN.Text = "Update Downloaded"
        MsgBox("Update downloaded, patch GameDroid Now?", MsgBoxStyle.YesNo, "Update now?")
        If MsgBoxResult.Yes Then
            System.Diagnostics.Process.Start(Application.StartupPath + "\Bin\temp\setupGD.exe")
            Me.Close()
            Form1.Close()
            subcat_selector.Close()
            OptionsForm.Close()
        Else
            Me.Close()
        End If
    End Sub

Origionally I had this:
VB.NET:
request = WebRequest.Create("http://game-droid.co.cc/program/bin/setupGD.exe")
but that threw the 403 error, so I changed it to:
VB.NET:
        Dim url As String = "http://game-droid.co.cc/program/bin/setupGD.UPDATE"
        Dim web As New Net.WebClient
        web.Headers(Net.HttpRequestHeader.UserAgent) = "Update Request"
        request = WebRequest.Create(url)
thinking it would work because that's what I had to do with the xml. Same error
 
this:
Dim url As String = "http://game-droid.co.cc/program/bin/setupGD.UPDATE"
Dim web As New Net.WebClient
web.Headers(Net.HttpRequestHeader.UserAgent) = "Update Request"
...followed by this:
VB.NET:
web.DownloadFile(url, "setup.exe")
...gives me no trouble downloading the file. As mentioned in post 9 you can also use the async method and progress/complete events of WebClient.

The problem you had was because you mixed two different request codes, and didn't set UserAgent for other request.
 
Back
Top