分享

AutoHotKey初学指南

 樵夫1964 2021-02-18


最开始的时候, 同学在工作中需要为服务器安装软件, 但多台服务器的重复工作让他想寻找一种自动化的方式, 于是拜托我找一找. 但这方面我没有研究, 随便找了下, 也就是基于打包软件的命令行安装, 以及类似
AutoHotKey这样的自动化软件. 如果没听过AutoHotKey, 你可以理解为按键精灵之类的.

第一种方式, 由于安装文件的打包软件有很多种, 像NullsoftInstallShieldAdvanced Installer等, 我自己没有开发过像样的Windows程序, 这方面不了解. 查资料的结果是不同打包形式需要不同的命令和参数, 有得似乎并不提供静默安装的方式. 另外, 得针对不同软件, 辨别打包形式, 也挺麻烦.

至于第二种, 熟悉Linux平台的应该都习惯于使用脚本做一些自动化操作. 这里的脚本包括shell, python, ruby等. 所以, 基于学习另一种语言的想法, 便看了AutoHotKey的初学指南.

注意: 此处并不是原文翻译, 只是自学笔记和感受, 主观成份很多.


AutoHotKey(以下简称AHK)是Windows平台下一款免费开源的自动化软件, 方便用户处理重复性的任务. 它是一种脚本语言, 最开始只用于定义热键(hotkey)和相应的动作.

快速开始

在官网https:///下载软件并安装. 任意目录右击新建Autohotkey script, 追加^w::MsgBox, hello, world文本, 保存并双击脚本运行. 在任务栏右下脚会出现AutoHotKey的运行图标. 此时, 按键Ctrl+w会弹出对话框, 显示hello, world, 说明软件工作正常.

追加文本有这样的形式, hotkey::action. 此处, ^表示Ctrl键, 如果一定要区别左右, 可以使用<^>^的形式. 还有!表示Alt键, #表示Win键, +表示Shift键, 且都可以使用<>前缀表示左右键. ^w表示快捷键Ctrl+w, ^!w表示快捷键Ctrl+Alt+w, 依此类推. 而动作部分是一个命令MsgBox, 表示弹出对话框, 并显示文本. 可以有更多的参数, 以自定义标题栏文本, 选择按钮(如yes/no/cancel还是drop/save/ignore).

所谓的组合键, 字面意思是同时按下多个键, 但如果你的多个键都是正常键, 即没有`Ctrl`, `Alt`, `Shift`, `Win`键的话, 需要`&`来组合. 如同时按`a`和`b`, 表示为`a & b`. 另外, 如果热键只有`Ctrl`单键, 则需要用`Ctrl`来表示, 左右为`LCtrl`和`RCtrl`, 不区分大小写. 其余键类同. 

此处, 因为动作只有一个, 因此写到::后即可, 多个动作从第二行起, 每行一个动作, 最后写上Return表示此热键定义的动作完毕, 下面的内容属于另一个热键的.

除了定义热键外, AHK另一个常用法是文本替换, 或者说热字串(hotstring). 如::hw::hello, world. 重载入后, 在任意输入框, 包括所有的文本编辑器, 浏览器地址栏, 百度搜索框等, 当键入hw后, 任意结束符EndChar都会触发文本替换. 此处的结束符, 可能理解为非数字字母. 本质上, 当键入结束符, AHK出退格键N次再键入入替换文本. 

注意, 每添加一个新的热键或热字串, 都需要重新载入脚本. 可在右下脚的运行图标上右击, 选择Reload this script. 或者可以自定义热键来重载入脚本.

hotkey::action  ;1, 单行定义
hotkey::        ;2, 多行定义    action1    action2    ...Return
::hotstring::text  ;3, 热字串, 文本替换
::hotstring::      ;4, 热字串, 动作触发
   action
Return

虽然我这里区分了大小写, 但事实上AHK并不区分大小写, 但仍然推荐驼峰写法以方便辨认.

通过这种方式定义的热键或热字串都是全局性的, 如果想定义针对特定窗口的热键或热字串, 可以用如下形式

#IfWinActive Untiled - Notepad  ;标题栏文本#space::    MsgBox You pressed Win+Spacebar in notepad.Return#IfWinActive

此处在无标题记事本中创建了热键Win+space.

AHK还提供了简单的条件语句

if (var = 5) {  ; equal?    msgbox, var equals %var%} else {    MsgBox, var not equals %var%}

以上4种形式, 就基本是AHK的主要内容了.

分点细讲

AHK最主要的部分是热键, 函数, 和命令. 热键方面, 要知道你想要的热键如何表示. 函数和命令则是需要查表和记忆. 其余还有变量, 各种语句等.

函数和命令是AHK最奇怪的部分. 命令没有返回值, 函数有; 命令行参数文本默认为字串, 函数参数的字串必须'包围; 命令参数不能嵌套命令, 而函数参数可以是另一个函数的返回值; 命令参数文本中的+!#^被解析为特殊热键, 需要{}包围来表示原符号, 而函数参数中的字串不需要; 命令的参数中变量以%包围, 函数不需要; 命令参数中数学表达式并不运算, 函数会.

以上的不同, 并不是针对函数和命令的参数, 在其他方面也适用. 我一般将命令参数表现出来的特性理解成文本, 而函数参数表现出来的特性理解成表达式. 以下会提到在赋值语句中的差异. 其实在条件语句中, 当有()时, 适用表达式, 而没有()时, 适用文本. 但即使在文本中, 也只有在操作符如=<>右边才需要%包围变量.

这些差异大部分时候让我觉得很奇怪, 不明白语言为什么如此设计. 我相信这对任何一个学习过通用编程语言的人来说, 都是不可接受的. 但考虑到AHK其实并不是作为脚本语言被精心设计, 而是在autoit软件的基础上扩展起来的. 这是自己的理解, 我对AHK的历史以及开发记录并不了解.

变量

使用变量并不需要类型声明, 这点类似动态语言.

var = textvar := expression

上面说的文本和表达式的差异在此处也适用. 如num = 5*3, 实际上, num并不是15, 而是字串5*3. 此处数学表达式不运算, 而:=则会. 另外, var1=var2并不是将var2的内容给var1, 而是将字串var2var1. 需要var1=%var2%来达到目的. 而var1:=var2则可以.
其实差异还是挺多的, 所以我一直认为这里的语法设计的太冗余了. 建议大家可以的话, 尽量使用:=.

命令

因为命令比较经常使用, 先介绍经常使用的命令. 再声明一遍, 命令名不区分大小写.

cmd, arg1[, arg2, arg3...], 这是命令的一般形式, []内的参数表示可以省略. 如果只想省略中间的某个参数, 用,,连续两个,来将此位置的参数空过.

注意上面提到的, 在命令参数中, 有特殊的注意事项.

参数使用变量用%包围, 文本和数字无需'包围, 参数不进行数字运算. 一行一条命令.

Send, text: 发送文本, 本质上是发送敲击的键. 对于数字字母就是对应的符号, 而+!#^则是对应的热键, 请以{}包围. 另外, 还有些特殊键, 如回车{enter}, 删除{del},  大写{CapsLock}等.

Run, program: 运行程序, AHK会在%path%中查找. 如Run, NotePad.exe, 其中后缀可省略. 除了程序, 也可以直接打开网页run, www.baidu.com会调用默认浏览器打开百度首页. 也可以打开目录, 如run, %A_MyDocuments将打开我的文档. 此处的%A_MyDocumentsAHK预定义变量.

WinActivate, title_text: 激活指定标题栏的窗口, 注意操作系统环境不同, 标题栏文本的语言也不同. 如打开记事本, 在英文环境下, 标题栏文本是Untitled - notepad, 中文环境下是无标题 - 记事本. 我想, 这里是AHK唯一区分大小写的地方了吧.

WinWaitActive, title_text: 等待指定窗口的激活, 往往同上一起使用, 以确保接下来的命令运行在正确的窗口中.

sleep, num, 停止毫秒

MsgBox, text: 显示对话窗口, 跟文本参数, 只有确定按键.

MsgBox [, options, title, text, timeout]: 单独一个msgbox会提示press ok to continue, 选项显示不同的按钮, 如4yes/no或1ok/cancel,2abort/retry/ignore,3yes/no/cancel等.

InputBox, output_var, title_text, question_text, 以窗口形式获取用户输入

IfMsgBox, Yes/No: 如果对话框点击确定或否, 或者依据选项的不同输入, 来决定下一步

函数

函数一般有这样的形式, var:=func(arg1, arg2, ...).

变量直接用, 字串以'包围, 参数进行数字运算, 函数可嵌套, 有返回值.

SubStr(string, num), 返回从num位置的字串, 1索引

FileExist(path), 文件存在判断

特殊按键

  • {f1}-{f12}

  • {enter/space/esc/tab}

  • {bs/del/ins}

  • {up/down/left/right}

  • {home/end/pgup/pgdn}

  • {capslock/scrolllock/numlock}

  • {ctrl/lctrl/rctrl down/up}, alt, shift, win

  • {+!^#{}}, 仅表示+, !, ^, #, {, }

  • {numpad0-9}, {numpaddot/enter/mult/div/add/sub}数字键盘的键, 按下numlock键时

  • {numpadup/down/left/right/home/end/pgup/pgdn/del/ins/clear}数字键盘的控制键, numlock未按下时

  • {browser_back/forward/refresh/stop/search/favorites/home}, 浏览器的按键

  • {volume_mute/down/up音量键

  • {media_next/prev/stop/play_pause}媒体控制键

预定义变量

%包围, 如%A_WorkingDir%.

脚本属性:

  • 1, 2, 3, 脚本的命令行参数, 0表示参数数目

  • A_ScriptDir, A_ScriptName, A_ScriptFullPath, A_ScriptHwnd运行脚本的目录,文件名,全路径,主窗口句柄.

  • A_LineFile, A_LineNumber, A_ThisFunc, A_ThisLabel表示当前运行命令的文件,行号,函数,标号, 用于错误处理

  • A_AhkVersion, A_AhkPath本程序的版本和路径

  • A_IsUnicode, A_IsCompiled, A_ExitReason是否是unicode, 是否编译, 退出原因

对象

创建对象: (数组或列表, 字典或哈希, 在不同语言中叫法不同)

MyObject := ['one', 'two', 'three', 17]  ; 字面量创建
banana := {'Shape': 'Elongated', 'Color': 'Yellow'}
MyObject := Array('one', 'two', 'three', 17)  ; 函数创建
Banana := Object('Shape', 'Elongated', 'Color', 'Yellow')

添加新元素或改变原键值:

Banana.Consistency := 'Mushy'   
Banana['Pickled'] := True  ;两种方式索引, `.`和`[]`操作符
MyObject.NewKey := 'Shiny'  ;给数组添加键值对
MyObject.InsertAt(Index, Value1, Value2, Value3, ...)  ;多元素插入
MyObject.Push(Value1, Value2, Value3, ...)  ;追加元素

移除键值:

MyObject.NewKey := ''  ; 移除值
RemovedValue := MyObject.Delete(AnyKey)  ; 移除键
NumberOfRemovedKeys := MyObject.Delete(FirstKey, LastKey)
MyObject.Pop()  ; 弹出尾元素
RemovedValue := MyObject.RemoveAt(Index)  ; 移除索引处键
NumberOfRemovedKeys := MyObject.RemoveAt(Index, Length)

这里需要说明的是, ArrayObject是相同的对象, 数组默认的数字索引, 但也可以添加键值对. 则之前的值通过1,2,3索引, 加入的值通过键索引.

对于数组, 第一个元素的索引为1.

另外, 在命令中, 默认的是文本, 似乎不能直接输出MyObject.NewKey, 无论是否以%包围. 变通的方法是赋值给变量, 再将变量以%输出.

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多