home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2011 August / maximum-cd-2011-08.iso / DiscContents / AutoHotkey110000_Install.exe / Update.ahk < prev   
Encoding:
Text File  |  2011-01-18  |  11.8 KB  |  346 lines

  1. /*
  2. [AutoHotkey Updater]
  3. version = 0.001
  4. */
  5.  
  6. KeepBackup = 0 ; Set to 1 to keep old EXE as <filename>.<version>.bak.
  7. SelfUpdate = 1 ; Set to 0 to prevent the script from checking for updates to itself.
  8.  
  9. ; Alternate update sources should use the following structure:
  10. ;   %UpdateURL%/Update.ahk  -- [optional] newer version of this script
  11. ;   %UpdateURL%/version.txt -- text file: ONLY a version number
  12. ;   %UpdateURL_bin%         -- zip file: AutoHotkey.exe and AutoHotkeySC.bin;
  13. ;                       {suffix} is replaced with "w", "a" or "w64" as appropriate.
  14. ;   %UpdateURL_chm%         -- zip file: AutoHotkey.chm
  15. ;   %UpdateURL_a2e%         -- zip file: Ahk2Exe.exe
  16. UpdateURL = http://www.autohotkey.net/~Lexikos/AutoHotkey_L
  17. UpdateURL_bin = %UpdateURL%/AutoHotkey_L{suffix}.zip
  18. UpdateURL_chm = %UpdateURL%/AutoHotkey_L_Help.zip
  19. UpdateURL_a2e = %UpdateURL%/Ahk2Exe_L.zip
  20.  
  21. TempDir = %A_Temp%\AhkUpdate%A_Now%
  22.  
  23.  
  24. #NoEnv
  25. #Include *i %A_ScriptDir%\UpdateDebug.ahk
  26.  
  27. if 0 > 0
  28. {
  29.     if IsFunc("_" %True%) ; Recursive call, used to swap exes or elevate the process.
  30.     {
  31.         prms := Object()
  32.         Loop %0%
  33.             prms.Insert(%A_Index%)
  34.         func := prms.Remove(1), _%func%(prms*)
  35.         ExitApp
  36.     }
  37.     else if 1 = SuppressUpToDate ; Suppress "AutoHotkey is up to date" message.
  38.         SuppressUpToDate := true
  39. }
  40.  
  41. if !A_IsCompiled && SelfUpdate
  42. {
  43.     ; First, check for a newer version of this script.
  44.     URLDownloadToFile %UpdateURL%/Update.ahk, %A_Temp%\Update.ahk
  45.     IniRead rver, %A_Temp%\Update.ahk, AutoHotkey Updater, version, %A_Space%
  46.     IniRead lver, %A_ScriptFullPath%,  AutoHotkey Updater, version, %A_Space%
  47.     if (lver < rver)
  48.     {
  49.         MsgBox 3, AutoHotkey Updater,
  50.         (LTrim Join`s
  51.         A newer version of this script is available.  It is recommended
  52.         that you use the updated version of the script to install further
  53.         updates.  *** WARNING: If you click yes, any modifications you
  54.         have made to this script will be lost. ***
  55.         `n`nUse the updated script?
  56.         )
  57.         ifMsgBox Yes
  58.         {
  59.             _SelfUpdate(A_Temp "\Update.ahk")
  60.             ExitApp
  61.         }
  62.         ifMsgBox Cancel
  63.         {
  64.             FileDelete %A_Temp%\Update.ahk
  65.             ExitApp
  66.         }
  67.     }
  68.     FileDelete %A_Temp%\Update.ahk
  69. }
  70.  
  71. if A_OSVersion in WIN_2000,WIN_NT4,WIN_95,WIN_98,WIN_ME ; Only WIN_2000 should actually be possible.
  72. {
  73.     MsgBox 16, AutoHotkey Updater, Windows XP or later is required.
  74.     ExitApp
  75. }
  76.  
  77. FileCreateDir %TempDir%
  78.  
  79. ; Retrieve latest version number.
  80. URLDownloadToFile %UpdateURL%/version.txt, %TempDir%\version.txt
  81. FileRead version, %TempDir%\version.txt
  82.  
  83. if (version <= A_AhkVersion)
  84. {
  85.     if !SuppressUpToDate
  86.         MsgBox 64, AutoHotkey Updater, AutoHotkey is up to date.
  87.     FileRemoveDir %TempDir%
  88.     ExitApp
  89. }
  90.  
  91. MsgBox 68, AutoHotkey Update Available,
  92. (
  93. An update for AutoHotkey is available.
  94.  
  95. Installed version:`t%A_AhkVersion%
  96. Latest version:`t%version%
  97.  
  98. Would you like to install it now?
  99. )
  100. ifMsgBox No
  101. {
  102.     FileRemoveDir %TempDir%
  103.     ExitApp
  104. }
  105.  
  106. ; Determine the appropriate package.
  107. if A_PtrSize = 8
  108.     suffix = w64 ; Above already verified A_IsUnicode is true in this case.
  109. else if A_IsUnicode
  110.     suffix = w
  111. else
  112.     suffix = a
  113. StringReplace UpdateURL_bin, UpdateURL_bin, {suffix}, %suffix%
  114.  
  115. ; Download binaries.
  116. errors     := !Download(UpdateURL_bin, TempDir "\bin.zip")
  117. ; Download help file.
  118. ifExist %A_AhkPath%\..\AutoHotkey.chm
  119.     errors += !Download(UpdateURL_chm, TempDir "\help.zip")
  120. ; Download compiler.
  121. ifExist %A_AhkPath%\..\Compiler\Ahk2Exe.exe
  122.     errors += !Download(UpdateURL_a2e, TempDir "\compiler.zip")
  123.  
  124. if errors
  125. {
  126.     MsgBox 16, AutoHotkey Updater, Update failed: download error.
  127.     ifExist %TempDir%\*.zip
  128.         Run %TempDir% ; Allow user to extract files manually.
  129.     else
  130.         FileRemoveDir %TempDir%, 1
  131.     ExitApp
  132. }
  133.  
  134. ; Extract binaries, help file and compiler into temp dir.
  135. oShell := ComObjCreate("Shell.Application")
  136. oDir := oShell.NameSpace(TempDir)
  137. Loop %TempDir%\*.zip
  138. {
  139.     oZip := oShell.NameSpace(A_LoopFileFullPath)
  140.     if !(oZip && oDir)
  141.     {
  142.         MsgBox 16, AutoHotkey Updater, Update failed: unzip error.
  143.         Run %TempDir%
  144.         ExitApp
  145.     }
  146.     oDir.CopyHere(oZip.Items, 4)
  147. }
  148. oShell := oDir := oZip := ""
  149.  
  150. _Install(TempDir)
  151.  
  152. ExitApp
  153.  
  154.  
  155. _Install(source_dir)
  156. {
  157.     ; Get list of scripts running on the old executable. This will apparently
  158.     ; work even after the file itself is renamed, but better be on the safe side.
  159.     Process Exist
  160.     my_pid := ErrorLevel
  161.     ComObjError(0) ; ComObjGet("winmgmts:") fails on Guest account.
  162.     for proc in ComObjGet("winmgmts:").InstancesOf("Win32_Process")
  163.         if (proc.ExecutablePath = A_AhkPath && proc.ProcessId != my_pid)
  164.             pids .= proc.ProcessId ","
  165.     pids := SubStr(pids,1,-1)
  166.  
  167.     ; Rename current executable to allow another to take its place.
  168.     backup_path = %A_AhkPath%.%A_AhkVersion%.bak
  169.     FileMove %A_AhkPath%, %backup_path%, 1
  170.     if ErrorLevel
  171.     {
  172.         if !A_IsAdmin
  173.         {   ; Try again as admin.
  174.             if Elevate("Install", source_dir)
  175.                 ExitApp
  176.         }
  177.         MsgBox 16, AutoHotkey Updater, Update failed: unable to rename old file.  Error %err%.`n`nSource: %A_AhkPath%`nDestination: %backup_path%
  178.         Run %source_dir%
  179.         ExitApp
  180.     }
  181.  
  182.     ; Move new files into place -- FileCopy is used because otherwise the files would still have permissions inherited from %A_Temp%.
  183.     FileCopy %source_dir%\AutoHotkey.exe, %A_AhkPath%
  184.     if ErrorLevel
  185.     {
  186.         MsgBox 16, AutoHotkey Updater, Update failed: unable to move AutoHotkey.exe to "%A_AhkPath%".
  187.         Run %source_dir%
  188.         ExitApp
  189.     }
  190.     FileCopy %source_dir%\AutoHotkeySC.bin, %A_AhkPath%\..\Compiler\AutoHotkeySC.bin, 1 ; Should simply fail if no Compiler dir.
  191.     FileCopy %source_dir%\Ahk2Exe.exe, %A_AhkPath%\..\Compiler\Ahk2Exe.exe, 1 ; If it exists.
  192.     FileCopy %source_dir%\AutoHotkey.chm, %A_AhkPath%\..\AutoHotkey.chm, 1 ; If it exists.
  193.  
  194.     ; Clean up. :)
  195.     FileRemoveDir %source_dir%, 1
  196.     
  197.     ; Relaunch using new executable -- see _TidyUp() below.
  198.     Run "%A_AhkPath%" "%A_ScriptFullPath%" TidyUp "%my_pid%" "%backup_path%" "%pids%"
  199. }
  200.  
  201.  
  202. _TidyUp(parent_pid, delete_me, other_pids="")
  203. {
  204.     ; Update registry -- this is done here so can be positive the version number is accurate.
  205.     RegRead InstallDir, HKLM, SOFTWARE\AutoHotkey, InstallDir
  206.     if (A_AhkPath = InstallDir "\AutoHotkey.exe")
  207.     {
  208.         RegWrite REG_SZ, HKLM, SOFTWARE\AutoHotkey, Version, %A_AhkVersion%
  209.         RegWrite REG_SZ, HKLM, SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\AutoHotkey, DisplayName, AutoHotkey %A_AhkVersion%
  210.         RegWrite REG_SZ, HKLM, SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\AutoHotkey, DisplayVersion, %A_AhkVersion%
  211.     }
  212.     
  213.     Process WaitClose, %parent_pid% ; Wait for previous instance of this script to close.
  214.     DetectHiddenWindows On
  215.     scripts := Object()
  216.     Loop Parse, other_pids, `,
  217.     {
  218.         ifWinExist ahk_pid %A_LoopField% ahk_class AutoHotkey
  219.         {
  220.             WinGetTitle script
  221.             script := RegExReplace(script, " - [^-]*$")
  222.             scripts[WinExist()] := script
  223.             script_filenames .= script "`n"
  224.         }
  225.     }
  226.     SplitPath A_AhkPath, exe
  227.     SplitPath delete_me, bak
  228.     if scripts.MaxIndex() != ""
  229.     {
  230.         MsgBox 4, AutoHotkey Updater, The following scripts are still running:`n`n%script_filenames%`nWould you like to automatically reload them?
  231.         ifMsgBox Yes
  232.         {
  233.             failed := ""
  234.             while (id := scripts.MaxIndex()) ; Must be MAX rather than MIN, otherwise existing IDs will be invalidated by Remove().
  235.             {
  236.                 script := scripts.Remove(id)
  237.                 ifExist %script%
  238.                 {
  239.                     ; Triggering reload won't work in most cases since the version number
  240.                     ; in the window title has changed. Instead, forcibly start the script
  241.                     ; and automatically close the old one if the new one loaded okay.
  242.                     Run "%A_AhkPath%" /force "%script%",,, pid
  243.                     WinWait ahk_pid %pid%,, 1
  244.                     ; Above may have timed out or found a load-time error dialog.
  245.                     ; Check for the "ahk_class AutoHotkey" window specifically,
  246.                     ; since its presence indicates the script loaded okay.
  247.                     ifWinExist ahk_pid %pid% ahk_class AutoHotkey
  248.                         WinClose ahk_id %id%,, 0
  249.                 }
  250.                 ifWinExist ahk_id %id%
  251.                     failed .= script "`n"
  252.             }
  253.             if failed !=
  254.                 MsgBox 16, AutoHotkey Updater, One or more scripts were not successfully reloaded:`n`n%failed%
  255.         }
  256.     }
  257.  
  258.     global KeepBackup
  259.     if KeepBackup ; This is set at the top of the script, for configuration by a user.
  260.         ExitApp
  261.     ; Attempt to delete file. This will fail if any old scripts are still running.
  262.     FileDelete %delete_me%
  263.     ; If unsuccessful, attempt to schedule it for deletion. This will only work
  264.     ; for administrators. If a limiter user got this far in the installation,
  265.     ; they're probably working with a portable installation and won't want to
  266.     ; provide admin credentials just to schedule a file for deletion.
  267.     if ErrorLevel && !DllCall("MoveFileEx", "str", delete_me, "ptr", 0, "uint", 4) ; MOVEFILE_DELAY_UNTIL_REBOOT:=4
  268.         MsgBox 16, AutoHotkey Updater, Failed to delete old file "%bak%".
  269.     ExitApp
  270. }
  271.  
  272.  
  273. _SelfUpdate(source_path)
  274. {
  275.     ; Copy and Delete instead of Move so that file permissions are inherited correctly.
  276.     FileCopy %source_path%, %A_ScriptFullPath%, 1
  277.     if ErrorLevel
  278.     {
  279.         if !A_IsAdmin
  280.         {   ; Try again as admin.
  281.             if Elevate("SelfUpdate", source_path)
  282.                 ExitApp
  283.         }
  284.         MsgBox 16, AutoHotkey Updater, Script update failed.  Error %err%.
  285.         ExitApp
  286.     }
  287.     FileDelete %source_path%
  288.     Reload
  289. }
  290.  
  291.  
  292. Elevate(func, prms*)
  293. {
  294.     cmd := func
  295.     for i,prm in prms
  296.     {
  297.         StringReplace prm, prm, `", "", All
  298.         cmd .= " """ prm """"
  299.     }
  300.     if A_IsCompiled
  301.         exe := A_ScriptFullPath
  302.     else
  303.         exe := A_AhkPath, cmd := """" A_ScriptFullPath """ " cmd
  304.     return DllCall("shell32\ShellExecute", "ptr", 0, "str", "RunAs"
  305.                     , "str", exe, "str", cmd, "ptr", 0, "int", 1) > 32
  306. }
  307.  
  308.  
  309. D(debug_string)
  310. {
  311.     OutputDebug AhkUpdate: %debug_string%`n
  312.     FileAppend %debug_string%`n, *, CP0
  313. }
  314.  
  315.  
  316. ; Based on code by Sean and SKAN @ http://www.autohotkey.com/forum/viewtopic.php?p=184468#184468
  317. Download(url, file)
  318. {
  319.     static vt
  320.     if !VarSetCapacity(vt)
  321.     {
  322.         VarSetCapacity(vt, A_PtrSize*11), nPar := "31132253353"
  323.         Loop Parse, nPar
  324.             NumPut(RegisterCallback("DL_Progress", "F", A_LoopField, A_Index-1), vt, A_PtrSize*(A_Index-1))
  325.     }
  326.     global _cu
  327.     SplitPath file, dFile
  328.     SysGet m, MonitorWorkArea, 1
  329.     y := mBottom-52-2, x := mRight-330-2, VarSetCapacity(_cu, 100)
  330.     , DllCall("shlwapi\PathCompactPathEx", "str", _cu, "str", url, "uint", 50, "uint", 0)
  331.     Progress Hide CWFAFAF7 CT000020 CB445566 x%x% y%y% w330 h52 B1 FS8 WM700 WS700 FM8 ZH12 ZY3 C11,, %_cu%, AutoHotkeyProgress, Tahoma
  332.     WinSet Transparent, 192, AutoHotkeyProgress
  333.     re := DllCall("urlmon\URLDownloadToFile", "ptr", 0, "str", url, "str", file, "uint", 0, "ptr*", &vt)
  334.     Progress Off
  335.     return re=0 ? 1 : 0
  336. }
  337. DL_Progress( pthis, nP=0, nPMax=0, nSC=0, pST=0 )
  338. {
  339.     global _cu
  340.     if A_EventInfo = 6
  341.     {
  342.         Progress Show
  343.         Progress % P := 100*nP//nPMax, % "Downloading:     " Round(np/1024,1) " KB / " Round(npmax/1024) " KB    [ " P "`% ]", %_cu%
  344.     }
  345.     return 0
  346. }