Page 1 of 1
[Solved] Auto-update running app?
Posted: Fri Dec 20, 2024 12:18 pm
by BarryG
SOLVED! The "ren" command in the batch file isn't meant to have the file path included for the new name, which was causing the "ren" command to fail. I didn't show the full path in my hasty example below (sorry). Also, you need to wrap the batch file paths in quotes too, which I didn't show below.
I'm pulling my hair out trying to get my app to auto-update itself while it's running. Downloading the new exe version is easy, but then I can't find a way to quit the app and run the new version with the same exe name. Here's the batch file that my app creates to do it, but it doesn't work all the time and also leaves "Update.bat" alive until the newly-launched exe quits, which is not good. How would you do it?
Code: Select all
; MyApp.new is the new downloaded version.
f=CreateFile(#PB_Any,"Update.bat")
If f
WriteStringN(f,"ping -n 2 127.0.0.1 >NUL")
WriteStringN(f,"del MyApp.exe")
;WriteStringN(f,"ren MyApp.new MyApp.exe") ; Original snippet with the path missing.
WriteStringN(f,"ren C:\Path\MyApp.new MyApp.exe") ; How it's supposed to be. Sorry!
WriteStringN(f,"MyApp.exe")
WriteStringN(f,"del Update.bat")
CloseFile(f)
RunProgram("Update.bat","","",#PB_Program_Hide)
End
EndIf
Re: Auto-update running app?
Posted: Fri Dec 20, 2024 2:18 pm
by Quin
To do this for my application, I wrote a tiny Updater application and include it in the executable with a DataSection and IncludeBinary. Then, when I'm updating, I go:
Code: Select all
Protected Temp$ = GetEnvironmentVariable("TEMP")
Protected FileID = CreateFile(#PB_Any, Temp$ + #PS$ + "Updater.exe")
If Not FileID
Debug "There was a problem downloading the update."
ProcedureReturn
EndIf
WriteData(FileID, ?Updater, ?EndUpdater - ?Updater)
CloseFile(FileID)
RunProgram(Temp$ + #PS$ + "Updater.exe", "", GetCurrentDirectory())
Shutdown()
The actual implementation of the updater is up to you, I just made a little window that opens showing a progress bar.
HTH!
Re: Auto-update running app?
Posted: Fri Dec 20, 2024 2:28 pm
by AZJIO
1. When you click the "update" button, a new file is downloaded.
2. Run the file and pass it the parameters “name of the process” that needs to be killed and “path to the executable file” that needs to be deleted.
3. You can make a window that will offer to close the program in the normal way. After closing the program and confirming by clicking the "OK" button, you check that the process does not exist and delete the executable file and copy the new file instead.
Re: Auto-update running app?
Posted: Fri Dec 20, 2024 4:15 pm
by Axolotl
The deletion will only work when the exe is finished.
Maybe this change helps?
Code: Select all
; MyApp.new is the new downloaded version.
f = CreateFile(#PB_Any, "Update.bat")
If f
; WriteStringN(f,"ping -n 2 127.0.0.1 >NUL")
WriteStringN(f,":Label")
WriteStringN(f,"del MyApp.exe")
WriteStringN(f,"if exist MyApp.exe goto :Label")
WriteStringN(f,"ren MyApp.new MyApp.exe")
WriteStringN(f,"MyApp.exe")
WriteStringN(f,"del Update.bat")
CloseFile(f)
RunProgram("Update.bat","","",#PB_Program_Hide)
End
EndIf
Re: Auto-update running app?
Posted: Fri Dec 20, 2024 4:57 pm
by Axolotl
Second Idea: (just coded, not tested)
Maybe this is of any help
Thank you in advance for your feedback!
Code: Select all
; ---------------------------------------------------------------------------------------------------------------------
;
; Updater.exe 0.00
;
; call the update with
; RunProgram("Updater.exe", "<ExeFile> <ServerFile> [/silent]", "")
;
; Parameter:
;
; ExeFile .. executable file to be updated (with path or should be in the same directory as the updater)
;
; ServerFile .. Location of the new file (https://....)
;
; bSilent .. /silent otherwise MessageRequester shows errors
;
; ---------------------------------------------------------------------------------------------------------------------
EnableExplicit
#ProgramName$ = "Updater"
#ErrorCaption$ = #ProgramName$ + " Error"
#InfoCaption$ = #ProgramName$ + " "
; ---------------------------------------------------------------------------------------------------------------------
Procedure GetParentPID()
Protected hSnapshot
Protected PROCESSENTRY32.PROCESSENTRY32
Protected bProcess
hSnapshot = CreateToolhelp32Snapshot_(#TH32CS_SNAPPROCESS, #Null)
If hSnapshot
PROCESSENTRY32\dwsize = SizeOf(PROCESSENTRY32)
bProcess = Process32First_(hSnapshot, @PROCESSENTRY32)
While bProcess
If PeekS(@PROCESSENTRY32\szExeFile, #MAX_PATH) = GetFilePart(ProgramFilename())
CloseHandle_(hSnapshot)
; Debug "ProcessID = " + PROCESSENTRY32\th32ProcessID
; Debug "Parent ProcessID = " + PROCESSENTRY32\th32ParentProcessID
ProcedureReturn PROCESSENTRY32\th32ParentProcessID ; return the found parent process id
EndIf
bProcess = Process32Next_(hSnapshot, @PROCESSENTRY32)
Wend
CloseHandle_(hSnapshot)
EndIf
ProcedureReturn 0 ; no parent process id found
EndProcedure
; ---------------------------------------------------------------------------------------------------------------------
Procedure.s GetProcessPath(PID)
Protected hSnapshot
Protected PROCESSENTRY32.PROCESSENTRY32
Protected bProcess
hSnapshot = CreateToolhelp32Snapshot_(#TH32CS_SNAPPROCESS, #Null)
If hSnapshot
PROCESSENTRY32\dwsize = SizeOf(PROCESSENTRY32)
bProcess = Process32First_(hSnapshot, @PROCESSENTRY32)
While bProcess
If PROCESSENTRY32\th32ProcessID = PID
CloseHandle_(hSnapshot)
ProcedureReturn PeekS(@PROCESSENTRY32\szExeFile) ; return the parent executable file name
EndIf
bProcess = Process32Next_(hSnapshot, @PROCESSENTRY32)
Wend
CloseHandle_(hSnapshot)
EndIf
ProcedureReturn "" ; no parent process found
EndProcedure
; ---------------------------------------------------------------------------------------------------------------------
Procedure Main()
Protected ExeFile$, DownloadFile$, BakFile$
Protected ExeName$, ServerFile$, path$
Protected bSilent
; read the agruments (quick and dirty)
;
ExeFile$ = ProgramParameter() ; executable file to be updated
ServerFile$ = ProgramParameter() ; i.e. "https://,,,,"
bSilent = Bool(ProgramParameter() = "/silent")
; if ExeFile$ is empty, updater.exe probably called by double click directly
;
If ExeFile$ = ""
; Not bSilent
MessageRequester(#ErrorCaption$, #ProgramName$ + " is not a stand-alone program!")
ProcedureReturn 1 ; some error
EndIf
path$ = GetPathPart(ExeFile$)
If path$ = ""
path$ = GetPathPart(ProgramFilename()) ; Updater and Executable are in the same directory !!!
EndIf
ExeName$ = GetFilePart(ExeFile$, #PB_FileSystem_NoExtension)
BakFile$ = path$ + ExeName$ + ".bak"
DownloadFile$ = path$ + ExeName$ + "_New.exe" ; temporary name for downloaded file
; do the download in some way
;
If Not ReceiveHTTPFile(ServerFile$, DownloadFile$) ;
If Not bSilent
MessageRequester(#ErrorCaption$, "Update failed!")
EndIf
ProcedureReturn 1 ; some error
EndIf
; Check if current executable is terminated already
;
While GetParentPID()
Debug "Wait until the exe is finished" ; show debug message while waiting
Delay(2000)
Wend
; make a backup of current executable (remove the last one)
;
DeleteFile(BakFile$) ; maybe no backup file (first update)
If RenameFile(ExeFile$, BakFile$)
If RenameFile(DownloadFile$, ExeFile$)
If Not bSilent
MessageRequester(#InfoCaption$, "Update successful", 0)
EndIf
RunProgram(ExeFile$, "", "")
EndIf
EndIf
ProcedureReturn 0
EndProcedure
End Main()
Re: Auto-update running app?
Posted: Fri Dec 20, 2024 6:00 pm
by PBJim
The way that I would approach this, is with two very simple provisos :
1. Downloaded updates are written to a separate file name called update.exe
2. Always run your application using a calling routine, let's call it caller.exe, which first looks for the directory presence of update.exe before executing RunProgram("application.exe"), and if it first finds update.exe, then it copies it over application.exe before running it.
If you want the automatic update to take effect while the application is running, rather than next time you run it, then you just close it and re-run caller.exe.
Re: Auto-update running app?
Posted: Fri Dec 20, 2024 7:05 pm
by skywalk
I also use the batch file approach.
It gets created on the fly when the user clicks "upgrade", "check for updates", etc.
Then the app saves and runs the batch file and quits.
I use a simple delay in the batch file to guarantee the app is really exited.
Re: [Solved] Auto-update running app?
Posted: Sat Dec 21, 2024 1:21 pm
by BarryG
Solved. PEBKAC error. See edited first post.

Re: [Solved] Auto-update running app?
Posted: Mon Dec 30, 2024 12:53 pm
by HeX0R
If you need no instant use of the new version, you could also RENAME your own running application, then download the new one with the old filename.
Next start you'll have the new version (and a corpse, which could be deleted when starting).
But all that would not work, if your app sits in Program Files Dir of course.
Re: [Solved] Auto-update running app?
Posted: Mon Dec 30, 2024 2:46 pm
by Little John
Why not download the original setup program for the new version?
Then in your program which is to be updated, just run
Code: Select all
RunProgram("<Path>/mysetup.exe")
End