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
Download: >Here<
Version: 1.7

Compatible with: AHK Basic, AHK L ANSI, AHK L Unicode x86/x64

Download MD5 creator: >Here<



What is it?

This is a self script updater. It allows a script to check if there is a newer version of its self available and optionally download and switch to the newer version while keeping the same filename and location.

Example:

Script A (version 1.0) -> check_forupdate()

check_forupdate() -> downloads Script A (version 1.1)
check_forupdate() -> kills Script A (version 1.0)
check_forupdate() -> replaces Script A (version 1.0) with Script A (version 1.1)
check_forupdate() -> starts Script A (version 1.1)

It works with a compiled or uncompiled script and can switch to a compiled or uncompiled script through the update process.


How to use it

1. Download and add the "Check_ForUpdate()" function into your script
2. Create a file with the name of "Version.ini" and the following content:

[Info]
Version=1.0
URL=https://ahknet.autohotkey.com/~Rseding91/Self%20Script%20Updater/Self%20Script%20Updater.ahk
MD5=04EB42FE8048E54AA1C414A1780D896D

-Replace the "Version" number with the version of your latest script.
-Replace the "URL" with the URL for your script file.
-Replace the "MD5" hash with the hash of your file. Or, if you don't want to use the MD5 hash verification simply omit the MD5 key from the ini file.

3. Upload the "Version.ini" file to a website of your choosing
4. In the "Check_ForUpdate()" function replace the following:

Static Script_Name := "Self Script Updater" ;Your script name
, Version_Number := 1.0 ;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

-Replace the "Version_Number" with the version number of your script
-Replace the "Update_URL" with the URL of the Version.ini file you just uploaded

5. Now, simply call the function and it will do its stuff.


What are the paramaters of the function for?

There are 4 paramaters and a return value depending on what happens with the function. All of the paramaters are optional.

parameter 1: _ReplaceCurrentScript = 1
About: If set to 1, the function will attempt to overwrite the existing running script with the downloaded version (if there is a newer version available). If this is set to 0 the function will return the downloaded file (path+name)

parameter 2: _SuppressMsgBox = 0
About: If set to 1, the function will skip asking if the user wants to update and simply attempt to update (if there is a newer version available).
If set to 2, the function will skip the "Update finished" message after the update finishes.
If set to 3, the function will skip both of the messages.

parameter 3: _CallbackFunction = ""
About: If set the function will call this function before the update process kills the running script. If the function doesn't exist it will say so in the error information paramater (the 4th one).

parameter 4: ByRef _Information = ""
About: If you want error information; pass a byref variable for the fourth paramater and it will be set to any errors that may happen.

Sack
  • Guests
  • Last active:
  • Joined: --
Its too big for such a simple task, I think using MD5 check function is more reliable, smaller and needs less work.

Rseding91
  • Members
  • 703 posts
  • Last active: Apr 02 2016 05:05 AM
  • Joined: 07 Jun 2010
I'm not quite sure I get what your saying.. the function uses a MD5 check on the file it downloads?

The reason it's so big is the error checking and retrying if anything goes wrong as well as the "replace the current running script with the downloaded one".

If you want, I could remove all the error checking and provide a compact version of the function. That would reduce the filesize by a lot.

Rseding91
  • Members
  • 703 posts
  • Last active: Apr 02 2016 05:05 AM
  • Joined: 07 Jun 2010
Updated to 1.1

I forgot to add the return value if anything went wrong.. oops

Uberi
  • Moderators
  • 1119 posts
  • Last active: May 02 2015 06:05 PM
  • Joined: 23 Aug 2010
How about a callback function so the script can show save/close/update dialogs? Something like CheckForUpdate(Func("UpdateCallback")).

Works nicely, very simple to use.

aaronbewza
  • Members
  • 466 posts
  • Last active: Feb 05 2013 08:40 AM
  • Joined: 20 Feb 2011
very, very cool! :) I might be back with a question or two... this is something I'd definitely find use for.

Rseding91
  • Members
  • 703 posts
  • Last active: Apr 02 2016 05:05 AM
  • Joined: 07 Jun 2010
Updated to 1.2

Changed the SuppressMsgBox paramater to be: 1 - skip asking to update, 2 - skip showing a "finished" message when the update finishes, 3 - skips both messages
Changed the third paramater (error/information) to the fourth paramater.
Made the third paramater a callback function that will be called when the script is about to kill its self and start the newer version.

Rseding91
  • Members
  • 703 posts
  • Last active: Apr 02 2016 05:05 AM
  • Joined: 07 Jun 2010
Updated to 1.3

Fixed the optional function callback paramater. I typed it wrong in the last version.

iBrandon318
  • Members
  • 8 posts
  • Last active: Nov 18 2011 12:27 AM
  • Joined: 21 Oct 2011

Updated to 1.3

Fixed the optional function callback paramater. I typed it wrong in the last version.


Updated to 1.3

Fixed the optional function callback paramater. I typed it wrong in the last version.


For Some Reason Mine Won't Work.

I Have In My Script
Check_ForUpdate(_ReplaceCurrentScript = 0, _SuppressMsgBox = 1, _CallbackFunction = "", ByRef _Information = "")
{
	;Version.ini file format
	;
	;[Info]
	;Version=1.1
	;URL=http://_______.info/Self%20Script%20Updater.ahk
	;MD5=A9F3CE97FE2D0BD9C3969D70928FC2DC
	
	Static Script_Name := "Self Script Updater" ;Your script name
	, Version_Number := 1.1 ;The script's version number
	, Update_URL := "http://________.info/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 .= "WScript.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
}

And My Version.ini shows
[Info]
Version=1.2
URL=http://________.info/Accept%20Potfarm%20Gift%20Script.ahk
MD5=A9F3CE97FE2D0BD9C3969D70928FC2DC

But When I Run The Script, No Update Message Comes Up. Help?

Rseding91
  • Members
  • 703 posts
  • Last active: Apr 02 2016 05:05 AM
  • Joined: 07 Jun 2010
2 things :)

1. you have "replace current script" set at 0 - no.

2. you have suppress message box default to 1 - skip asking if you want to update


Call the function like so: Check_ForUpdate(1,0)

Or, if you don't want to msgbox: Check_ForUpdate(1,1)

Also, make sure the url you have is valid - <!-- m -->http://________.info/Version.ini<!-- m --> isn't a valid website.

iBrandon318
  • Members
  • 8 posts
  • Last active: Nov 18 2011 12:27 AM
  • Joined: 21 Oct 2011

2 things :)

1. you have "replace current script" set at 0 - no.

2. you have suppress message box default to 1 - skip asking if you want to update


Call the function like so: Check_ForUpdate(1,0)

Or, if you don't want to msgbox: Check_ForUpdate(1,1)

Also, make sure the url you have is valid - <!-- m -->http://________.info/Version.ini<!-- m --> isn't a valid website.


Thanks For Your Help :) Got It.

Rseding91
  • Members
  • 703 posts
  • Last active: Apr 02 2016 05:05 AM
  • Joined: 07 Jun 2010
Updated to 1.4

Fixed the suppress msgbox option - it was throwing errors.

help meh
  • Guests
  • Last active:
  • Joined: --
it doesnt work for me :(


here is the ini
[Info] 
Version=1.0 
URL=http://fake.webs.com/test.ahk

and the ahk script

 Check_ForUpdate(1,0)(_ReplaceCurrentScript = 1, _SuppressMsgBox = 0, _CallbackFunction = "", ByRef _Information = "")
{
	;Version.ini file format
	;
	;[Info]
	;Version=1.5
	;URL=http://www.fake.webs.com/test.ahk
	
	
	Static Script_Name := "Self Script Updater" ;Your script name
	, Version_Number := 1.3 ;The script's version number
	, Update_URL := "http://www.fake.webs.com/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
}


Uberi
  • Moderators
  • 1119 posts
  • Last active: May 02 2015 06:05 PM
  • Joined: 23 Aug 2010

it doesnt work for me :(


Maybe because "http://www.fake.webs.com/version.ini" is not available?

awannaknow
  • Members
  • 372 posts
  • Last active: Mar 03 2019 05:18 AM
  • Joined: 14 Jun 2009

5. Now, simply call the function and it will do its stuff.

Thank you rseding91,
I want to add your updater function to a script I'm trying to make (not finished, yet).

But I don't know how to call it.
I just copied the entire content of your Self Script Updater.ahk and pasted it at the very end of my AHK script.
I read 2 posts of members trying to call it in 2 different way :
1 - iBrandon318 like this :
Check_ForUpdate(_ReplaceCurrentScript = 0, _SuppressMsgBox = 1, _CallbackFunction = "", ByRef _Information = "")
seems to like just pasting the first line.

2 - help meh
[color=red]Check_ForUpdate(1,0)[/color](_ReplaceCurrentScript = 1, _SuppressMsgBox = 0, _CallbackFunction = "", ByRef _Information = "")
just adding the red part.
Shall I add something like this Check_ForUpdate(1,0) anywhere in my script (just modifying parameters). Let say at the beginning, before the first return ?
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