0% found this document useful (0 votes)
174 views35 pages

Installer

This document contains code for an AutoHotkey setup script. It initializes variables, checks for administrator privileges, determines the currently installed version, and initializes the GUI. The GUI uses an IE ActiveX control to display pages for installing/configuring AutoHotkey. It handles command line options, installs by default if run silently, and allows browsing to select an install directory.

Uploaded by

My Name
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
174 views35 pages

Installer

This document contains code for an AutoHotkey setup script. It initializes variables, checks for administrator privileges, determines the currently installed version, and initializes the GUI. The GUI uses an IE ActiveX control to display pages for installing/configuring AutoHotkey. It handles command line options, installs by default if run silently, and allows browsing to select an install directory.

Uploaded by

My Name
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 35

#NoEnv

#NoTrayIcon
; #Warn
#SingleInstance Off
try Menu Tray, Icon, appwiz.cpl, -1500if !A_IsAdmin && !%False%
{
if A_OSVersion not in WIN_2003,WIN_XP,WIN_2000
{
Run *RunAs "%A_AhkPath%" "%A_ScriptFullPath%",, UseErrorLevel
if !ErrorLevel
ExitApp
}
MsgBox 0x31, AutoHotkey Setup,
(LTrim Join`s
Setup is running as a limited user. If you continue, some problems
are likely to occur. It is strongly recommended that you run Setup
as an administrator.`n
`n
To continue anyway, click OK. Otherwise click Cancel.
)
IfMsgBox Cancel
ExitApp
}

SourceDir := A_ScriptDirSilentMode := false


SilentErrors := 0
AutoRestart := false

ProductName := "AutoHotkey"
ProductVersion := A_AhkVersion
ProductPublisher := "Lexikos"
ProductWebsite := "https://autohotkey.com/"

EnvGet ProgramW6432, ProgramW6432


DefaultPath := (ProgramW6432 ? ProgramW6432 : A_ProgramFiles) "\AutoHotkey"
DefaultType := A_Is64bitOS ? "x64" : "Unicode"
DefaultStartMenu := "AutoHotkey"
DefaultCompiler := true
DefaultDragDrop := true
DefaultToUTF8 := false
DefaultIsHostApp := false
DefaultUIAccess := false
AutoHotkeyKey := "SOFTWARE\AutoHotkey"
UninstallKey := "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\AutoHotkey"
FileTypeKey := "AutoHotkeyScript"

RegRead UACIsEnabled, HKLM,


SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System, EnableLUA

Menu Tray, MainWindow ; Enable debugging setup.exe.

if 1 = /exec ; For internal use


{
HandleExec(1)
ExitApp
}

DetermineVersion()
ConfigureMode := DefaultPath = A_ScriptDir

Loop %0%
if %A_Index% = /S
SilentMode := true
else if %A_Index% = /R
AutoRestart := true
else if %A_Index% = /U32
DefaultType = Unicode
else if %A_Index% in /U64,/x64
DefaultType = x64
else if %A_Index% in /A32,/ANSI
DefaultType = ANSI
else if %A_Index% in /uiAccess,/uiAccess=0,/uiAccess=1
DefaultUIAccess := SubStr(%A_Index%, 10) != "=0"
else if %A_Index% in /IsHostApp,/IsHostApp=0,/IsHostApp=1
DefaultIsHostApp := SubStr(%A_Index%, 11) != "=0"
else if InStr(%A_Index%, "/D=") = 1 {
if !RegExMatch(DllCall("GetCommandLine", "str"), "(?<!"")/D=\K[^""]*?(?=$|[
`t]+/)", DefaultPath)
DefaultPath := SubStr(%A_Index%, 4)
Loop %DefaultPath%, 2 ; Resolve relative path.
DefaultPath := A_LoopFileLongPath
SlashD := true
}
else if (%A_Index% = "/?") {
ViewHelp("/docs/Scripts.htm#install")
ExitApp
}
else if (%A_Index% = "/Uninstall") {
SilentMode := true
Uninstall()
ExitApp
}
else if (%A_Index% = "/E") {
Extract(SlashD ? DefaultPath : "")
ExitApp
}
else if (SubStr(%A_Index%,1,5) = "/Test")
TestMode := SubStr(%A_Index%,6)

if SilentMode {
QuickInstall()
ExitApp % SilentErrors
}

if WinExist("AutoHotkey Setup ahk_class AutoHotkeyGUI") {


MsgBox 0x30, AutoHotkey Setup, AutoHotkey Setup is already running!
WinActivate
ExitApp
}

OnExit GuiClose
Gui Margin, 0, 0
Gui +LastFound
try { ; Hide window title.
DllCall("UxTheme\SetWindowThemeAttribute", "ptr", WinExist()
, "int", 1, "int64*", (3<<32)|3, "int", 8)
}
OnMessage(0x100, "gui_KeyDown", 2)
try Gui Add, ActiveX, vwb w600 h400 hwndhwb, Shell.Explorer
try {
if !wb
throw Exception("Failed to create IE control")
if GetKeyState("Shift") || GetKeyState("Ctrl")
throw 1
SetWBClientSite()
InitUI()
}
catch excpt {
if ConfigureMode {
MsgBox 0x10, AutoHotkey Setup, Setup failed to initialize its user
interface and will now exit.
ExitApp
}
message := IsObject(excpt)
? "Setup encountered an error.`n"
. " Specifically: " excpt.Message
: "Setup is in troubleshooting mode (you're holding Ctrl or Shift)."
type := DefaultType="ANSI" ? "ANSI 32-bit" : "Unicode "
(DefaultType="x64"?"64":"32") "-bit"
MsgBox 0x33, AutoHotkey Setup,
(
%message%

Do you want to install with default options?


%ProductName% v%ProductVersion% (%type%)
%DefaultPath%

Click Yes to install.


Click No to copy setup files to a directory of your choosing.
Click Cancel to exit.
)
IfMsgBox Yes
{
QuickInstall()
MsgBox 0, AutoHotkey Setup, Installation complete.
}
else IfMsgBox No
Extract()
ExitApp
}
Gui Show,, AutoHotkey Setup
Gui +OwnDialogs
WinWaitClose ; Let +OwnDialogs apply to threadless callbacks.
return

GuiEscape:
Gui +OwnDialogs
MsgBox 0x2034, AutoHotkey Setup, Are you sure you want to exit setup?
IfMsgBox No
return
GuiClose:
Gui Destroy
OnExit
ExitApp

DetermineVersion() {
global
local url, v
; This first section has two purposes:
; 1) Determine the location of any current installation.
; 2) Determine which view of the registry it was installed into
; (only applicable if the OS is 64-bit).
CurrentRegView := ""
Loop % (A_Is64bitOS ? 2 : 1) {
SetRegView % 32*A_Index
RegRead CurrentPath, HKLM, %AutoHotkeyKey%, InstallDir
if !ErrorLevel {
CurrentRegView := A_RegView
break
}
}
if ErrorLevel {
CurrentName := ""
CurrentVersion := ""
CurrentType := ""
CurrentPath := ""
CurrentStartMenu := ""
return
}
RegRead CurrentVersion, HKLM, %AutoHotkeyKey%, Version
RegRead CurrentStartMenu, HKLM, %AutoHotkeyKey%, StartMenuFolder
RegRead url, HKLM, %UninstallKey%, URLInfoAbout
; Identify by URL since uninstaller display name is the same:
if (url = "http://www.autohotkey.net/~Lexikos/AutoHotkey_L/"
|| url = "http://l.autohotkey.net/")
CurrentName := "AutoHotkey_L"
else
CurrentName := "AutoHotkey"
; Identify which build is installed/set as default:
FileAppend ExitApp `% (A_IsUnicode=1) << 8 | (A_PtrSize=8) << 9, %A_Temp
%\VersionTest.ahk
RunWait %CurrentPath%\AutoHotkey.exe "%A_Temp%\VersionTest.ahk",, UseErrorLevel
if ErrorLevel = 0x300
CurrentType := "x64"
else if ErrorLevel = 0x100
CurrentType := "Unicode"
else if ErrorLevel = 0
CurrentType := "ANSI"
else
CurrentType := ""
FileDelete %A_Temp%\VersionTest.ahk
; Set some default parameter based on current installation:
if CurrentType
DefaultType := CurrentType
DefaultPath := CurrentPath
DefaultStartMenu := CurrentStartMenu
DefaultCompiler := FileExist(CurrentPath "\Compiler\Ahk2Exe.exe") != ""
RegRead v, HKCR, %FileTypeKey%\ShellEx\DropHandler
DefaultDragDrop := ErrorLevel = 0
RegRead v, HKCR, Applications\AutoHotkey.exe, IsHostApp
DefaultIsHostApp := !ErrorLevel
RegRead v, HKCR, %FileTypeKey%\Shell\uiAccess\Command
DefaultUIAccess := !ErrorLevel && UACIsEnabled
RegRead v, HKCR, %FileTypeKey%\Shell\Open\Command
DefaultToUTF8 := InStr(v, " /CP65001 ") != 0
}

InitUI() {
local w gosub DefineUI
wb.Silent := true
wb.Navigate("about:<!DOCTYPE HTML><meta http-equiv='x-ua-compatible'
content='IE=Edge'>")
while wb.ReadyState != 4 {
Sleep 10
if (A_TickCount-initTime > 2000)
throw 1
}
wb.Document.open()
wb.Document.write(html)
wb.Document.close() w := wb.Document.parentWindow
if !w || !w.initOptions
throw 1
w.AHK := Func("JS_AHK")
if (!CurrentType && A_ScriptDir != DefaultPath)
CurrentName := "" ; Avoid showing the Reinstall option since we don't know
which version it was.
w.initOptions(CurrentName, CurrentVersion, CurrentType
, ProductVersion, DefaultPath, DefaultStartMenu
, DefaultType, A_Is64bitOS = 1)
w.configureMode := ConfigureMode
w.document.body.className := ConfigureMode ? "config-mode" : ""
if ConfigureMode {
w.installdir.disabled := true
w.installdir_browse.disabled := true
w.nav_install.innerText := "apply"
w.install_button.innerText := "Apply"
w.opt1.onclick := ""
w.opt1.removeAttribute("href")
w.opt1.firstChild.innerText := "Checking for updates..."
}
w.installcompiler.checked := DefaultCompiler
w.enabledragdrop.checked := DefaultDragDrop
w.separatebuttons.checked := DefaultIsHostApp
w.enableuiaccess.checked := DefaultUIAccess && IsTrustedLocation(DefaultPath)
; w.defaulttoutf8.checked := DefaultToUTF8
if !A_Is64bitOS
w.it_x64.style.display := "None"
if A_OSVersion in WIN_2000,WIN_2003,WIN_XP,WIN_VISTA ; i.e. not WIN_7, WIN_8 or
a future OS.
w.separatebuttons.parentNode.style.display := "none"
if !UACIsEnabled
w.enableuiaccess.parentNode.style.display := "none"
else {
w.enableuiaccess.onchange := Func("enableuiaccess_onchange")
w.installdir.onchange := Func("installdir_onchange")
}
w.switchPage("start")
w.document.body.focus()
; Scale UI by screen DPI. My testing showed that Vista with IE7 or IE9
; did not scale by default, but Win8.1 with IE10 did. The scaling being
; done by the control itself = deviceDPI / logicalDPI.
logicalDPI := w.screen.logicalXDPI, deviceDPI := w.screen.deviceXDPI
if (A_ScreenDPI != 96)
w.document.body.style.zoom := A_ScreenDPI/96 * (logicalDPI/deviceDPI)
if ConfigureMode
CheckForUpdates()
}

CheckForUpdates() {
local w := getWindow(), latestVersion := ""
try {
whr := ComObjCreate("WinHttp.WinHttpRequest.5.1")
whr.Open("GET", "https://autohotkey.com/download/1.1/version.txt", true)
whr.Send()
whr.WaitForResponse()
latestVersion := whr.responseText
}
if RegExMatch(latestVersion, "^(\d+\.){3}\d+") {
if (latestVersion = ProductVersion)
w.opt1.firstChild.innerText := "Reinstall (download required)"
else
w.opt1.firstChild.innerText := "Download v" latestVersion
w.opt1.href := "#"
w.opt1.onclick := Func("DownloadAHK")
} else
w.opt1.innerText := "An error occurred while checking for updates."
}

/* Fix keyboard shortcuts in WebBrowser control.


*/

gui_KeyDown(wParam, lParam, nMsg, hWnd) {


global wb
if (Chr(wParam) ~= "[A-Z]" || wParam = 0x74) ; Disable Ctrl+O/L/F/N and F5.
return
Gui +OwnDialogs ; For threadless callbacks which interrupt this.
pipa := ComObjQuery(wb, "{00000117-0000-0000-C000-000000000046}")
VarSetCapacity(kMsg, 48), NumPut(A_GuiY, NumPut(A_GuiX
, NumPut(A_EventInfo, NumPut(lParam, NumPut(wParam
, NumPut(nMsg, NumPut(hWnd, kMsg)))), "uint"), "int"), "int")
Loop 2
r := DllCall(NumGet(NumGet(1*pipa)+5*A_PtrSize), "ptr", pipa, "ptr", &kMsg)
; Loop to work around an odd tabbing issue (it's as if there
; is a non-existent element at the end of the tab order).
until wParam != 9 || wb.Document.activeElement != ""
ObjRelease(pipa)
if r = 0 ; S_OK: the message was translated to an accelerator.
return 0
}

/* javascript:AHK('Func') --> Func()


*/

JS_AHK(func, prms*) {
global wb
; Stop navigation prior to calling the function, in case it uses Exit.
wb.Stop(), %func%(prms*)
}

/* Complex workaround to override "Active scripting" setting


* and ensure scripts can run within the WebBrowser control.
*/

global WBClientSite

SetWBClientSite()
{
interfaces := {
(Join,
IOleClientSite: [0,3,1,0,1,0]
IServiceProvider: [3]
IInternetSecurityManager: [1,1,3,4,8,7,3,3]
)}
unkQI := RegisterCallback("WBClientSite_QI", "Fast")
unkAddRef := RegisterCallback("WBClientSite_AddRef", "Fast")
unkRelease := RegisterCallback("WBClientSite_Release", "Fast")
WBClientSite := {_buffers: bufs := {}}, bufn := 0,
for name, prms in interfaces
{
bufn += 1
bufs.SetCapacity(bufn, (4 + prms.MaxIndex()) * A_PtrSize)
buf := bufs.GetAddress(bufn)
NumPut(unkQI, buf + 1*A_PtrSize)
NumPut(unkAddRef, buf + 2*A_PtrSize)
NumPut(unkRelease, buf + 3*A_PtrSize)
for i, prmc in prms
NumPut(RegisterCallback("WBClientSite_" name, "Fast", prmc+1, i), buf +
(3+i)*A_PtrSize)
NumPut(buf + A_PtrSize, buf + 0)
WBClientSite[name] := buf
}
global wb
if pOleObject := ComObjQuery(wb, "{00000112-0000-0000-C000-000000000046}")
{ ; IOleObject::SetClientSite
DllCall(NumGet(NumGet(pOleObject+0)+3*A_PtrSize), "ptr"
, pOleObject, "ptr", WBClientSite.IOleClientSite, "uint")
ObjRelease(pOleObject)
}
}

WBClientSite_QI(p, piid, ppvObject)


{
static IID_IUnknown := "{00000000-0000-0000-C000-000000000046}"
static IID_IOleClientSite := "{00000118-0000-0000-C000-000000000046}"
static IID_IServiceProvider := "{6d5140c1-7436-11ce-8034-00aa006009fa}"
iid := _String4GUID(piid)
if (iid = IID_IOleClientSite || iid = IID_IUnknown)
{
NumPut(WBClientSite.IOleClientSite, ppvObject+0)
return 0 ; S_OK
}
if (iid = IID_IServiceProvider)
{
NumPut(WBClientSite.IServiceProvider, ppvObject+0)
return 0 ; S_OK
}
NumPut(0, ppvObject+0)
return 0x80004002 ; E_NOINTERFACE
}
WBClientSite_AddRef(p)
{
return 1
}

WBClientSite_Release(p)
{
return 1
}

WBClientSite_IOleClientSite(p, p1="", p2="", p3="")


{
if (A_EventInfo = 3) ; GetContainer
{
NumPut(0, p1+0) ; *ppContainer := NULL
return 0x80004002 ; E_NOINTERFACE
}
return 0x80004001 ; E_NOTIMPL
}

WBClientSite_IServiceProvider(p, pguidService, piid, ppvObject)


{
static IID_IUnknown := "{00000000-0000-0000-C000-000000000046}"
static IID_IInternetSecurityManager := "{79eac9ee-baf9-11ce-8c82-00aa004ba90b}"
if (_String4GUID(pguidService) = IID_IInternetSecurityManager)
{
iid := _String4GUID(piid)
if (iid = IID_IInternetSecurityManager || iid = IID_IUnknown)
{
NumPut(WBClientSite.IInternetSecurityManager, ppvObject+0)
return 0 ; S_OK
}
NumPut(0, ppvObject+0)
return 0x80004002 ; E_NOINTERFACE
}
NumPut(0, ppvObject+0)
return 0x80004001 ; E_NOTIMPL
}

WBClientSite_IInternetSecurityManager(p, p1="", p2="", p3="", p4="", p5="", p6="",


p7="", p8="")
{
if (A_EventInfo = 5) ; ProcessUrlAction
{
if (p2 = 0x1400) ; dwAction = URLACTION_SCRIPT_RUN
{
NumPut(0, p3+0) ; *pPolicy := URLPOLICY_ALLOW
return 0 ; S_OK
}
}
return 0x800C0011 ; INET_E_DEFAULT_ACTION
}

_String4GUID(pGUID)
{
VarSetCapacity(String,38*2)
DllCall("ole32\StringFromGUID2", "ptr", pGUID, "str", String, "int", 39)
Return String
}

/* Utility Functions
*/

getWindow() {
global wb
return wb.document.parentWindow
}

ErrorExit(errMsg) {
global
if !SilentMode
MsgBox 0x2010, AutoHotkey Setup, %errMsg%
ExitApp 1
}

CloseScriptsEtc(installdir, actionToContinue) {
titles := ""
DetectHiddenWindows On
close := [], reopen := []
WinGet w, List, ahk_class AutoHotkey
Loop % w {
; Exclude the install script.
if (w%A_Index% = A_ScriptHwnd)
continue
; Determine if the script actually needs to be terminated.
WinGet exe_path, ProcessPath, % "ahk_id " w%A_Index%
if (exe_path != "") {
; Exclude external executables.
if InStr(exe_path, installdir "\") != 1
continue
; The main purpose of this next check is to avoid closing
; SciTE4AutoHotkey's toolbar, but also may be helpful for
; other situations.
exe := SubStr(exe_path, StrLen(installdir) + 2)
if !RegExMatch(exe, "i)^(AutoHotkey((A32|U32|U64)(_UIA)?)?\.exe|
Compiler\\Ahk2Exe.exe)$")
continue
}
; Append script path to the list.
WinGetTitle title, % "ahk_id " w%A_Index%
title := RegExReplace(title, " - AutoHotkey v.*")
titles .= " - " title "`n"
close.Push(w%A_Index%)
if FileExist(title)
reopen.Push({path: title, exe: exe_path})
}
if (titles != "") {
global SilentMode, installInPlace
if !SilentMode {
static button_retry, button_mode
button_retry := 3
if (actionToContinue = "installation") {
help_text =
(LTrim
Click Reload to automatically reload the scripts later.
Click Close All to just close the scripts and continue.
)
button_mode := 3
} else {
help_text =
(LTrim
Click Close All to close all scripts and continue the
%actionToContinue%.
)
button_mode := 1
}
SetTimer CloseScriptsEtc_Buttons, -5
MsgBox % 0x2030|button_mode, AutoHotkey Setup,
(LTrim
Setup needs to close the following script(s):
`n%titles%
%help_text%
)
IfMsgBox Cancel
Exit
IfMsgBox Yes
global AutoRestart := true
}
; Close script windows (typically causing them to exit).
Loop % close.MaxIndex()
{
WinClose % "ahk_id " close[A_Index]
WinWaitClose % "ahk_id " close[A_Index],, 1
}
}
; Close all help file and Window Spy windows automatically:
GroupAdd autoclosegroup, AutoHotkey_L Help ahk_class HH Parent
GroupAdd autoclosegroup, AutoHotkey Help ahk_class HH Parent
GroupAdd autoclosegroup, Active Window Info ahk_exe %installdir%\AU3_Spy.exe
; Also close the old Ahk2Exe (but the new one is a script, so it
; was already handled by the section above):
GroupAdd autoclosegroup, Ahk2Exe v ahk_exe %installdir%\Compiler\Ahk2Exe.exe
WinClose ahk_group autoclosegroup
return reopen

CloseScriptsEtc_Buttons:
Critical
if !WinExist("ahk_class #32770 ahk_pid " DllCall("GetCurrentProcessId")) {
if (button_retry--)
SetTimer,, -5
return
}
if (button_mode = 1)
ControlSetText Button1, Close &All
else {
ControlSetText Button1, &Reload
ControlSetText Button2, Close &All
}
return
}

ReopenScripts(scripts) {
global AutoRestart
if !AutoRestart || !scripts || !scripts.MaxIndex()
return
failed := ""
for i, script in scripts {
workdir := script.path
SplitPath workdir,, workdir
try
script.exe ? Run_(script.exe, """" script.path """", workdir)
: Run_("""" script.path """",, workdir)
catch
failed .= "`n" script
}
if (failed != "" && !SilentMode)
MsgBox 0x2010, AutoHotkey Setup, Failed to restart the following scripts:`n
%failed%
}

GetErrorMessage(error_code="") {
VarSetCapacity(buf, 1024) ; Probably won't exceed 1024 chars.
if DllCall("FormatMessage", "uint", 0x1200, "ptr", 0, "int", error_code!=""
? error_code : A_LastError, "uint", 1024, "str", buf, "uint", 1024,
"ptr", 0)
return buf
}

switchPage(page) {
global
if !SilentMode
getWindow().switchPage(page)
}

UpdateStatus(status) {
; ToolTip % status
; if !SilentMode
; getWindow().install_status.innerText := status
}

ShellRun(prms*)
{
shellWindows := ComObjCreate("Shell.Application").Windows
VarSetCapacity(_hwnd, 4, 0)
desktop := shellWindows.FindWindowSW(0, "", 8, ComObj(0x4003, &_hwnd), 1)
if ptlb := ComObjQuery(desktop
, "{4C96BE40-915C-11CF-99D3-00AA004AE837}" ; SID_STopLevelBrowser
, "{000214E2-0000-0000-C000-000000000046}") ; IID_IShellBrowser
{
if DllCall(NumGet(NumGet(ptlb+0)+15*A_PtrSize), "ptr", ptlb, "ptr*",
psv:=0) = 0
{
VarSetCapacity(IID_IDispatch, 16)
NumPut(0x46000000000000C0, NumPut(0x20400, IID_IDispatch, "int64"),
"int64")
DllCall(NumGet(NumGet(psv+0)+15*A_PtrSize), "ptr", psv
, "uint", 0, "ptr", &IID_IDispatch, "ptr*", pdisp:=0)
shell := ComObj(9,pdisp,1).Application
shell.ShellExecute(prms*)
ObjRelease(psv)
}
ObjRelease(ptlb)
}
}
Run_(target, args:="", workdir:="") {
try
ShellRun(target, args, workdir)
catch e
Run % args="" ? target : target " " args, % workdir
}

/* Utility Functions invoked by the UI


*/

Customize() {
local w := getWindow()
if !ConfigureMode
w.document.body.className := "custom-mode"
w.switchPage("version")
}

SelectFolder(id, prompt="", root="::{20d04fe0-3aea-1069-a2d8-08002b30309d}") {


global wb
if !(field := wb.document.getElementById(id))
return
Gui +OwnDialogs
FileSelectFolder path
, % root " *" field.value
,, % prompt
if !ErrorLevel && (id != "installdir" || installdir_allowed(path))
field.value := path
}

ReadLicense() {
Run_(A_ScriptDir "\license.txt")
}

ViewHelp(topic) {
local path
if FileExist(A_ScriptDir "\AutoHotkey.chm")
path := A_ScriptDir "\AutoHotkey.chm"
else
path := CurrentPath "\AutoHotkey.chm"
if FileExist(path)
Run_("hh.exe", "mk:@MSITStore:" path "::" topic)
else
Run_("https://autohotkey.com" topic)
}

RunAutoHotkey() {
; Setup may be running as a user other than the one that's logged
; in (i.e. an admin user), so in addition to running AutoHotkey.exe
; in user mode, have it call the function below to ensure the script
; file is correctly located.
Run_("AutoHotkey.exe", """" A_WorkingDir "\Installer.ahk"" /exec runahk")
}
Exec_RunAHK() {
; This could detect %ExeDir%\AutoHotkey.ahk (which takes precedence
; over %A_MyDocuments%\AutoHotkey.ahk), but that file is unlikely to
; exist in this situation.
script_path := A_MyDocuments "\AutoHotkey.ahk"
; Start the script.
Run AutoHotkey.exe,,, pid
; Check for common failures.
SetTitleMatchMode 2
DetectHiddenWindows On
message := ""
message_flags := 0x2034
Loop {
Sleep 50
Process Exist, %pid%
if !ErrorLevel {
if !FileExist(script_path) {
WinWait AutoHotkey Help,, 1
if !ErrorLevel {
WinActivate ; Welcome screen (v1.1.20).
return
}
}
message =
(LTrim Join`s
AutoHotkey has exited. You may need to edit your startup
script. For instance, if it exited because it had nothing
to do, you can add a hotkey.
)
message_flags := 0x2044 ; Less severe, since it might be intentional.
break
}
if WinExist("ahk_class #32770 ahk_pid " pid) {
WinGetText message
if !InStr(message, "Error")
return
WinWaitClose
Process Exist, %pid%
message := "Your script encountered an error" (ErrorLevel ? "." : " and
exited.")
. " You will need to edit it to resolve this error."
break
}
if WinExist("ahk_class AutoHotkey ahk_pid " pid) {
WinWaitClose,,, .2 ; Wait a moment in case the script is empty/about to
exit.
if !ErrorLevel
continue ; Back to the top of the loop.
DetectHiddenWindows Off
if !WinExist("ahk_pid " pid)
MsgBox 0x2040, AutoHotkey Setup, Your script is running in the
background.
return
}
}
MsgBox % message_flags, AutoHotkey Setup, %message%`n`nYour script is located
here:`n %script_path%`n`nDo you want to edit this file?
IfMsgBox Yes
{
if !FileExist(script_path)
FileAppend,, %script_path%
Run edit "%script_path%"
}
}
Quit() {
ExitApp
}

ViewWebsite() {
global
Run_(ProductWebsite)
}

Extract(dstDir="") {
if (dstDir = "") {
FileSelectFolder dstDir,,, Select a folder to copy program files to.
if ErrorLevel
return
}
try {
global TestMode, SourceDir
if (TestMode = "FailExtract")
throw
shell := ComObjCreate("Shell.Application")
try FileCreateDir %dstDir%
dst := shell.NameSpace(dstDir)
src := shell.NameSpace(SourceDir)
if !(dst && src)
throw
try dst.CopyHere(src.Items, 256)
}
catch {
FileCopyDir %SourceDir%, %dstDir%, 1
if ErrorLevel {
MsgBox 0x2030, AutoHotkey Setup, An unspecified error occurred.
return
}
}
Run %dstDir%
}

DownloadAHK() {
global wb
wb.Stop()
file := A_Temp "\ahk-install.exe"
switchPage("downloading")
Sleep 10
if !Download("https://autohotkey.com/download/ahk-install.exe", file,
"DownloadAHK_Progress") {
MsgBox 0x2010,, Download failed.
switchPage("start")
return
}
Run "%file%" /exec waitclose %A_ScriptHwnd% /exec downloaded "%file%"
ExitApp
}
Exec_WaitClose(hwnd) {
DetectHiddenWindows On
WinWaitClose ahk_id %hwnd%
}
Exec_Downloaded(file) {
; global SilentMode := true
DetermineVersion()
QuickInstall()
; NOTE: .\ is required here. Otherwise it launches the copy found
; in the directory containing the current module -- the temp dir.
Run .\AutoHotkeyU32.exe Installer.ahk /exec cleanup "%file%"
}
Exec_Cleanup(file) {
SplitPath file, name
Process WaitClose, %name%
MsgBox 64, AutoHotkey Setup, Installation complete.
FileDelete %file%
}
DownloadAHK_Progress(n, nMax) {
if !nMax
return
w := getWindow()
w.document.getElementById("dl_progress")
.style.width := (n*100/nMax) "%"
w.document.getElementById("dl_text")
.innerText := DownloadSize(n) " / " DownloadSize(nMax)
Sleep 10
}
DownloadSize(n) {
n /= 1024
if (n > 1024)
return Round(n/1024, 2) " MB"
return Round(n, 2) " KB"
}

; Based on code by Sean and SKAN @ http://www.autohotkey.com/forum/viewtopic.php?


p=184468#184468
Download(url, file, callback) {
static vt
if !VarSetCapacity(vt) {
VarSetCapacity(vt, A_PtrSize*11), nPar := "31132253353"
Loop Parse, nPar
NumPut(RegisterCallback("DL_Progress", "F", A_LoopField, A_Index-1),
vt, A_PtrSize*(A_Index-1))
}
if !(IsObject(callback) || (callback := Func(callback)))
return !(ErrorLevel := 1)
VarSetCapacity(bobj, A_PtrSize*2), NumPut(&callback, NumPut(&vt, bobj)),
VarSetCapacity(tn, 520)
if (0 = DllCall("urlmon\URLDownloadToCacheFile", "ptr", 0, "str", url, "str",
tn, "uint", 260, "uint", 0x10, "ptr", &bobj))
FileCopy %tn%, %file%, 1
else
ErrorLevel := 1
return !ErrorLevel
}
DL_Progress( pthis, nP=0, nPMax=0, nSC=0, pST=0 ) {
if A_EventInfo = 6
fn := Object(NumGet(pthis+A_PtrSize)), %fn%(np, npMax)
return 0
}

/* Setup Actions
*/
; Upgrade to newer version or from AutoHotkey to AutoHotkey_L.
; Type: "ANSI" or "Unicode"
Upgrade(Type="") {
global
_Install({
(Join C
type: Type,
path: DefaultPath,
menu: DefaultStartMenu,
ahk2exe: DefaultCompiler,
dragdrop: DefaultDragDrop,
uiAccess: DefaultUIAccess,
utf8: DefaultToUTF8,
isHostApp: DefaultIsHostApp
)})
}

; Quick install with default options.


QuickInstall() {
global
_Install({
(Join
type: DefaultType,
path: DefaultPath,
menu: DefaultStartMenu,
ahk2exe: DefaultCompiler,
dragdrop: DefaultDragDrop,
uiAccess: DefaultUIAccess,
utf8: DefaultToUTF8,
isHostApp: DefaultIsHostApp
)})
}

; Begin installation after reviewing options.


CustomInstall() {
local w := getWindow()
_Install({
(C Join
type: w.installtype.value,
path: w.installdir.value,
menu: w.startmenu.value,
ahk2exe: w.installcompiler.checked,
dragdrop: w.enabledragdrop.checked,
uiAccess: w.enableuiaccess.checked,
utf8: DefaultToUTF8, ;w.defaulttoutf8.checked
isHostApp: w.separatebuttons.checked
)})
}

; Uninstall.
Uninstall() {
global

try
SetWorkingDir % CurrentPath
catch
ErrorExit("Error uninstalling; installation directory '" CurrentPath "' may
be invalid.")
CloseScriptsEtc(CurrentPath, "uninstallation")

switchPage("wait")

/* Registry
*/

SetRegView % CurrentRegView

RegDelete HKLM, %UninstallKey%


RegDelete HKLM, %AutoHotkeyKey%
RegDelete HKCU, %AutoHotkeyKey% ; Created by Ahk2Exe.

RegDelete HKCR, .ahk


RegDelete HKCR, %FileTypeKey%
RegDelete HKCR, Applications\AutoHotkey.exe

RegDelete HKLM, SOFTWARE\Microsoft\Windows\CurrentVersion\App


Paths\AutoHotkey.exe

/* Files
*/

FileDelete AutoHotkeyU32.exe
FileDelete AutoHotkeyA32.exe
FileDelete AutoHotkeyU64.exe

FileDelete AutoHotkeyU32_UIA.exe
FileDelete AutoHotkeyA32_UIA.exe
FileDelete AutoHotkeyU64_UIA.exe

FileDelete AU3_Spy.exe
FileDelete AutoHotkey.chm
FileDelete license.txt

; This file would only exist if an older version of AutoHotkey_L


; installed it:
FileDelete Update.ahk

; Although the old installer was designed not to overwrite this in


; case the user made customizations, the old uninstaller deletes it:
FileDelete %A_WinDir%\ShellNew\Template.ahk

RemoveCompiler()

FileDelete %ProductName% Website.url


if (CurrentStartMenu != "") ; Must not remove A_ProgramsCommon itself!
FileRemoveDir %A_ProgramsCommon%\%CurrentStartMenu%, 1

if !SilentMode
MsgBox 0x2040, AutoHotkey Setup
, Setup will now close to complete the uninstallation.

; Try deleting it normally first, in case this script is running


; on an external exe (such as via a downloaded installer).
FileDelete AutoHotkey.exe
if !ErrorLevel {
FileDelete Installer.ahk
SetWorkingDir %A_Temp% ; Otherwise FileRemoveDir will fail.
FileRemoveDir %CurrentPath% ; Only if empty.
ExitApp
}

Gui Cancel

; Use cmd.exe to work around the fact that AutoHotkey.exe is locked


; while it is still running. Having a second instance of the script
; terminate this instance should be more reliable than performing
; an arbitrary wait (e.g. by calling "ping").
Run %ComSpec% /c "
(Join`s&`s
AutoHotkey.exe "%A_ScriptFullPath%" /exec kill %A_ScriptHwnd%
del Installer.ahk
del AutoHotkey.exe
cd %A_Temp%
rmdir "%CurrentPath%"
)",, Hide
}

/* Installation
*/

_Install(opt) {
global

/* Validation
*/

local exefile, binfile


if opt.type = "Unicode" {
exefile := "AutoHotkeyU32.exe"
binfile := "Unicode 32-bit.bin"
} else if opt.type = "x64" && A_Is64bitOS {
exefile := "AutoHotkeyU64.exe"
binfile := "Unicode 64-bit.bin"
} else if opt.type = "ANSI" {
exefile := "AutoHotkeyA32.exe"
binfile := "ANSI 32-bit.bin"
} else
ErrorExit("Invalid installation type '" opt.type "'")

if !InStr(FileExist(opt.path), "D")
try
FileCreateDir % opt.path
catch
ErrorExit("Unable to create installation directory ('" opt.path "')")

/* Preparation
*/

SetWorkingDir % opt.path

; If the following is "true", we have no source files to install,


; but we may have settings to change. This includes replacing the
; binary files with %exefile% and %binfile%.
installInPlace := (A_WorkingDir = A_ScriptDir)
reopen := CloseScriptsEtc(CurrentPath, "installation")

switchPage("wait")

; Remove old files which are no longer relevant.


if (CurrentVersion <= "1.0.48.05") {
FileDelete Compiler\README.txt
FileDelete Compiler\upx.exe
}
FileDelete uninst.exe

if A_Is64bitOS {
; For xx-bit installs, write to the xx-bit view of the registry.
local regView := (opt.type = "x64") ? 64 : 32
if (CurrentRegView && CurrentRegView != regView) {
; Clean up old keys in the other registry view.
SetRegView % CurrentRegView
RegDelete HKLM, %UninstallKey%
RegDelete HKLM, %AutoHotkeyKey%
RegDelete HKLM, SOFTWARE\Microsoft\Windows\CurrentVersion\App
Paths\AutoHotkey.exe
RegDelete HKLM, SOFTWARE\Microsoft\Windows\CurrentVersion\App
Paths\Ahk2Exe.exe
}
SetRegView % regView
}

/* Install Files
*/

UpdateStatus("Copying files")

; Install all unique files.


if !installInPlace {
InstallMainFiles()
if opt.ahk2exe
InstallCompilerFiles()
}

; Create UIA files from main files.


InstallUIAccessFiles(opt.uiAccess)

; If the user deselected Ahk2Exe and it was previously installed,


; ensure it is removed.
if !opt.ahk2exe
RemoveCompiler()

; Create the "default" binaries, corresponding to whichever version


; the user selected.
if !installInPlace
InstallFile(exefile, "AutoHotkey.exe")
;else: a workaround is needed later.
if opt.ahk2exe
InstallFile("Compiler\" binfile, "Compiler\AutoHotkeySC.bin")

/* Start Menu Shortcuts


*/
if CurrentStartMenu
FileRemoveDir %A_ProgramsCommon%\%CurrentStartMenu%, 1

if opt.menu {
UpdateStatus("Creating shortcuts")
local smpath := A_ProgramsCommon "\" opt.menu
FileCreateDir %smpath%
FileCreateShortcut %A_WorkingDir%\AutoHotkey.exe, %smpath%\AutoHotkey.lnk
FileDelete %smpath%\AutoIt3 Window Spy.lnk
FileCreateShortcut %A_WorkingDir%\AU3_Spy.exe, %smpath%\Active Window Info
(Window Spy).lnk
FileCreateShortcut %A_WorkingDir%\AutoHotkey.chm, %smpath%\AutoHotkey Help
File.lnk
IniWrite %ProductWebsite%, %ProductName% Website.url, InternetShortcut, URL
FileCreateShortcut %A_WorkingDir%\%ProductName% Website.url, %smpath
%\Website.lnk
FileCreateShortcut %A_WorkingDir%\Installer.ahk, %smpath%\AutoHotkey
Setup.lnk
,,,, %A_WinDir%\System32\appwiz.cpl,, -1499
if opt.ahk2exe
FileCreateShortcut %A_WorkingDir%\Compiler\Ahk2Exe.exe
, %smpath%\Convert .ahk to .exe.lnk
}

/* Registry
*/

UpdateStatus("Configuring registry")

RegWrite REG_SZ, HKLM, %AutoHotkeyKey%, InstallDir, %A_WorkingDir%


RegWrite REG_SZ, HKLM, %AutoHotkeyKey%, Version, %ProductVersion%
if opt.menu
RegWrite REG_SZ, HKLM, %AutoHotkeyKey%, StartMenuFolder, % opt.menu
else
RegDelete HKLM, %AutoHotkeyKey%, StartMenuFolder

; Might need to get rid of this to allow the ShellNew template to work:
RegDelete HKCR, ahk_auto_file
RegWrite REG_SZ, HKCR, .ahk,, %FileTypeKey%
RegWrite REG_SZ, HKCR, .ahk\ShellNew, FileName, Template.ahk

RegWrite REG_SZ, HKCR, %FileTypeKey%,, AutoHotkey Script


RegWrite REG_SZ, HKCR, %FileTypeKey%\DefaultIcon,, %A_WorkingDir
%\AutoHotkey.exe`,1

; Set up system verbs:


RegWrite REG_SZ, HKCR, %FileTypeKey%\Shell\Open,, Run Script
RegWrite REG_SZ, HKCR, %FileTypeKey%\Shell\Edit,, Edit Script
if opt.ahk2exe
RegWrite REG_SZ, HKCR, %FileTypeKey%\Shell\Compile,, Compile Script

local value

; Set default action, but don't overwrite.


try
RegRead value, HKCR, %FileTypeKey%\Shell,
catch ; Key likely doesn't exist.
RegWrite REG_SZ, HKCR, %FileTypeKey%\Shell,, Open
; Set editor, but don't overwrite.
try
RegRead value, HKCR, %FileTypeKey%\Shell\Edit\Command,
catch
RegWrite REG_SZ, HKCR, %FileTypeKey%\Shell\Edit\Command,, notepad.exe `%1

if opt.ahk2exe
RegWrite REG_SZ, HKCR, %FileTypeKey%\Shell\Compile\Command,, "%A_WorkingDir
%\Compiler\Ahk2Exe.exe" /in "`%l"

local cmd
cmd = "%A_WorkingDir%\AutoHotkey.exe"
if opt.utf8
cmd = %cmd% /CP65001
cmd = %cmd% "`%1" `%*
RegWrite REG_SZ, HKCR, %FileTypeKey%\Shell\Open\Command,, %cmd%

if UACIsEnabled {
; Run as administrator
RegWrite REG_SZ, HKCR, %FileTypeKey%\Shell\RunAs\Command,, "%A_WorkingDir
%\AutoHotkey.exe" "`%1" `%*
; Run with UI Access
if opt.uiAccess && FileExist(uiafile := StrReplace(exefile, ".exe",
"_UIA.exe")) {
RegWrite REG_SZ, HKCR, %FileTypeKey%\Shell\uiAccess,, Run with UI
Access
RegWrite REG_SZ, HKCR, %FileTypeKey%\Shell\uiAccess\Command,,
"%A_WorkingDir%\%uiafile%" "`%1" `%*
} else
RegDelete HKCR, %FileTypeKey%\Shell\uiAccess
}

if opt.dragdrop
RegWrite REG_SZ, HKCR, %FileTypeKey%\ShellEx\DropHandler,, {86C86720-42A0-
1069-A2E8-08002B30309D}
else
RegDelete HKCR, %FileTypeKey%\ShellEx

; App Paths registration isn't strictly necessary, so it's not done for the
other exe versions.
RegWrite REG_SZ, HKLM, SOFTWARE\Microsoft\Windows\CurrentVersion\App
Paths\AutoHotkey.exe,, %A_WorkingDir%\AutoHotkey.exe
if opt.ahk2exe
RegWrite REG_SZ, HKLM, SOFTWARE\Microsoft\Windows\CurrentVersion\App
Paths\Ahk2Exe.exe,, %A_WorkingDir%\Compiler\Ahk2Exe.exe

local suffixList := "|A32|U32|U64|A32_UIA|U32_UIA|U64_UIA"


Loop Parse, suffixList, |
{
RegDelete HKCR, Applications\AutoHotkey%A_LoopField%.exe
if opt.isHostApp && FileExist("AutoHotkey" A_LoopField ".exe")
RegWrite REG_SZ, HKCR, Applications\AutoHotkey%A_LoopField%.exe,
IsHostApp
}

; Write uninstaller info.


RegWrite REG_SZ, HKLM, %UninstallKey%, DisplayName, %ProductName%
%ProductVersion%
RegWrite REG_SZ, HKLM, %UninstallKey%, UninstallString, "%A_WorkingDir
%\AutoHotkey.exe" "%A_WorkingDir%\Installer.ahk"
RegWrite REG_SZ, HKLM, %UninstallKey%, DisplayIcon, %A_WorkingDir
%\AutoHotkey.exe
RegWrite REG_SZ, HKLM, %UninstallKey%, DisplayVersion, %ProductVersion%
RegWrite REG_SZ, HKLM, %UninstallKey%, URLInfoAbout, %ProductWebsite%
RegWrite REG_SZ, HKLM, %UninstallKey%, Publisher, %ProductPublisher%
RegWrite REG_SZ, HKLM, %UninstallKey%, NoModify, 1

; Notify other programs (e.g. explorer.exe) that file type associations have
changed.
; This may be necessary to update the icon when upgrading from an older version
of AHK.
DllCall("shell32\SHChangeNotify", "uint", 0x08000000, "uint", 0, "int", 0,
"int", 0) ; SHCNE_ASSOCCHANGED

UpdateStatus("")

if installInPlace {
; As AutoHotkey.exe is probably in use by this script, the final
; step will be completed by another instance of this script:
reopen_args := ""
for _, script in reopen
reopen_args .= " """ script.path """ """ script.exe """"
Run .\AutoHotkeyU32.exe "%A_ScriptFullPath%"
/exec kill %A_ScriptHwnd%
/exec setExe %exefile% %SilentMode%
/exec reopen%reopen_args%
ExitApp
}

ReopenScripts(reopen)

SwitchDone()
}

SwitchDone() {
getWindow().document.body.className := ""
switchPage("done")
}

Exec_Reopen(args*) {
reopen := []
while args.Length()
reopen.Push({path: args.RemoveAt(1), exe: args.RemoveAt(1)})
global AutoRestart := true
ReopenScripts(reopen)
}

InstallFile(file, target="") {
global
if (target = "")
target := file
Loop { ; Retry loop.
try {
FileCopy %SourceDir%\%file%, %target%, 1
; If successful (no exception thrown):
return
}
if SilentMode {
SilentErrors += 1
return ; Continue anyway.
}
local error_message := RTrim(GetErrorMessage(), "`r`n")
MsgBox 0x2012, AutoHotkey Setup,
(LTrim
Error installing file "%target%"

Specifically: %error_message%

Click Abort to stop the installation,


Retry to try again, or
Ignore to skip this file.
)
IfMsgBox Abort
ExitApp
IfMsgBox Ignore
return
}
}

InstallMainFiles() {
InstallFile("AutoHotkeyU32.exe")
InstallFile("AutoHotkeyA32.exe")
if A_Is64bitOS
InstallFile("AutoHotkeyU64.exe")

InstallFile("AU3_Spy.exe")
InstallFile("AutoHotkey.chm")
InstallFile("license.txt")

InstallFile("Installer.ahk")

if !FileExist(A_WinDir "\ShellNew\Template.ahk") {
FileCreateDir %A_WinDir%\ShellNew
InstallFile("Template.ahk", A_WinDir "\ShellNew\Template.ahk")
}
}

InstallUIAccessFiles(create) {
local suffixList := "A32|U32" (A_Is64bitOS ? "|U64" : "")
Loop Parse, suffixList, |
{
file = AutoHotkey%A_LoopField%_UIA.exe
if !(create || FileExist(file))
continue
FileCopy AutoHotkey%A_LoopField%.exe, %file%, 1
try
EnableUIAccess(file)
catch
MsgBox 48, AutoHotkey Setup, Error creating %file%. ; Non-critical.
}
}

installdir_allowed(path) {
local w := getWindow()
if w.enableuiaccess.checked && !IsTrustedLocation(path) {
MsgBox 0x2034, AutoHotkey Setup, Installing to "%path%" will disable the
"Run with UI Access" option`, which requires that you install to a subdirectory of
Program Files.`n`nInstall here anyway?
IfMsgBox No
return false
w.enableuiaccess.checked := false
}
return true
}

installdir_onchange() {
local w := getWindow()
if !installdir_allowed(w.installdir.value)
w.installdir.value := DefaultPath
}

enableuiaccess_onchange() {
local w := getWindow()
if w.enableuiaccess.checked && !IsTrustedLocation(w.installdir.value) {
w.enableuiaccess.checked := false
MsgBox 0x2030, AutoHotkey Setup, This option requires installing AutoHotkey
to a subdirectory of Program Files.
}
}

IsTrustedLocation(path) { ; http://msdn.com/library/bb756929
EnvGet other, % A_PtrSize=8 ? "ProgramFiles(x86)" : "ProgramW6432"
return InStr(path, A_ProgramFiles "\") = 1
|| other && InStr(path, other "\") = 1
}

EnableUIAccess(filename)
{
hStore := DllCall("Crypt32\CertOpenStore", "ptr", 10 ; STORE_PROV_SYSTEM_W
, "uint", 0, "ptr", 0, "uint", 0x20000 ; SYSTEM_STORE_LOCAL_MACHINE
, "wstr", "Root", "ptr")
if !hStore
throw
p := DllCall("Crypt32\CertFindCertificateInStore", "ptr", hStore
, "uint", 0x10001 ; X509_ASN_ENCODING|PKCS_7_ASN_ENCODING
, "uint", 0, "uint", 0x80007 ; FIND_SUBJECT_STR
, "wstr", "AutoHotkey", "ptr", 0, "ptr")
if p
cert := new CertContext(p)
else
cert := EnableUIAccess_CreateCert("AutoHotkey", hStore)
EnableUIAccess_SetManifest(filename)
EnableUIAccess_SignFile(filename, cert, "AutoHotkey")
}
EnableUIAccess_SetManifest(file)
{
xml := ComObjCreate("Msxml2.DOMDocument")
xml.async := false
xml.setProperty("SelectionLanguage", "XPath")
xml.setProperty("SelectionNamespaces"
, "xmlns:v1='urn:schemas-microsoft-com:asm.v1' "
. "xmlns:v3='urn:schemas-microsoft-com:asm.v3'")
if !xml.load("res://" file "/#24/#1") ; Load current manifest
throw
node := xml.selectSingleNode("/v1:assembly/v3:trustInfo/v3:security"
. "/v3:requestedPrivileges/v3:requestedExecutionLevel")
if !node ; Not AutoHotkey v1.1?
throw
node.setAttribute("uiAccess", "true")
xml := RTrim(xml.xml, "`r`n")
VarSetCapacity(data, data_size := StrPut(xml, "utf-8") - 1)
StrPut(xml, &data, "utf-8")
if !(hupd := DllCall("BeginUpdateResource", "str", file, "int", false))
throw
r := DllCall("UpdateResource", "ptr", hupd, "ptr", 24, "ptr", 1
, "ushort", 1033, "ptr", &data, "uint", data_size)
if !DllCall("EndUpdateResource", "ptr", hupd, "int", !r) && r
throw
}
EnableUIAccess_CreateCert(CertName, hStore)
{
if !DllCall("Advapi32\CryptAcquireContext", "ptr*", hProv
, "str", CertName, "ptr", 0, "uint", 1, "uint", 8) ; PROV_RSA_FULL=1,
CRYPT_NEWKEYSET=8
throw
prov := new CryptContext(hProv)
if !DllCall("Advapi32\CryptGenKey", "ptr", hProv
, "uint", 2, "uint", 0x4000001, "ptr*", hKey) ; AT_SIGNATURE=2,
EXPORTABLE=..01
throw
key := new CryptKey(hKey)
Loop 2
{
if A_Index = 1
pbName := cbName := 0
else
VarSetCapacity(bName, cbName), pbName := &bName
if !DllCall("Crypt32\CertStrToName", "uint", 1, "str", "CN=" CertName
, "uint", 3, "ptr", 0, "ptr", pbName, "uint*", cbName, "ptr", 0) ;
X509_ASN_ENCODING=1, CERT_X500_NAME_STR=3
throw
}
VarSetCapacity(cnb, 2*A_PtrSize), NumPut(pbName, NumPut(cbName, cnb))
VarSetCapacity(endTime, 16)
DllCall("GetSystemTime", "ptr", &endTime)
NumPut(NumGet(endTime, "ushort") + 10, endTime, "ushort") ; += 10 years
if !hCert := DllCall("Crypt32\CertCreateSelfSignCertificate"
, "ptr", hProv, "ptr", &cnb, "uint", 0, "ptr", 0
, "ptr", 0, "ptr", 0, "ptr", &endTime, "ptr", 0, "ptr")
throw
cert := new CertContext(hCert)
if !DllCall("Crypt32\CertAddCertificateContextToStore", "ptr", hStore
, "ptr", hCert, "uint", 1, "ptr", 0) ; STORE_ADD_NEW=1
throw
return cert
}
class CryptContext {
__New(p) {
this.p := p
}
__Delete() {
DllCall("Advapi32\CryptReleaseContext", "ptr", this.p, "uint", 0)
}
}
class CertContext extends CryptContext {
__Delete() {
DllCall("Crypt32\CertFreeCertificateContext", "ptr", this.p)
}
}
class CryptKey extends CryptContext {
__Delete() {
DllCall("Advapi32\CryptDestroyKey", "ptr", this.p)
}
}
EnableUIAccess_SignFile(File, CertCtx, Name)
{
VarSetCapacity(wfile, 2 * StrPut(File, "utf-16")), StrPut(File, &wfile, "utf-
16")
VarSetCapacity(wname, 2 * StrPut(Name, "utf-16")), StrPut(Name, &wname, "utf-
16")
cert_ptr := IsObject(CertCtx) ? CertCtx.p : CertCtx
EnableUIAccess_Struct(file_info, "ptr", A_PtrSize*3 ; SIGNER_FILE_INFO
, "ptr", &wfile)
VarSetCapacity(dwIndex, 4, 0) ; DWORD
EnableUIAccess_Struct(subject_info, "ptr", A_PtrSize*4 ; SIGNER_SUBJECT_INFO
, "ptr", &dwIndex, "ptr", SIGNER_SUBJECT_FILE:=1, "ptr", &file_info)
EnableUIAccess_Struct(cert_store_info, "ptr", A_PtrSize*4 ;
SIGNER_CERT_STORE_INFO
, "ptr", cert_ptr, "ptr", SIGNER_CERT_POLICY_CHAIN:=2)
EnableUIAccess_Struct(cert_info, "uint", 8+A_PtrSize*2 ; SIGNER_CERT
, "uint", SIGNER_CERT_STORE:=2, "ptr", &cert_store_info)
EnableUIAccess_Struct(authcode_attr, "uint", 8+A_PtrSize*3 ;
SIGNER_ATTR_AUTHCODE
, "int", false, "ptr", true, "ptr", &wname)
EnableUIAccess_Struct(sig_info, "uint", 8+A_PtrSize*4 ; SIGNER_SIGNATURE_INFO
, "uint", CALG_SHA1:=0x8004, "ptr", SIGNER_AUTHCODE_ATTR:=1
, "ptr", &authcode_attr)
hr := DllCall("MSSign32\SignerSign"
, "ptr", &subject_info, "ptr", &cert_info, "ptr", &sig_info
, "ptr", 0, "ptr", 0, "ptr", 0, "ptr", 0, "uint")
if (hr != 0)
throw hr
}
EnableUIAccess_Struct(ByRef struct, arg*)
{
VarSetCapacity(struct, arg[2], 0), p := &struct
Loop % arg.Length()//2
p := NumPut(arg[2], p+0, arg[1]), arg.RemoveAt(1, 2)
return &struct
}

InstallCompilerFiles() {
FileCreateDir Compiler
InstallFile("Compiler\Ahk2Exe.exe")
InstallFile("Compiler\ANSI 32-bit.bin")
InstallFile("Compiler\Unicode 32-bit.bin")
; Install the following file even if !isOS64bit() to support
; compiling scripts for 64-bit systems on 32-bit systems:
InstallFile("Compiler\Unicode 64-bit.bin")
}

RemoveCompiler() {
global
FileDelete Compiler\Ahk2Exe.exe
FileDelete Compiler\ANSI 32-bit.bin
FileDelete Compiler\Unicode 32-bit.bin
FileDelete Compiler\Unicode 64-bit.bin
FileDelete Compiler\AutoHotkeySC.bin
FileRemoveDir Compiler ; Only if empty.
RegDelete HKLM, SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\Ahk2Exe.exe
}

HandleExec(n) {
++n
argn := %false%
while (n <= argn) {
fn := Func("Exec_" %n%), ++n, args := []
while (n <= argn) {
v := %n%, ++n
if v = /exec
break
args.Push(v)
}
c := args.Length()
if !fn || c < fn.MinParams || (c > fn.MaxParams && !fn.IsVariadic)
ErrorExit("Internal: bad /exec")
%fn%(args*)
}
}

Exec_Kill(id) {
DetectHiddenWindows On
WinKill ahk_id %id%
WinWaitClose ahk_id %id%,, 10
}

Exec_SetExe(exefile, SilentMode := false) {


InstallFile(exefile, "AutoHotkey.exe")
if !SilentMode
MsgBox 64, AutoHotkey Setup, The settings have been updated.
}
DefineUI:
html=
(%`
<!DOCTYPE HTML>
<html><head>

<style type="text/css">
body {
background-color: ButtonFace;
font-family: "Arial", sans-serif;
font-size: 14px;
overflow: hidden;
cursor: default;
padding: 0;
margin: 0;
border: none;
position: absolute;
top: 0;
left: 0;
width: 600px;
height: 400px;
}
h1 {
font-size: 37px;
font-weight: normal;
color: #405871;
background-color: white;
padding: 15px 25px;
margin: 0 -15px;
}
p {
margin-top: 15px;
}
a:link, a:visited {
color: #0066CC;
}
.options {
margin: 0 3em 0 2em;
}
.options a {
display: block;
padding: 0.8em 1em;
margin: 0.3em 0;
position: relative;
_height: 1%; /* IE6 hasLayout */
}
.marker {
position: absolute;
right: 10px;
font-size: 25px;
top: 50%;
margin-top: -17px;
}
a.button,
.options a {
border: 1px solid ButtonShadow;
background-color: white;
text-decoration: none;
}
a.button {
padding: .3em .5em;
text-align: center;
}
a.button,
a.button:visited,
.options a:link,
.options a:visited {
cursor: hand;
color: #405871;
}
a.button:hover,
a.button:active, /*IE6*/
.options a:hover,
.options a:active,
.options a:focus {
background-color: #F8F8FF;
border-color: #4774B2;
color: #4774B2;
}
.options a:active,
.options a:focus {
left: 3px;
}
.options p {
font-size: 85%;
margin: 0.2em 1em;
}
.footer {
position: absolute;
bottom: 1em;
font-size: 85%;
}
p.footer {
left: 2em;
}
p#extract {
left: auto;
right: 2em;
}
.page {
padding: 15px;
display: none; /* overridden by script */
color: ButtonText;
}
.nav {
background-color: #405871;
color: white;
padding: 3px 0;
}
#version_number {
position: absolute;
right: 20px;
}
.nav a,
.nav a:visited {
color: #ddd;
text-decoration: none;
padding: 0 5px 3px;
}
.nav a:hover {
color: white;
}
.nav a.current,
.nav a.current:visited /*IE6*/ {
color: #405871;
background-color: ButtonFace;
cursor: default;
border-top: 2px solid #60A0F0;
padding: 0 7px 3px;
margin: 0 -2px;
}
#configure_nav {
padding-left: 1em;
display: none;
}
.custom-mode #configure_nav,
.config-mode #configure_nav {
display: inline;
}
.config-mode .install-only {
display: none;
}
.warning {
display: none;
background-color: #fee;
color: #800;
border: 1px solid #800;
padding: 0.5em;
margin: -0.5em 0 1em;
}
.textbox {
border: 1px solid ButtonShadow;
padding: 0 0.4em;
margin: 7px 0 10px;
height: 29px;
line-height: 27px;
vertical-align: top;
}
#installdir, #startmenu {
width: 70%;
}
#installdir_browse, #startmenu_del {
padding: 0 0.6em;
margin: 7px 0 10px;
height: 29px;
line-height: 29px;
display: inline-block;
background-color: ButtonFace;
}
label {
padding: 5px;
display: block;
width: 90%;
}
label.indent {
padding-left: 30px;
}
label p {
font-size: 85%;
margin: .3em 25px;
color: #405871;
}
#install_button, #next-button {
font-size: 125%;
right: 15px;
width: 5em;
}
#dl_container {
position: absolute;
left: 12%;
top: 50%;
width: 80%;
height: 1em;
background-color: white;
border: 1px solid #405871;
}
#dl_progress {
width: 0;
height: 100%;
background-color: #405871;
}
#dl_text {
position: absolute;
left: 12%;
top: 60%;
width: 80%;
text-align: center;
}
</style>
<script type="text/javascript">
function forEach(arr, fn) {
var i;
for (i = 0; i < arr.length; ++i)
fn.apply(arr[i]);
}
function selectNavTab(nav, tab) {
tab = '#' + tab;
forEach (nav.getElementsByTagName("a"), function() {
this.className = this.hash == tab ? this.className + ' current '
: this.className.replace(' current ', '');
})
}
function onload() {
forEach (configure_nav.getElementsByTagName("a"), function() {
this.tabIndex = 1000;
if (this.hash != "") {
this.onclick = function() {
if (event.preventDefault)
event.preventDefault(); // IE11
event.returnValue = // IE8/IE6
switchPage(this.hash.substr(1));
}
}
})
}
function initOptions(curName, curVer, curType, newVer, instDir, smFolder, defType,
is64) {
if (onload) onload(), onload = null;
var opt;
var warn;
var types = {Unicode: "Unicode 32-bit", ANSI: "ANSI 32-bit", x64: "Unicode
64-bit"};
var curTypeName = types[curType];
var defTypeName = types[defType];
curTypeName = curTypeName ? " (" + curTypeName + ")" : "";
if (curName == "AutoHotkey" && curVer <= "1.0.48.05") {
start_intro.innerText = curName + " v" + curVer + " is installed. What
do you want to do?";
var uniType = is64 ? "x64" : "Unicode";
var uniTypeName = types[uniType];
opt = [
"AHK('Upgrade', 'ANSI')", "Upgrade to v" + newVer + " (" +
types.ANSI + ")", "Recommended for compatibility.",
"AHK('Upgrade', '" + uniType + "')", "Upgrade to v" + newVer + "
(" + uniTypeName + ")", "",
"AHK('Customize')", "Custom Installation", ""
];
warn = '<strong>Note:</strong> Some AutoHotkey 1.0 scripts are <a
href="#" onclick="'+"AHK('ViewHelp', '/docs/Compat.htm'); return false"+'">not
compatible</a> with AutoHotkey 1.1.';
} else if (curName == "") {
start_intro.innerText = "Please select the type of installation you
wish to perform.";
opt = [
"AHK('QuickInstall')", "Express Installation", "Default version:
" + defTypeName + "<br>Install in: " + instDir,
"AHK('Customize')", "Custom Installation", ""
];
} else if (curVer != newVer) {
start_intro.innerText = curName + " v" + curVer + curTypeName + " is
installed. What do you want to do?";
opt = [
"AHK('Upgrade', '" + defType + "')", (curVer < newVer ? "Upgrade"
: "Downgrade") + " to v" + newVer + " (" + defTypeName + ")", "",
"AHK('Customize')", "Custom Installation", ""
];
} else {
start_intro.innerText = curName + " v" + curVer + curTypeName + " is
installed. What do you want to do?";
opt = [
"AHK('QuickInstall')", "Repair", "",
"AHK('Customize')", "Modify", "",
"AHK('Uninstall')", "Uninstall", ""
];
}
var i, html = [];
for (i = 0; i < opt.length; i += 3) {
html.push('<a href="#" onclick="', opt[i], '; return false" id="opt',
Math.floor(i/3)+1, '"><span>', opt[i+1], '</span>');
if (opt[i+2])
html.push('<p>', opt[i+2], '</p>');
if (opt[i] == "AHK('Customize')")
html.push('<div class="marker">\u00BB</div>');
html.push('</a>');
}
start_options.innerHTML = html.join("");
start_warning.innerHTML = warn;
start_warning.style.display = warn ? "block" : "none";
version_number.innerHTML = 'version ' + newVer;
installtype.value = defType;
installdir.value = instDir;
startmenu.value = smFolder;
startmenu.onblur();
forEach (document.getElementsByTagName("a"), function() {
if (/*this.className == "button" ||*/ this.parentNode.className ==
"options")
this.hideFocus = true;
})
}
document.onselectstart =
document.oncontextmenu =
document.ondragstart =
function() {
return window.event && event.srcElement.tagName == "INPUT" || false;
};
function setInstallType(type) {
installtype.value = type;
switchPage(configureMode ? 'options' : 'location');
event.returnValue = false;
}
function switchPage(page) {
page = document.getElementById(page);
for (var n = page.parentNode.firstChild; n; n = n.nextSibling) if
(n.className == "page") {
if (n != page)
n.style.display = "none";
else
n.style.display = "block";
}
selectNavTab(configure_nav, page.id);
var f;
switch (page.id) {
case "version": f = "it_" + installtype.value; break;
case "location": f = "next-button"; break;
case "options": f = "install_button"; break;
case "done": f = "done_exit"; break;
}
if (f) {
// If page == version, it mightn't actually be visible at this point,
// which causes IE7 (and perhaps older) to throw error 0x80020101.
try { document.getElementById(f).focus() } catch (ex) { }
}
return false;
}
function customInstall() {
if (startmenu.style.color)
startmenu.value = '';
return AHK('CustomInstall');
}</script>
</head><body scroll="no">

<h1>AutoHotkey Setup</h1>
<div class="nav">
<em id="version_number"></em>
<span id="configure_nav">
<a href="#start">home</a>
<a href="#version">version</a>
<a href="#location" class="install-only">location</a>
<a href="#options">options</a>
<a href="#" onclick="customInstall(); return false"
id="nav_install">install</a>
</span>
&nbsp;
</div>

<div class="page" id="start">


<p id="start_intro"></p>
<div class="warning" id="start_warning"></div>
<div class="options" id="start_options"></div>
<p class="footer">AutoHotkey is open source software: <a href="#"
onclick="AHK('ReadLicense'); return false">read license</a></p>
<p class="footer install-only" id="extract"><a href="#"
onclick="AHK('Extract'); return false" title="Save program files without
installing.">extract to...</a></p>
</div>
<div class="page" id="version">
<p>Which version of AutoHotkey.exe should run by default?</p>
<input type="hidden" id="installtype">
<div class="options">
<a href="#" id="it_Unicode" onclick="setInstallType('Unicode')">Unicode
32-bit
<p>Recommended for new installations/scripts.</p> <div
class="marker">&#187;</div></a>
<a href="#" id="it_x64" onclick="setInstallType('x64')">Unicode 64-bit
<p>Faster, but compiled scripts won't run on 32-bit systems.</p>
<div class="marker">&#187;</div></a>
<a href="#" id="it_ANSI" onclick="setInstallType('ANSI')">ANSI 32-bit
<p>Better compatibility with some legacy scripts.</p> <div
class="marker">&#187;</div></a>
</div>
<p class="footer"><a id="versionhelp" href="#" onclick="AHK('ViewHelp',
'/docs/Compat.htm#Format'); return false">More information</a></p>
</div>

<div class="page" id="location">


<label for="installdir" class="indent">Install location:<br>
<input type="text" class="textbox" id="installdir" value="C:\Program
Files\AutoHotkey"> <a href="#" onclick="AHK('SelectFolder', 'installdir', 'Select
the folder to install AutoHotkey in.'); return false" id="installdir_browse"
class="button">Browse</a></label>
<label for="startmenu" class="indent"> Create shortcuts in the following
Start menu folder:<br>
<input type="text" class="textbox" id="startmenu" value="AutoHotkey"
onfocus="if (style.color) value='', style.color = '';"
onblur="if (value == '') value = '(don\'t create shortcuts)',
style.color = '#888';">
<a href="#" id="startmenu_del" class="button" style="color:red"
onclick = "startmenu.value=''; startmenu.onblur(); return false;">X</a>
</label>
<a href="#" onclick="switchPage('options'); return false" class="button
footer" id="next-button">Next</a>
</div>

<div class="page" id="options">


<label for="installcompiler" class="install-only"><input type="checkbox"
id="installcompiler" checked="checked"> Install script compiler
<p>Installs Ahk2Exe, a tool to convert any .ahk script into a stand-
alone EXE.<br>
Also adds a "Compile" option to .ahk context menus.</p></label>
<label for="enabledragdrop"><input type="checkbox" id="enabledragdrop">
Enable drag &amp; drop
<p>Files dropped onto a .ahk script will launch that script (the files
will be passed as parameters). This can lead to accidental launching so you may
wish to disable it.</p></label>
<label for="separatebuttons"><input type="checkbox" id="separatebuttons">
Separate taskbar buttons
<p>Causes each script which has visible windows to be treated as a
separate program, but prevents AutoHotkey.exe from being pinned to the taskbar. <a
href="#" onclick="AHK('ViewHelp',
'/docs/Scripts.htm#Installer_IsHostApp')">[help]</a></p></label>
<label for="enableuiaccess"><input type="checkbox" id="enableuiaccess"> Add
'Run with UI Access' to context menus
<p>UI Access enables scripts to automate administrative programs. <a
href="#" onclick="AHK('ViewHelp',
'/docs/Scripts.htm#Installer_uiAccess')">[help]</a></p></label>
<a href="#" onclick="customInstall(); return false" id="install_button"
class="button footer">Install</a>
</div>

<div class="page" id="wait">


<p style="color: #999; font-size: 120%; text-align: center; margin-top:
5em">this shouldn't take long...</p>
<p style="text-align: center" id="install_status"></p>
</div>

<div class="page" id="done">


<p>Installation complete.</p>
<div class="options">
<a href="#" onclick="AHK('ViewHelp', '/docs/AHKL_ChangeLog.htm');
return false">View Changes &amp; New Features</a>
<a href="#" onclick="AHK('ViewHelp', '/docs/Tutorial.htm'); return
false">View the Tutorial</a>
<a href="#" onclick="AHK('RunAutoHotkey'); return false">Run
AutoHotkey</a>
<a href="#" onclick="AHK('Quit'); return false" id="done_exit">Exit</a>
</div>
</div>

<div class="page" id="downloading">


<div id="dl_container"><div id="dl_progress"></div></div>
<div id="dl_text">Connecting...</div>
</div>

</body></html>
)
return

You might also like