Jump to content

AutoUpdater Concept Issue


Darkz0r
 Share

Recommended Posts

Hi everyone,

I'm coding an AutoUpdater Script for my Application and it's almost done. But the method I'm using is not the best, in fact, it will make me have a lot of work and I need to make it simplier.

My current script downloads a .txt file from the server to tempdir containing the version number and then compares it to the one in the .txt of my application folder, if the application version is lower than the server one, it will download a .rar with all the files.

So where's the problem? The problem is that the user will have to download the whole 2GB of my application everytime there is an update.

My idea was to just compare the client and server files and then if it would download just the different files. I've seen some methods around here but they don't do exactly what I need, also I don't think they support subfolder check.

Could some give me some advice? Or maybe even give me an example please?

Edited by Darkz0r
Link to comment
Share on other sites

I would go with robocopy's /mir function. It is setup to only copy newer files, and delete files that no longer exist in the source.

Basically make a second script for updating. When there is and update, the main program launches the updater and kills itself. And the main program should watch to update the updater.

You can also check the file version, rather than using a separate text file to keep track of versions.

There are mirror scripts native to autoit if you search for them.

Edited by DicatoroftheUSA
Link to comment
Share on other sites

Firstly, thanks to both of you! :)

I would go with robocopy's /mir function. It is setup to only copy newer files, and delete files that no longer exist in the source.

Basically make a second script for updating. When there is and update, the main program launches the updater and kills itself. And the main program should watch to update the updater.

You can also check the file version, rather than using a separate text file to keep track of versions.

There are mirror scripts native to autoit if you search for them.

Hmm, I'd rather not use external applications if possible, but if there's no other way I'll give it a try.

Take a look at

Looks interesting. Any idea how to declare $PathFrom to my FTP server?

Link to comment
Share on other sites

I'm a bit confused. If you are only updating helper files and not the 2GB app everytime. Why not just exclude it from the .rar file and only push down the files that have changed? Seems a bit overly complicated if I'm understanding you right.

EndFuncAutoIt is the shiznit. I love it.
Link to comment
Share on other sites

Well, I don't blame you, I'm a bit confused myself trying to get some method to autoupdate files that I may be missing something stupidly obvious.

To give you an idea of what I'm talking, here is an example of my script:

#include <GUIConstantsEx.au3> ; Needed for $GUI_EVENT_CLOSE

InetGet("http://www.myurl.com/autoupdater_version.txt", @TempDir & "\autoupdater_version.txt") ; Get the file with update info
$AutoUpdater_File = FileOpen(@TempDir & "\autoupdater_version.txt", 0) ; Opens the File with update info
$AutoUpdater_Server_Version = FileReadLine($AutoUpdater_File, 1) ; Reads the first line (Version Value)
FileClose($AutoUpdater_File) ; Closes the update info file as it is not needed anymore
$AutoUpdater_Version = "1.0" ; The current version of the AutoUpdater (I actually check it from a file in my actual script)
InetGet("http://www.myurl.com/app_version", @TempDir & "\app_version.txt") ; Gets the Application update info
$server_file = FileOpen(@TempDir & "\app_version.txt", 0) ; Opens the File with the application update info
$Server_Version = FileReadLine($server_file, 1) ; Reads the first line (Version Value)
$Client_Version = "1.0" ; The current version of the Application
$Link_FULL = FileReadLine($server_file, 2) ; Reads the second line (Link with the full version)
$Link_UPDATE = FileReadLine($server_file, 3) ; Reads the third line (Link for the update)
FileClose($server_file) ; Closes the file with the application update info


; Call main function
MainWindow()

; Begin MainWindow Function
Func MainWindow()
    Global $Form1 = GUICreate("My AutoUpdater v1.0", 150, 130) ; Gui & title name
    $Button1 = GUICtrlCreateButton("Update", 25, 30, 100, 25, 0) ; Update Button
    $Button3 = GUICtrlCreateButton("Exit", 25, 70, 100, 25, 0) ; Exit Button
    GUISetState() ; Set GUI Visible

    While 1 ; While Function Running
        Switch GUIGetMsg() ; Check for user events
            Case $GUI_EVENT_CLOSE ; If close (X) clicked then...
                Exit ; Closes application
            Case $Button3 ; If Exit button pressed then...
                ExitLoop ; Closes application
            Case $Button1 ; If Update button pressed then...
                If $Server_Version > $Client_Version Then ; Check if the last version is higger than our current version, if yes...
                    ; Do the update stuff
                EndIf ; Finish the Check
        EndSwitch ; End Switch
    WEnd ; End While
    GUIDelete($Form1) ; Close the GUI
EndFunc ; End of MainWindow Function

I believe the problem is with the method I'm using to check for updates on the server.

I'll have to make a .rar everytime there is an update and it will keep getting bigger and bigger...

For example: If the Application last version is 10.1 and the user still has 1.0 he will not update to 1.1, then 1.2, then 1.3 and so on until 10.1

so I have to keep all the files I keep updating from 1.0 until 10.1 in the .RAR.

So, having a method that compares server and client versions and updating when there are new ones seems a better idea.

Also...

Here is my current version of _RSync using FTPEx.au3 (not working):

#include <FTPEx.au3>

; Global vars
Local $ftp_server = "ftp.myserver.com" ; Your FTP Server
Local $ftp_username = "myusername" ; Your FTP Username
Local $ftp_password = "mypassword" ; Your FTP Password
Local $ftp_open = _FTP_Open("MyFTP Control")
Local $ftp_connection = _FTP_Connect($ftp_open, $ftp_server, $ftp_username, $ftp_password)
Global $PathFrom = _FTP_ListToArray($ftp_connection, 0) ; Will return an array with list of directories

If @error Then MsgBox(0, "Error", "Error connecting to FTP Server")
$PathTo = @ScriptDir

; Ensure $PathTo is readable
$PathTo = StringStripWS($PathTo, 3)
If StringRight($PathTo, 1) = "\" Then
$PathTo = StringTrimRight($PathTo, 1)
EndIf

; Basic check: $PathTo MUST exist
If Not FileExists($PathTo) Then
MsgBox(0, "Error", "Invalid destination :" & @LF & $PathTo)
Exit
EndIf

; Ask for a synchro...
; Synchro source to destination
_RSync("", $PathFrom[3], $PathTo) ; [3] -> Is the "public_html" directory


Func _RSync($subpath, $from, $to)
; $subpath is built along the way, and passed recursively
; $from and $to are here because source and destination are to be swapped.
; I left som ConsoleWrite(), just see how they work
ConsoleWrite("Scanning " & $from & $subpath & @LF)
; Building the logical source directory
; Remember source dans dest are logical :)
Local $h_Handle
Local $FilesFrom = _FTP_FindFileFirst($ftp_connection, $from & $subpath & "\*.*", $h_Handle)

While 1
Local $file = _FTP_FindFileNext($h_Handle)
If @error Then ExitLoop
; Building the full path to source and destination file (or directory)
Local $filename = FileGetLongName($from & $subpath & "\" & $file)
Local $tofilename = FileGetLongName($to & $subpath & "\" & $file)
; Getting the file (or dir) properties
Local $fileprops = FileGetAttrib($filename)
If StringInStr($fileprops, "D") Then
; If it's a directory
Local $subpath2 = $subpath & "\" & $file
If Not FileExists($to & $subpath2) Then
; Needed because of empty dirs, the 9 value to FileCopy can rebuild the dir tree, but only when a file is in.
DirCreate($to & $subpath2)
EndIf
; The most interesting part : this func is recursive :)
; Beware of the recursion level : 384.
_RSync($subpath2, $from, $to)
Else
; Not a dir, mostly files and links
; Getting the mod. time of source and dest file...
Local $fromtime = FileGetTime($filename, 0, 1)
Local $totime = FileGetTime($tofilename, 0, 1)

; In case the destination file does not exists, $fromtime is always greater than $totime
If $fromtime > $totime Then
FileCopy($filename, $tofilename, 9)
ConsoleWrite("Synchro " & $filename & " And " & $tofilename & @LF)
EndIf
EndIf
WEnd

; Proper close of the file list
_FTP_FindFileClose($h_Handle)
; Close the FTP connection
_FTP_Close($ftp_open)
EndFunc

I always get trouble parsing arrays. Could use some help... :S

Edited by Darkz0r
Link to comment
Share on other sites

Well I have an application and the way it checks for updates is probably not the best but it works without downloading anything or needing to check a database.

I made a simple HTML page that has nothing in it but the version #. e.g. www.yoursite.com/version.html That's it no tags of any kind. Just one line with the version. I tell the app to check that URL if there is an internet connection using _INetGetSource() I compare it to the internal number of the app and if it's newer I tell the user there is a newer version and ask if they want to download it. I use inetGet to retrieve the file from a location on my site and it brings up the installer and it's pretty fast.

What type of app do you have that is 2GB anyway? That is huge for an EXE. My app is pretty big with 3500 + lines of code and its only like 1MB when compiled and it does a lot of stuff. So I'm curious as to why yours is so huge.

EndFuncAutoIt is the shiznit. I love it.
Link to comment
Share on other sites

I believe the problem is with the method I'm using to check for updates on the server.

I'll have to make a .rar everytime there is an update and it will keep getting bigger and bigger...

For example: If the Application last version is 10.1 and the user still has 1.0 he will not update to 1.1, then 1.2, then 1.3 and so on until 10.1

so I have to keep all the files I keep updating from 1.0 until 10.1 in the .RAR.

So, having a method that compares server and client versions and updating when there are new ones seems a better idea.

G'day Darkz0r

What about a RAR file for each version?

Then your update file (INI) could look something like this.

[Latest Version]
Version=10.1
[1.1]
url=http://www.olddomain.com/myprog1.1.rar
OtherUsefullInfo=really old version on another server
.
.
.
[10.0]
url=http://www.mydomain.com/myprog10.0.rar
OtherUsefullInfo=maybe a message about what was added etc
[10.1]
url=http://www.mydomain.com/myprog10.1.rar
OtherUsefullInfo=maybe a message about what was added etc
SpecialCommandsToUse=del \myprog\settings\*.*

Your code updater could read the "latest version" compare it with the version returned form "FileGetVersion ()" and if it's not the same iterate through the avalable versions until it hits one higher than it's current version. Then download and install it.

After the update the "new" version could check if it needs updating and if needed proceed to update again.

That way you only have to worry about the updates between versions even if they have a verison that is years old. :)

Alos your RAR file is only as big as it needs to be for each version.

Hope everyone has a great Christmas

John Morrison

Link to comment
Share on other sites

Well I have an application and the way it checks for updates is probably not the best but it works without downloading anything or needing to check a database.

I made a simple HTML page that has nothing in it but the version #. e.g. www.yoursite.com/version.html That's it no tags of any kind. Just one line with the version. I tell the app to check that URL if there is an internet connection using _INetGetSource() I compare it to the internal number of the app and if it's newer I tell the user there is a newer version and ask if they want to download it. I use inetGet to retrieve the file from a location on my site and it brings up the installer and it's pretty fast.

What type of app do you have that is 2GB anyway? That is huge for an EXE. My app is pretty big with 3500 + lines of code and its only like 1MB when compiled and it does a lot of stuff. So I'm curious as to why yours is so huge.

I thought of the same, but at the time I wasn't really sure of the function that would read from the html file, _INetGetSource(), thank you, that it's quite handy actually!

By application I don't mean the compiled script itself, but a game I'm currently developing, which obviously, has multiple files.

G'day Darkz0r

What about a RAR file for each version?

Then your update file (INI) could look something like this.

[Latest Version]
Version=10.1
[1.1]
url=http://www.olddomain.com/myprog1.1.rar
OtherUsefullInfo=really old version on another server
.
.
.
[10.0]
url=http://www.mydomain.com/myprog10.0.rar
OtherUsefullInfo=maybe a message about what was added etc
[10.1]
url=http://www.mydomain.com/myprog10.1.rar
OtherUsefullInfo=maybe a message about what was added etc
SpecialCommandsToUse=del \myprog\settings\*.*

Your code updater could read the "latest version" compare it with the version returned form "FileGetVersion ()" and if it's not the same iterate through the avalable versions until it hits one higher than it's current version. Then download and install it.

After the update the "new" version could check if it needs updating and if needed proceed to update again.

That way you only have to worry about the updates between versions even if they have a verison that is years old. :)

Alos your RAR file is only as big as it needs to be for each version.

Hope everyone has a great Christmas

John Morrison

Well, that could also work, But I'm having a problem with "IniReadSectionNames" It is just finding the first Section and I'm not sure why...

Also, I'm not completely sure how I'll get the last version available...

Here is my current example script:

; Write version.ini on ScriptDir for testing purposes
FileDelete(@ScriptDir & "\version.ini")
IniWrite(@ScriptDir & "\version.ini", "1.0", "URL", "http://www.update.com/1.0")
; __________________________________________________________________
IniWrite(@ScriptDir & "\version.ini", "1.1", "URL", "http://www.update.com/1.1")
; __________________________________________________________________
IniWrite(@ScriptDir & "\version.ini", "1.2", "URL", "http://www.update.com/1.2")
; __________________________________________________________________



; Declare the current version of the Application
Local $client_version = "1.0" ; In my actual script, I use FileRead with StringRegExp

; Read the section names
Local $SectionNames = IniReadSectionNames(@ScriptDir & "\version.ini")
For $a = 1 To $SectionNames[$a] ; Creating a loop to get all section names
    ; Now we read the keys of each Section
    Local $keys = IniReadSection(@ScriptDir & "\version.ini", $SectionNames[$a])
    ; If an error occurred when trying to Read
    If @error Then
        MsgBox(4096, "", "Error occurred, probably no INI file.")
    ; If no error
    Else
        ; Creates a loop to get all keys within each section
        For $i = 1 To $keys[0][0]
            ; Now show us each section, key and their values
            MsgBox(4096, "", "Section: " & $SectionNames[$a] & @CRLF _ ; Break line
            & "Key: " & $keys[$i][0] & @CRLF & "Value: " & $keys[$i][1])

            ; Do the comparison here with the Latest version
        Next
    EndIf
Next
Link to comment
Share on other sites

Your for loop has small error.

It should read

For $a = 1 To $SectionNames[0]

You might like looking at this as well

should allow you to get the ini file directly into memory and handle it from there without the need for a file on the hard drive. :)

Good Luck!

John Morrison

P.S when you get it all worked out It'd be great to see your solution.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...