Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

[Func] Self script updater


  • Please log in to reply
69 replies to this topic
Rseding91
  • Members
  • 703 posts
  • Last active: Apr 02 2016 05:05 AM
  • Joined: 07 Jun 2010
You would paste the function into your script then in a different area where you want to run it you past this:

Check_ForUpdate(1,0)

Making sure to change the values in the function to the ones your script should be using (version number/name/website).

awannaknow
  • Members
  • 372 posts
  • Last active: Mar 03 2019 05:18 AM
  • Joined: 14 Jun 2009
I'll do as you say, thanks for guidance.

You would paste the function into your script then in a different area where you want to run it you past this:

Check_ForUpdate(1,0)


Making sure to change the values in the function to the ones your script should be using (version number/name/website).

Already done, I understdood your instructions but was not sure about # 5.
I'm not used to functions . . .
Your scripts online or anything you'll need online for free with 0hna.tk  like: Zero $ Hosting No Ad Free Online Hosting
Remove comments and blank lines in AHK code

awannaknow
  • Members
  • 372 posts
  • Last active: Mar 03 2019 05:18 AM
  • Joined: 14 Jun 2009
I tested and it is not working for me, is this (Code first line) must be changed to or leave as is ?:
Check_ForUpdate(_ReplaceCurrentScript = 0, _SuppressMsgBox = 0, _CallbackFunction = "", ByRef _Information = "")
and I skipped md5, so ini is like this :
[Info] 
Version=1.0 
URL=https://ahknet.autohotkey.com/~Rseding91/Self%20Script%20Updater/Self%20Script%20Updater.ahk 
MD5=
Maybe "md5=" must be erased ?
Your scripts online or anything you'll need online for free with 0hna.tk  like: Zero $ Hosting No Ad Free Online Hosting
Remove comments and blank lines in AHK code

Rseding91
  • Members
  • 703 posts
  • Last active: Apr 02 2016 05:05 AM
  • Joined: 07 Jun 2010
The ini file should contain the version number of your script that you have stored online someplace. The url should contain the location to download that version of the script.


You can see how to call the function with this example:
;This is the function-call. The part that tells autohotkey to execute the function below.
Check_ForUpdate(1)

;The 1 tells the function to use 1 as the first paramater - setting "_ReplaceCurrentSCript" to 1.

;This is the actual function.
Check_ForUpdate(_ReplaceCurrentScript = 0, _SuppressMsgBox = 0, _CallbackFunction = "", ByRef _Information = "")
{
	;Version.ini file format
	;
	;[Info]
	;Version=1.4
	;URL=http://www.mywebsite.com/my%20file.ahk or .exe
	;MD5=00000000000000000000000000000000 or omit this key completly to skip the MD5 file validation
	
	Static Script_Name := "Self Script Updater" ;Your script name
	, Version_Number := 1.3 ;The script's version number
	, Update_URL := "https://ahknet.autohotkey.com/~Rseding91/Self%20Script%20Updater/Version.ini" ;The URL of the version.ini file for your script
	, Retry_Count := 3 ;Retry count for if/when anything goes wrong
	
	Random,Filler,10000000,99999999
	Version_File := A_Temp . "\" . Filler . ".ini"
	, Temp_FileName := A_Temp . "\" . Filler . ".tmp"
	, VBS_FileName := A_Temp . "\" . Filler . ".vbs"
	
	Loop,% Retry_Count
	{
		_Information := ""
		
		UrlDownloadToFile,%Update_URL%,%Version_File%
		
		IniRead,Version,%Version_File%,Info,Version,N/A
		
		If (Version = "N/A"){
			FileDelete,%Version_File%
			
			If (A_Index = Retry_Count)
				_Information .= "The version info file doesn't have a ""Version"" key in the ""Info"" section or the file can't be downloaded."
			Else
				Sleep,500
			
			Continue
		}
		
		If (Version > Version_Number){
			If (_SuppressMsgBox != 1 and _SuppressMsgBox != 3){
				MsgBox,0x4,New version available,There is a new version of %Script_Name% available.`nCurrent version: %Version_Number%`nNew version: %Version%`n`nWould you like to download it now?
				
				IfMsgBox,Yes
					MsgBox_Result := 1
			}
			
			If (_SuppressMsgBox or MsgBox_Result){
				IniRead,URL,%Version_File%,Info,URL,N/A
				
				If (URL = "N/A")
					_Information .= "The version info file doesn't have a valid URL key."
				Else {
					SplitPath,URL,,,Extension
					
					If (Extension = "ahk" And A_AHKPath = "")
						_Information .= "The new version of the script is an .ahk filetype and you do not have AutoHotKey installed on this computer.`r`nReplacing the current script is not supported."
					Else If (Extension != "exe" And Extension != "ahk")
						_Information .= "The new file to download is not an .EXE or an .AHK file type. Replacing the current script is not supported."
					Else {
						IniRead,MD5,%Version_File%,Info,MD5,N/A
						
						Loop,% Retry_Count
						{
							UrlDownloadToFile,%URL%,%Temp_FileName%
							
							IfExist,%Temp_FileName%
							{
								If (MD5 = "N/A"){
									_Information .= "The version info file doesn't have a valid MD5 key."
									, Success := True
									Break
								} Else {
									H := DllCall("CreateFile","Str",Temp_FileName,"UInt",0x80000000,"UInt",3,"UInt",0,"UInt",3,"UInt",0,"UInt",0)
									, VarSetCapacity(FileSize,8,0)
									, DllCall("GetFileSizeEx","UInt",H,"Int64",&FileSize)
									, FileSize := NumGet(FileSize,0,"Int64")
									, FileSize := FileSize = -1 ? 0 : FileSize
									
									If (FileSize != 0){
										VarSetCapacity(Data,FileSize,0)
										, DllCall("ReadFile","UInt",H,"UInt",&Data,"UInt",FileSize,"UInt",0,"UInt",0)
										, DllCall("CloseHandle","UInt",H)
										, VarSetCapacity(MD5_CTX,104,0)
										, DllCall("advapi32\MD5Init",Str,MD5_CTX)
										, DllCall("advapi32\MD5Update",Str,MD5_CTX,"UInt",&Data,"UInt",FileSize)
										, DllCall("advapi32\MD5Final",Str,MD5_CTX)
										
										FileMD5 := ""
										Loop % StrLen(Hex:="123456789ABCDEF0")
											N := NumGet(MD5_CTX,87+A_Index,"Char"), FileMD5 .= SubStr(Hex,N>>4,1) . SubStr(Hex,N&15,1)
										
										VarSetCapacity(Data,FileSize,0)
										, VarSetCapacity(Data,0)
										
										If (FileMD5 != MD5){
											FileDelete,%Temp_FileName%
											
											If (A_Index = Retry_Count)
												_Information .= "The MD5 hash of the downloaded file does not match the MD5 hash in the version info file."
											Else										
												Sleep,500
											
											Continue
										} Else
											Success := True
									} Else {
										DllCall("CloseHandle","UInt",H)
										Success := True
									}
								}
							} Else {
								If (A_Index = Retry_Count)
									_Information .= "Unable to download the latest version of the file from " %URL% "."
								Else
									Sleep,500
								Continue
							}
						}
					}
				}
			}
		} Else
			_Information .= "No update was found."
		
		FileDelete,%Version_File%
		Break
	}
	
	If (_ReplaceCurrentScript And Success){
		SplitPath,URL,,,Extension
		Process,Exist
		MyPID := ErrorLevel
		
		VBS_P1 =
		(LTrim Join`r`n
			On Error Resume Next
			Set objShell = CreateObject("WScript.Shell")
			objShell.Run "TaskKill -f -im %MyPID%", WindowStyle, WaitOnReturn
			WScript.Sleep 1000
			Set objFSO = CreateObject("Scripting.FileSystemObject")
		)
		
		If (A_IsCompiled){
			If (Extension = "exe"){
				VBS_P2 =
				(LTrim Join`r`n
					objFSO.CopyFile "%Temp_FileName%", "%A_ScriptFullPath%", True
					objFSO.DeleteFile "%Temp_FileName%", True
					objShell.Run """%A_ScriptFullPath%"""
				)
				
				Return_Val :=  Temp_FileName
			} Else { ;Extension is ahk
				SplitPath,A_ScriptFullPath,,FDirectory,,FName
				FileMove,%Temp_FileName%,%FDirectory%\%FName%.ahk,1
				FileDelete,%Temp_FileName%
				
				VBS_P2 =
				(LTrim Join`r`n
					objFSO.DeleteFile "%A_ScriptFullPath%", True
					objShell.Run """%FDirectory%\%FName%.ahk"""
				)
				
				Return_Val := FDirectory . "\" . FName . ".ahk"
			}
		} Else {
			If (Extension = "ahk"){
				FileMove,%Temp_FileName%,%A_ScriptFullPath%,1
				If (Errorlevel)
					_Information .= "Error (" Errorlevel ") unable to replace current script with the latest version."
				Else {
					VBS_P2 = 
					(LTrim Join`r`n
						objShell.Run """%A_ScriptFullPath%"""
					)
					
					Return_Val :=  A_ScriptFullPath
				}
			} Else If (Extension = "exe"){
				SplitPath,A_ScriptFullPath,,FDirectory,,FName
				FileMove,%Temp_FileName%,%FDirectory%\%FName%.exe,1
				FileDelete,%A_ScriptFullPath%
				
				VBS_P2 =
				(LTrim Join`r`n
					objShell.Run """%FDirectory%\%FName%.exe"""
				)
				
				Return_Val :=  FDirectory . "\" . FName . ".exe"
			} Else {
				FileDelete,%Temp_FileName%
				_Information .= "The downloaded file is not an .EXE or an .AHK file type. Replacing the current script is not supported."
			}
		}
		
		VBS_P3 =
		(LTrim Join`r`n
			objFSO.DeleteFile "%VBS_FileName%", True
			Set objFSO = Nothing
			Set objShell = Nothing
		)
		
		If (_SuppressMsgBox < 2)
			VBS_P3 .= "`r`nWScript.Echo ""Update complected successfully."""
		
		FileDelete,%VBS_FileName%
		FileAppend,%VBS_P1%`r`n%VBS_P2%`r`n%VBS_P3%,%VBS_FileName%
		
		If (_CallbackFunction != ""){
			If (IsFunc(_CallbackFunction))
				%_CallbackFunction%()
			Else
				_Information .= "The callback function is not a valid function name."
		}
		
		RunWait,%VBS_FileName%,%A_Temp%,VBS_PID
		Sleep,2000
		
		Process,Close,%VBS_PID%
		_Information := "Error (?) unable to replace current script with the latest version.`r`nPlease make sure your computer supports running .vbs scripts and that the script isn't running in a pipe."
	}
	
	_Information := _Information = "" ? "None" : _Information
	
	Return Return_Val
}


If you need help understanding functions, just open up the autohotkey manual and search for "function." There is a section on them that should explain there use better then I could.

awannaknow
  • Members
  • 372 posts
  • Last active: Mar 03 2019 05:18 AM
  • Joined: 14 Jun 2009
I'll correct mistakes.
I'll try it again later on when I'll some time for.
Thanks for help.
:wink:

Update :
Tried it, works perfectly, deleted whole md5 line in "Version.ini".
Version.ini is like this :
[Info]
Version=1.4 
URL=http://www.mywebsite.com/my%20file.ahk or .exe

Your scripts online or anything you'll need online for free with 0hna.tk  like: Zero $ Hosting No Ad Free Online Hosting
Remove comments and blank lines in AHK code

jpjazzy
  • Members
  • 800 posts
  • Last active: Dec 17 2014 07:22 AM
  • Joined: 16 Feb 2010
Using it in my newest script which should be pretty nifty I hope. I tried this and it works beautifully. Very easy too use and every time I see this (or something of the sort):

Compatible with: AHK Basic


I am pretty sure I jizz myself... No one seems to care much about basic users anymore. Even if we are no longer supported, we still exist and it is always nice to see someone who respects that. Thank you again for a beautiful piece of code. 8)

I finished the code I was working on with your script incorporated into it.
It can be found here. Give it a whirl if you have time and see if I missed anything having to do with your function or if you notice anything. Cheers.
AutoHotkey Basic - Windows 7
Posted Image

Rseding91
  • Members
  • 703 posts
  • Last active: Apr 02 2016 05:05 AM
  • Joined: 07 Jun 2010
I looked over your use of the update function and everything seems to be correct.


No one seems to care much about basic users anymore.


Yeah, I write all of my code in AHK basic and port it over to _L as I go. Most things take a tad longer to write but they still execute faster in basic :)

for me, x64 is the only "upside" I would get from switching to _L. There are more and more bugs I am finding with basic that _L has fixed so who knows, I may end up switching to _L eventually. I do dislike the whole unicode 2x RAM thing for strings though. It makes dealing with large strings very RAM intensive (which is a problem for 32 bit apps). I can always stick with ANSI _L (until V2 that is).

jpjazzy
  • Members
  • 800 posts
  • Last active: Dec 17 2014 07:22 AM
  • Joined: 16 Feb 2010
Good. Thank you for taking a look.

I honestly have never tested _L so I can't comment on the speed, but the things that AHK Basic can't do and _L can are very limited, provided you have an open mind. Some tasks might be harder, but they can be done all the same usually. Being a good designer 50% knowing commands and also thinking 'out of the box' on things you can't necessarily do by some easy method. I think Basic keeps me thinking of key ways things can be done on a most... well for lack of a better word... basic level.

I have dual operating systems, and a laptop. I use AHK_L on my laptop and one OS on the my desktop. The OS with basic is the one I use 99% of the time even with it only being installed on one of my OS... That has to be saying something with itself.

Most cost in Basic (unless it is very poorly written) can be executed in _L too, so if you write it in basic... It is going to work regardless of who executes it with what version of AHK.

A good programmer doesn't buy the most up to date phone he can find to use, he buys the one that can execute his programs with the crappiest setup he can find to make sure it works for EVERYONE. That is my state of mind, so I probably will never fully integrate into AHK_L, so long as AHK basic remains on the downloads page.

Anyway, thanks again for the update function. I am fully intending on implementing this on much more than just that script.
AutoHotkey Basic - Windows 7
Posted Image

nimda
  • Members
  • 4368 posts
  • Last active: Aug 09 2015 02:36 AM
  • Joined: 26 Dec 2010

Most cost in Basic (unless it is very poorly written) can be executed in _L too, so if you write it in basic... It is going to work regardless of who executes it with what version of AHK.

nope. If it's written for Basic and it uses DllCall chances are it won't work on AHK_L Unicode and/or x64

he buys the one that can execute his programs with the crappiest setup he can find to make sure it works for EVERYONE.

It won't work for everyone unless it's written with AHK+AHK_L+Unicode+x64 in mind. Doing so results in [ugly] code like this.

Here is not the place to argue "Basic is better! No L is better!", so I'll just leave you this (especially the bugs in Basic) and this (where Chris put AHK_L first on the downloads page)

Rseding91
  • Members
  • 703 posts
  • Last active: Apr 02 2016 05:05 AM
  • Joined: 07 Jun 2010
One bug with Basic is byref paramaters follow #MaxMem when you call varsetcapacity on them inside the function when they shouldn't.. i've had to do quite a few work-arounds for this.

Torment
  • Guests
  • Last active:
  • Joined: --
I've used your piece of script on mine and it worked great as .ahk file.
However, I have plans in sharing my script with some friends later, so i'll have to compile it to be an .exe file.
I've tryed to test the auto update with the compiled version and it doesn't work as I expected...

It asks for update as it should,
It should delete the .exe but it doesn't because it was made to only delete the .ahk file.
it downloads it as a .ahk file (makes sense since I uploaded it that way) and then it should destroy the original file,
it runs de .ahk file as the updated version and for users that don't have AutoHotkey installed it won't work I believe.

I'll try fix it myself, I'm just saying because I think it's something you haven't thought of and you didn't plan to work this way I think.
Anyway, thank you very much :)

Rseding91
  • Members
  • 703 posts
  • Last active: Apr 02 2016 05:05 AM
  • Joined: 07 Jun 2010
The updater should work when updateing from a .exe to a .ahk (if AHK is installed.) Else, it will give a error message and say it can't do the update.

It should also work to update from a .ahk to a .exe.

I believe I tested .exe update to .exe and .ahk to .ahk. If you find one specific part that isn't working I can look into it and see what's wrong. But, as it is now it should work going from either to either (providing they have AHK if you want to go to a .ahk file.)

Torment
  • Members
  • 26 posts
  • Last active: Feb 06 2012 11:47 PM
  • Joined: 13 Dec 2011
I'll test better later because now i'm busy, but you mean if I give the .exe to a friend and he auto updates it it will do fine?

Rseding91
  • Members
  • 703 posts
  • Last active: Apr 02 2016 05:05 AM
  • Joined: 07 Jun 2010
As long as he updates to a .exe or has AHK installed, yes.

jpjazzy
  • Members
  • 800 posts
  • Last active: Dec 17 2014 07:22 AM
  • Joined: 16 Feb 2010
I have been using this a lot lately, including in my new script MasterBoard. One suggestion I thought of was to add a section that could be read from the INI containing update notes to let the users know changes if the author wanted that. I don't know if that would be something you might want to do, but a formatted string of update features somehow would be nice at times to let the users know what changes were applied. Up to you. :) Still love this function.
AutoHotkey Basic - Windows 7
Posted Image