File "SelfUpdate.inc"

Path: /linkmaker/inc/SelfUpdate.inc
File size: 6.89 KB
MIME-type:
Charset: utf-8

'------------------------------------------------------------------------------
' 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
'------------------------------------------------------------------------------