AutoHotkey v2 不是简单的“把版本号改一下”。它把很多 v1 时代为了兼容而保留的旧语法清掉了:命令语法、传统赋值、百分号取变量、ErrorLevel、Gui 子命令等都发生了变化。本文按最容易踩坑的顺序整理,适合把旧脚本逐段迁移到 v2 时对照检查。
一、先给脚本写清楚运行版本
迁移前建议在每个脚本开头加上版本声明,避免同一台电脑同时安装 v1/v2 后运行错解释器。
; v1 脚本 #Requires AutoHotkey v1.1 ; v2 脚本 #Requires AutoHotkey v2.0
不要一上来就全站式替换。更稳的做法是先挑一个功能完整、依赖较少的小脚本迁移,通过后再处理大型脚本和公共库。
二、命令语法变成函数调用
v1 常见的命令写法在 v2 中基本都变成了函数式写法。最大的变化是:字符串要加引号,变量不再用百分号包起来。
; v1 MsgBox, Hello AHK Run, notepad.exe Sleep, 500 ; v2 MsgBox "Hello AHK" Run "notepad.exe" Sleep 500
如果需要返回值,就用函数返回值;如果只是执行动作,v2 仍然允许省略括号。
三、传统赋值 var = text 要改成表达式赋值
v1 里很多老脚本会写:
; v1 name = AutoHotkey MsgBox, % name
v2 中应改成:
; v2 name := "AutoHotkey" MsgBox name
这也是迁移时最常见的第一类报错。经验上,看到单独一行的 =,就要警惕它是不是旧式赋值。
四、百分号取变量大多要删除
v1 命令参数里经常用 %var% 或 % expression 强制表达式。v2 的参数默认就是表达式,所以写法要反过来:变量直接写,普通文本加引号,拼接用空格或函数。
; v1 exe := "notepad.exe" WinActivate, % "ahk_exe " exe ; v2 exe := "notepad.exe" WinActivate "ahk_exe " exe
如果字符串比较复杂,建议用 Format(),可读性会比硬拼更好。
; v2
file := "test.txt"
MsgBox Format("当前文件:{}", file)
五、输出变量要用 &,很多命令改成返回值
v1 里不少命令通过参数返回结果:
; v1 MouseGetPos, x, y WinGetTitle, title, A PixelGetColor, color, 100, 100, RGB
v2 中要区分两种情况:有些输出变量要加 &,有些命令变成了直接返回。
; v2
MouseGetPos &x, &y
title := WinGetTitle("A")
color := PixelGetColor(100, 100, "RGB")
迁移窗口、图色、文件、注册表、INI 相关代码时,这类改动会非常多,建议一段一段测试。
六、ErrorLevel 不再是主要判断方式
v1 时代很多脚本依赖 ErrorLevel:
; v1
ImageSearch, x, y, 0, 0, A_ScreenWidth, A_ScreenHeight, icon.png
if (ErrorLevel = 0)
Click, %x%, %y%
v2 中优先看函数返回值,并对真正异常的情况使用 try/catch。
; v2
if ImageSearch(&x, &y, 0, 0, A_ScreenWidth, A_ScreenHeight, "icon.png")
Click x, y
else
MsgBox "没有找到图片"
一些函数在参数错误、文件不存在、窗口不存在等情况下会直接抛异常。迁移时不要简单把所有失败都当成“没找到”,该捕获异常的地方要写清楚。
七、热键多行写法要加大括号
v1 多行热键通常靠 return 结束:
; v1 F1:: MsgBox, 你好 return
v2 推荐写成函数体:
; v2
F1:: {
MsgBox "你好"
}
还有一个容易忽略的点:v2 的热键函数默认是局部作用域。如果要修改全局变量,需要显式声明。
; v2
count := 0
F1:: {
global count
count += 1
MsgBox count
}
八、#If 要改成 #HotIf
上下文热键迁移时,很多脚本会卡在这里。
; v1
#If WinActive("ahk_exe notepad.exe")
^j::Send, hello
#If
; v2
#HotIf WinActive("ahk_exe notepad.exe")
^j::Send "hello"
#HotIf
九、GUI 从命令式变成对象式
v1 的 GUI 代码通常长这样:
; v1 Gui, Add, Text,, 名字 Gui, Add, Edit, vName Gui, Add, Button, gSubmit, 确定 Gui, Show return Submit: Gui, Submit MsgBox, % Name return
v2 更推荐对象和事件写法:
; v2
myGui := Gui()
myGui.AddText(, "名字")
nameEdit := myGui.AddEdit()
myGui.AddButton(, "确定").OnEvent("Click", (*) => MsgBox(nameEdit.Value))
myGui.Show()
如果旧脚本 GUI 很多,不建议机械替换。先把界面创建、控件变量、按钮事件三部分拆开,再逐步重写。
十、对象字典建议改用 Map
v1 里很多人把普通对象当字典用。v2 中普通对象更偏“属性对象”,任意键值字典建议用 Map。
; v2 user := Map() user["name"] := "AHK" user["level"] := 2 MsgBox user["name"]
如果旧代码大量使用 obj[key] 存取动态键,迁移时要特别检查它到底应该是对象属性,还是 Map 字典。
推荐迁移顺序
- 先加
#Requires,确认脚本由正确版本运行。 - 把传统赋值、命令语法、百分号变量改掉。
- 处理输出变量、返回值、ErrorLevel。
- 再改热键、上下文热键、GUI、对象。
- 最后跑一遍真实使用场景,尤其是窗口、图色、剪贴板、文件读写这些容易受环境影响的部分。
结语
v2 的门槛在迁移期会高一些,但迁移完成后,代码会更统一、更容易读,也更适合长期维护。我的建议是:老脚本能稳定运行就不必急着全改;新项目、新教程、新公共库可以优先按 v2 写。
参考资料:AutoHotkey 官方 v1.1 到 v2.0 变更说明

评论(0)