'------------------------------------------------------------------------------ ' This is 'SelfUpdate.inc' v0.2 for PBWin9.0 '------------------------------------------------------------------------------ ' Before to #INCLUDE this file, define $VER and $SRC as is: ' $VER = "0.1" ' or "v0.1" ' $SRC = "http://mougino.free.fr/code/My Program/My Program.bas" ' Do not forget to add a ' Changelog ' section in your main .bas ' Finally call M_SELF_UPDATE at the beginning of your callback '------------------------------------------------------------------------------ '------------------------------------------------------------------------------ #IF NOT %DEF(%FN_EXISTS) %FN_EXISTS = -1 FUNCTION Exists(BYVAL fileOrFolder AS STRING) AS LONG LOCAL Dummy& Dummy& = GETATTR(fileOrFolder) FUNCTION = (ERRCLEAR = 0) END FUNCTION #ENDIF '------------------------------------------------------------------------------ '------------------------------------------------------------------------------ MACRO M_SELF_UPDATE STATIC m_tmr AS LONG IF CB.MSG = %WM_INITDIALOG THEN KILL ENVIRON$("TEMP") + "\" + EXE.NAME$ + "_updater.bat" m_tmr = SetTimer(CB.HNDL, 1512, 3000, BYVAL 0) ELSEIF CB.MSG = %WM_TIMER AND CB.WPARAM = 1512 THEN KillTimer CB.HNDL, m_tmr SELF_UPDATE_SUB CB.HNDL END IF END MACRO '------------------------------------------------------------------------------ '------------------------------------------------------------------------------ SUB SELF_UPDATE_SUB(BYVAL hDlg AS DWORD) LOCAL i, j, ii, jj, ff AS LONG LOCAL buf, e, r, s, t, x AS STRING ' Force update when program is called with parameter "-update" or "/update" IF LCASE$(TRIM$(COMMAND$)) = "-update" _ OR LCASE$(TRIM$(COMMAND$)) = "/update" THEN KILL ENVIRON$("TEMP") + "\" + EXE.NAME$ + ".noupd" END IF ' Skip update if user previously answered "Do not ask again" IF EXISTS( ENVIRON$("TEMP") + "\" _ + EXE.NAME$ + ".noupd" ) THEN EXIT SUB ' Download latest source, exit if download failed s = $SRC t = s : REPLACE "/" WITH "\" IN t t = PATHNAME$(NAMEX, t) t = ENVIRON$("TEMP") + "\" + t KILL t ' Use workaround to prevent cache issue RANDOMIZE TIMER s += "?fakeVar="+FORMAT$(RND(1,100000000)) i = URLDownloadToFile(NOTHING, BYVAL STRPTR(s), _ BYVAL STRPTR(t), BYVAL 0&, NOTHING) IF i <> %ERROR_SUCCESS THEN EXIT SUB ' Bufferize latest source + delete local copy ff = FREEFILE OPEN t FOR BINARY AS #ff GET$ #ff, LOF(#ff), buf REPLACE $CRLF WITH $LF IN buf REPLACE $LF WITH $CR IN buf CLOSE #ff KILL t ' Parse source for target exe j = INSTR(UCASE$(buf), "#COMPILE EXE") IF j > 0 THEN jj = INSTR(j, buf, $CR) IF jj > 0 THEN e = MID$(buf, j, jj-j-1) j = INSTR(e, $DQ) IF j > 0 THEN e = MID$(e, j+1) e = TRIM$(e) e = RTRIM$(e, $DQ) x = e END IF END IF END IF IF x = "" THEN x = PATHNAME$(NAME, t) + ".exe" ' Parse source for current version (hopefuly in the changelog) i = INSTR(buf, $CR + "' " + $VER) ' 0.1 IF i = 0 THEN i = INSTR(buf, $CR + "' v" + $VER) ' v0.1 IF i = 0 THEN i = INSTR(buf, $CR + "' - v" + $VER) ' - v0.1 IF i = 0 THEN i = INSTR(buf, $CR + "' - " + $VER) ' - 0.1 IF i = 0 THEN EXIT SUB buf = LEFT$(buf, i-1) ' Isolate changelog section i = INSTR(-1, LCASE$(buf), "changelog") IF i = 0 THEN i = INSTR(-1, buf, $CR + "'--") IF i = 0 THEN i = INSTR(-1, buf, $CR + "' --") IF i = 0 THEN EXIT SUB i = INSTR(i+1, buf, $CR) IF i = 0 THEN EXIT SUB ' should not happen, but safety first buf = MID$(buf, i) ' Remove all liner sections ('---- or ' ----) i = INSTR(buf, $CR + "'--") WHILE i > 0 j = INSTR(i, buf, "--" + $CR) e = TRIM$(MID$(buf, i+1, j-i-1)) IF TRIM$(REMOVE$(e, "-")) = "'" THEN buf = LEFT$(buf, i-1) + MID$(buf, j+2) i = INSTR(buf, $CR + "'--") WEND i = INSTR(buf, $CR + "' --") WHILE i > 0 j = INSTR(i, buf, "--" + $CR) e = TRIM$(MID$(buf, i+1, j-i-1)) IF TRIM$(REMOVE$(e, "-")) = "'" THEN buf = LEFT$(buf, i-1) + MID$(buf, j+2) i = INSTR(buf, $CR + "' --") WEND ' If we're already using the latest version, do nothing IF TRIM$(REMOVE$(buf, "-"), $CR) = "'" THEN EXIT SUB IF TRIM$(REMOVE$(buf, "-"), $CR) = "' " THEN EXIT SUB ' New version available! Propose it to the user REPLACE $CR + "'" WITH $CR IN buf REPLACE "[x]" WITH "[X]" IN buf REPLACE " [X]" WITH " o" IN buf REPLACE " [X]" WITH " -" IN buf t = "A new version is available!" + $CR + $CR t += TRIM$(buf, $CR) + $CR + $CR t += "Update now?" i = MyMsgBox(hDlg, t, "", %MB_ICONQUESTION, "&Yes;&No;&Do not ask again") ' User selected "Update? > Do not ask again" IF i = 3 THEN ff = FREEFILE OPEN ENVIRON$("TEMP") + "\" + EXE.NAME$ + ".noupd" FOR BINARY AS #ff PUT$ #ff, $VER + ": user clicked ""Do not ask again"" in the Update box" + $CR PUT$ #ff, "To allow updates again: delete this file, or call the program with the ""/update"" parameter" + $CR CLOSE #ff EXIT SUB END IF ' User selected "Update? > No" IF i = 2 THEN EXIT SUB ' Next is when user chose to update :) ' Download latest executable i = INSTR(-1, s, "/") IF i = 0 THEN EXIT SUB ' should not happen, but safety first s = LEFT$(s, i) + x t = ENVIRON$("TEMP") + "\" + x ' Use workaround to prevent cache issue s += "?fakeVar="+FORMAT$(RND(1,100000000)) i = URLDownloadToFile(NOTHING, BYVAL STRPTR(s), _ BYVAL STRPTR(t), BYVAL 0&, NOTHING) IF i <> %ERROR_SUCCESS THEN MyMsgBox hDlg, "Error downloading " + x + $CR + $CR _ + "Check your connection and try again.", "", %MB_ICONWARNING EXIT SUB END IF ' Create batch file to replace old exe and restart new exe ff = FREEFILE OPEN ENVIRON$("TEMP") + "\" + EXE.NAME$ + "_updater.bat" FOR OUTPUT AS #ff PRINT #ff, "@Echo Off" PRINT #ff, "Echo Updating " + x + "... Please be patient" PRINT #ff, "TimeOut 2 > nul" PRINT #ff, "Del " + $DQ + EXE.FULL$ + $DQ PRINT #ff, "Copy " + $DQ + t + $DQ + " " + $DQ + EXE.FULL$ + $DQ + " > nul" PRINT #ff, "Del " + $DQ + t + $DQ PRINT #ff, "TimeOut 1 > nul" PRINT #ff, "Start " + $DQ+$DQ + " " + $DQ + EXE.FULL$ + $DQ CLOSE #ff ff = SHELL(ENVIRON$("TEMP") + "\" + EXE.NAME$ + "_updater.bat", 1) ExitProcess(12345) ' Close ourselves END SUB '------------------------------------------------------------------------------