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
zoraxe
  • Members
  • 25 posts
  • Last active: Dec 14 2012 10:29 AM
  • Joined: 17 Aug 2012

1. For some reason the Shell.Run task didn't wait for TaskKill to complete, before trying to update the exe file.
I added a Sleep task for 1 sec. to solve this (in the VBScript).


Can you post the code you have? I know there was a problem with the older versions of the updater where that would happen almost every time.


Used the latest version I've seen here - v1.7

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

Used the latest version I've seen here - v1.7


Try editing the update function so the vbs file doesn't delete its self then can you paste that here?

All of the tests i've run show that it properly kills the script and starts the new one without any problems.

blode
  • Members
  • 25 posts
  • Last active: Apr 27 2013 04:49 PM
  • Joined: 11 Jul 2012
part of my script just failed to find the VBS post-update window
IfWinExist, Windows Script Host, Update completed successfully


i think i found why ;)
If (_SuppressMsgBox < 2)
			VBS_P3 .= "`r`nWScript.Echo ""Update complected successfully."""


Albvar
  • Members
  • 5 posts
  • Last active: Feb 14 2013 11:36 PM
  • Joined: 08 Feb 2013

Hello!

 

I was able to update a compiled .exe from a machine that had AHK installed. I ran the exe on a machine that did not have ahk installed and it would not self update. Is it possible to make it auto update the executeable without having to install autohotkey?



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

Hello!

 

I was able to update a compiled .exe from a machine that had AHK installed. I ran the exe on a machine that did not have ahk installed and it would not self update. Is it possible to make it auto update the executeable without having to install autohotkey?

 

It should already be able to do that. Can you post the script you're using here so I can check it?



Albvar
  • Members
  • 5 posts
  • Last active: Feb 14 2013 11:36 PM
  • Joined: 08 Feb 2013

It should already be able to do that. Can you post the script you're using here so I can check it?

Thanks for the reply!

 

I was just testing it so simply it's just sleep and a msgbox.

 

 

Sleep, 5000
Msgbox,,,Hello

Check_ForUpdate(1,0)
Check_ForUpdate(_ReplaceCurrentScript = 1, _SuppressMsgBox = 0, _CallbackFunction = "", ByRef _Information = "")
{
	;Version.ini file format - this is just an example of what the version.ini file would look like
	;
	;[Info]
	;Version=1.8
	;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 := "autoupdater" ;Your script name
	, Version_Number := 1.8 ;The script's version number
	, Update_URL := "http://10.88.1.18:8081/CICS/download/version.ini" ;The URL of the version.ini file for your script
	, Retry_Count := 1 ;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 {
									Ptr := A_PtrSize ? "Ptr" : "UInt"
									, H := DllCall("CreateFile",Ptr,&Temp_FileName,"UInt",0x80000000,"UInt",3,"UInt",0,"UInt",3,"UInt",0,"UInt",0)
									, DllCall("GetFileSizeEx",Ptr,H,"Int64*",FileSize)
									, FileSize := FileSize = -1 ? 0 : FileSize
									
									If (FileSize != 0){
										VarSetCapacity(Data,FileSize,0)
										, DllCall("ReadFile",Ptr,H,Ptr,&Data,"UInt",FileSize,"UInt",0,"UInt",0)
										, DllCall("CloseHandle",Ptr,H)
										, VarSetCapacity(MD5_CTX,104,0)
										, DllCall("advapi32\MD5Init",Ptr,&MD5_CTX)
										, DllCall("advapi32\MD5Update",Ptr,&MD5_CTX,Ptr,&Data,"UInt",FileSize)
										, DllCall("advapi32\MD5Final",Ptr,&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",Ptr,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 /PID %MyPID%", 0, 1
			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
}


lagomorph
  • Members
  • 403 posts
  • Last active: May 15 2014 03:41 PM
  • Joined: 02 Apr 2010

This was what I did to add change notes to the function:

 

 

Add this to your script, if you please. Customize various options as needed.

UpdateAnnounce(AnnounceMessage)
{
Gui 2:+alwaysontop -SysMenu +Owner
AnnounceMessage := RegExReplace(AnnounceMessage,"``n","`n")
Gui, 2:Add, Text, w525, %AnnounceMessage%
Gui, 2:Add, Button, Default gupdatemessagebutton, OK
Gui, 2:Show, Autosize, AutoFlash Update Message
WinWaitClose, AutoFlash Update Message
;MsgBox ,4096,,AutoFlash was just updated!`n`n%AnnounceMessage%`n`nPress OK to restart AutoFlash
return
}

Add a "ChangeLog" Key to your "Version.ini" file. Include `n linebreaks as needed for multiline change notes.

 

Add this line to the check_forupdate function, right after the IniRead,URL,%Version_File%,Info,URL line

IniRead,AnnounceMessage,%Version_File%,Info,ChangeLog

Also edit the callback function section of the code so that it passes our AnnounceMessage variable as a parameter. Then just add the callback function parameter when you call the function.

 

Thanks to TLM and Tomoe for helping me figure out how to sanitize the linefeeds in the changelog variable to display multiline correctly from the .ini file.

 

 



tps242
  • Members
  • 26 posts
  • Last active: Jan 21 2015 06:50 AM
  • Joined: 01 Dec 2014

Does this not work  with dropbox or what?

[Info]
Version=3.4
URL=https://www.dropbox.com/s/r5o80fqdp32yqlk/Helper.ahk?dl=1

The code added to the end :

Check_ForUpdate(_ReplaceCurrentScript = 1, _SuppressMsgBox = 0, _CallbackFunction = "", ByRef _Information = "")
{
;Version.ini file format - this is just an example of what the version.ini file would look like
;
;[Info]
;Version=1.9
;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 := "Helper" ;Your script name
, Version_Number := 3.2 ;The script's version number
, Update_URL := "https://www.dropbox.com/s/p3aa2eoa0bzbje3/Version.ini?dl=1" ;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 {
Ptr := A_PtrSize ? "Ptr" : "UInt"
, H := DllCall("CreateFile",Ptr,&Temp_FileName,"UInt",0x80000000,"UInt",3,"UInt",0,"UInt",3,"UInt",0,"UInt",0)
, DllCall("GetFileSizeEx",Ptr,H,"Int64*",FileSize)
, FileSize := FileSize = -1 ? 0 : FileSize
 
If (FileSize != 0){
VarSetCapacity(Data,FileSize,0)
, DllCall("ReadFile",Ptr,H,Ptr,&Data,"UInt",FileSize,"UInt",0,"UInt",0)
, DllCall("CloseHandle",Ptr,H)
, VarSetCapacity(MD5_CTX,104,0)
, DllCall("advapi32\MD5Init",Ptr,&MD5_CTX)
, DllCall("advapi32\MD5Update",Ptr,&MD5_CTX,Ptr,&Data,"UInt",FileSize)
, DllCall("advapi32\MD5Final",Ptr,&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",Ptr,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 /PID %MyPID%", 0, 1
Set objFSO = CreateObject("Scripting.FileSystemObject")
)
 
If (A_IsCompiled){
SplitPath,A_ScriptFullPath,,Dir,,Name
VBS_P2 =
(LTrim Join`r`n
Finished = False
Count = 0
Do Until (Finished = True Or Count = 5)
Err.Clear
objFSO.CopyFile "%Temp_FileName%", "%Dir%\%Name%.%Extension%", True
If (Err.Number = 0) then
Finished = True
objShell.Run """%Dir%\%Name%.%Extension%"""
Else
WScript.Sleep(1000)
Count = Count + 1
End If
Loop
objFSO.DeleteFile "%Temp_FileName%", True
)
 
Return_Val :=  Temp_FileName
} 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
)
 
If (_SuppressMsgBox < 2)
{
If (InStr(VBS_P2, "Do Until (Finished = True Or Count = 5)"))
{
VBS_P3 .= "`r`nIf (Finished = False) Then"
VBS_P3 .= "`r`nWScript.Echo ""Update failed."""
VBS_P3 .= "`r`nElse"
If (Extension != "exe")
VBS_P3 .= "`r`nobjFSO.DeleteFile """ A_ScriptFullPath """"
VBS_P3 .= "`r`nWScript.Echo ""Update completed successfully."""
VBS_P3 .= "`r`nEnd If"
} Else
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
}
 
Check_ForUpdate()


capbat
  • Members
  • 191 posts
  • Last active: Feb 08 2017 06:57 PM
  • Joined: 29 Nov 2007

Hi all specialy Rseding91, Thanks for the Function.

Althoug I don't know if this thread is very much alive I haven't seen the author here since 2013, but anyways here is my problem.

 

I am woking with compiled scripts and it worked well with a small test I did using a very simple script (exe).

But on the main script I want to use the function with, I am having a little problem.

 

My scripts (Exe) works in his environment in it's working directory there are a few subdirectory for data, help, documentation files etc. and in the main directory the A_workingDir, there are 2 or 3 files images that are used by the main script (exe).

When I invoke the update function, the new exe is loaded and eventually starts executing, BUT it does not recognize the image nor the directories he is in. It seems that he has lost where he is. But if I get out of it, and re-execute it everything is Ok.

It is a very long script so I wont included here but I guess it would be replicable just by having the script use image in it`s working dir.

 

Any ideas?.

 

Bat



hotwire567
  • New members
  • 3 posts
  • Last active: Jul 31 2015 12:55 AM
  • Joined: 26 Jul 2015

Doesn't work. Help please!

http://pastebin.com/fD2Za2RS

 

When I press the check for updates button I get the A message box and then a little time later the B message box.

 

192.168.1.106 is a wampsever hosted on my local network, I will change it to my websites real url when I'm done testing.