# 常见问题(FAQ)

## 目录

一般故障排查

- 如果 AutoHotkey 无法安装我该怎么办?
- 如何恢复 .ahk 文件的右键菜单选项?
- 为什么我的脚本在前一个系统运行良好却无法工作于 Windows xxx?
- 我该如何处理用户账户控制(UAC) 导致的问题?
- 因为脚本出错而无法启动, 我不能通过托盘图标编辑我的脚本. 我能在别的地方找到我的脚本吗?
- 如何查找代码中的错误并修复呢?
- 为什么 Run 函数不能启动我的游戏或程序?
- 为什么脚本中的非 ASCII 字符显示或发送不正确?
- 为什么在某些游戏中热字串, Send 和 MouseClick 不起作用?
- 如何在玩游戏或平时 CPU 高负荷运行时改善性能?
- 我的杀毒软件把 AHK 归为恶意软件. 它真的含有病毒吗?

常见任务

- 我可以在哪里找到官方发行版或更旧的版本?
- 可以在 USB 驱动器中运行 AHK 代码吗?
- 如何获取命令行操作的输出?
- 如何让一个脚本关闭, 暂停, 挂起或重启其他的脚本?
- 如何在不退出脚本的情况下停止重复的动作?
- 如何在任意编辑器中获取上下文相关的 AutoHotkey 函数帮助?
- 如何检测一个网页何时加载完毕?
- 如何比较或操作日期与时间?
- 如何发送当前的日期和/或时间?
- 如何发送文本到不活跃或隐藏的窗口?
- 如何控制 Winamp, 即使在它未激活时?
- 如何改变 MsgBox 的按钮名称?
- 如何改变默认编辑器, 即通过上下文菜单或托盘图标打开的那个?
- 如何保存我的 GUI 控件的内容?
- 我能使用 AHK 画点什么吗?
- 如何在窗口出现, 关闭或变成[不]活跃时执行操作?

热键, 热字串和重映射

- 如何让我的热键和热字串在 PC 启动时自动生效?
- 我在把鼠标按键作为热键使用时遇到问题. 能提供一些建议吗?
- 如何将 tab 和空格键设置为热键?
- 如何将按键或鼠标按键重映射成其他键?
- 如何检测按键或按钮的双击?
- 如何让热键或热字串只在特定的程序中有效? 换句话说, 我想让特定的按键执行它原来的功能, 除了当指定的窗口激活时.
- 如何让前缀按键执行它原来的功能, 而不是什么都不做?
- 如何改变或禁用 Windows 内置的快捷键, 例如 Win+U(辅助工具管理器) 和 Win+R(运行)?
- 如何在热字串中使用通配符或正则表达式?
- 如何将不存在于我键盘布局中的键作为热键使用?
- 我的小键盘上有个特殊的 000 键. 可以把它设成热键吗?

## 一般故障排查

### 如果 AutoHotkey 无法安装我该怎么办?

7-zip 错误: 使用 7-zip 或其他解压缩软件解压安装程序 EXE, 然后运行 setup.exe 或 Installer.ahk(拖拽 Installer.ahk 到 AutoHotkeyU32.exe 上即可).

AutoHotkey 的安装程序(exe 文件) 以 7-zip 自解压格式打包, 安装时尝试解压文件到用户的临时文件夹并执行编译的脚本进行安装. 有时系统策略或其他原因阻止了文件的解压或执行. 通常在遇到这种情况时会显示 "7-zip 错误" 这样一个消息. 手动解压文件到不同的目录或许能解决该问题.

安装挂死: 如果安装窗口显示空白或不显示, 尝试下面的解决方案:

- 在安装程序启动时, 按住 `Ctrl` 或 `Shift`. 如果出现 UAC 提示, 按住 `Ctrl` 或 `Shift` 并点击“是或继续". 你应该能看到询问是否你要以默认选项安装的提示.
- 以命令行选项安装. 如果你手动解压安装程序的 Exe 文件, 使用 `setup.exe /S` 或 `AutoHotkeyU32.exe Installer.ahk /S`.

其他: 以上建议基本能解决遇到的大多数问题. 更进一步的援助, 请到论坛发帖求助.

### 如何恢复 .ahk 文件的右键菜单选项?

通常情况下, 如果安装了 AutoHotkey, 右键单击 AutoHotkey 脚本文件(.ahk) 应该会提供以下选项:

- Run Script(运行脚本)
- Compile Script(编译脚本)(取决于 Install script compiler 安装选项)
- Edit Script(编辑脚本)
- Run as administrator(以管理员权限运行)(如果在 AutoHotkey 安装时启用了 UAC)
- Run with UI Access(以 UI Access 运行)(如果在安装期间启用了该选项)

有时这些选项会被当前用户配置文件中的设置覆盖, 例如是否使用 Open With(打开方式) 更改了打开 .ahk 文件的默认程序. 可以通过删除以下注册表键来解决此问题:

    HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.ahk\UserChoice

这可以通过应用此注册表文件来完成.

还可能需要修复默认注册表值, 方法是重新安装 AutoHotkey 或运行 AutoHotkey Setup(从开始菜单) 并在窗口顶部选择 apply(应用).

### 为什么我的脚本在前一个系统运行良好却无法工作于 Windows xxx?

这个问题有许多的影响因素, 例如:

- 我已经升级了我的电脑或系统, 现在我的脚本无法工作.
- 当程序以管理员权限运行时, 热键或热字串不工作.
- 系统阻止自动化操作(例如, 磁盘管理忽略 Send).

当切换操作系统时, 发生的变动也许影响了你的脚本. 例如, 你的新电脑, 可能有不同的驱动或安装了其他的软件. 如果你升级了新版本的 AutoHotkey, 确认你之前使用的是哪个版本并检查更新历史和二进制兼容性.

也请参考以下问题:

### 我该如何处理用户账户控制(UAC) 导致的问题?

用户账户控制(UAC) 是导致问题的常见原因, 特别在系统由 Windows XP/Vista/7 升级到 Vista/7/8/10 时. UAC 存在于 Windows Vista 及更后的系统, 在新系统或新安装时默认是被激活的, 并且在 Windows 8 及之后的系统中很难被禁止.

在默认情况下, UAC 保护 "提权" 程序(程序以管理员权限运行) 不被非提权程序自动化, 因为这将允许他们绕过安全限制. 热键也将被屏蔽, 因此, 非提权程序不能监视用于提权程序的输入.

UAC 也阻止了 SendPlay 和 BlockInput 的正常工作.

常见的解决方案如下:

- 选中激活安装器界面上的 增加 'Run with UI Access'(以 UI Access 运行) 到上下文菜单 这个选项. 在开始菜单中运行安装程序, 该选项能被开启或关闭而不用重新安装 AutoHotkey. 该选项开启后, 右键选中的脚本文件选择 Run with UI Access(以 UI Access 运行), 或者使用命令行例如, `"AutoHotkeyU32_UIA.exe" "要打开的脚本文件名.ahk"`(可能需要包括完整路径).
- 以管理员权限运行脚本. 注意这样的脚本中运行的任何程序也具有管理员权限.
- 关闭用户账户控制(不推荐), 在 Windows 8 或之后的版本您还必须禁用 "以管理员核准模式运行所有管理员(Run all administrators in Admin Approval Mode)" 安全设置(也不推荐).
- 完全禁用 UAC. 不推荐这样做, 在 Windows 8 或之后的系统中会导致系统出现一些问题, 例如无法运行 Edge 和应用商店以及其安装的程序.

### 因为脚本出错而无法启动, 我不能通过托盘图标编辑我的脚本. 我该怎么办?

首先您必须修复您脚本中的错误才能找回 AHK 的系统托盘图标. 但是您必须先找到您的脚本.

请在下面的文件夹中寻找 AutoHotkey.ahk 文件:

- 你的 文档(或 我的文档) 文件夹.
- 安装 AutoHotkey 的文件夹, 通常是 C:\Program Files\AutoHotkey. 如果您正在使用 AutoHotkey 而没有安装它, 请查看包含 AutoHotkey.exe 的目录.

如果你直接运行另一个 AutoHotkey 可执行文件, 脚本名称取决于可执行文件. 例如, 如果您运行的是 AutoHotkey32.exe, 那么请查找 AutoHotkey32.ahk. 请注意, 根据你的系统设置这 ".ahk" 部分(扩展名) 可能是隐藏的, 但是文件一定有类似 这样的图标.

您可以随时从右键菜单中选择 Edit Script 来编辑 AHK 脚本. 如果这个右键菜单命令无效, 您还可以用记事本或其他文本编辑器来编辑.

如果您是从开始菜单中运行 AutoHotkey 或是直接双击 AutoHotkey.exe 来运行(不包含任何命令行参数), 那么它会查找上述的脚本来执行. 否则, 您可以在任意位置创建一个其他名称的 AHK 脚本文件(something.ahk), 然后运行 AHK 脚本, 而不是 AutoHotkey.

另请参阅命令行参数 "Script Filename"和 AutoHotkey.exe 的可移植性.

### 如何查找代码中的错误并修复呢?

对于简单的脚本, 请参阅调试脚本. 要查看变量的内容, 请使用 MsgBox 或 ToolTip. 对于复杂的脚本, 请参阅交互式调试.

### 为什么 Run 函数不能启动我的游戏或程序?

有些程序需要在它们自己的目录下运行(不能确定时, 通常最好这样做). 例如:

    Run A_ProgramFiles "\Some Application\App.exe", A_ProgramFiles "\Some Application"

如果你想要打开的程序位于 `A_WinDir "\System32"` 并且你是在 64 位系统中使用 32 位的 AutoHotkey, File System Redirector 将会产生干扰. 为避免该问题, 请使用 `A_WinDir "\SysNative"` 代替; 这是一个仅在 64 位系统上运行的 32 位程序可见的虚拟目录.

### 为什么脚本中的非 ASCII 字符显示或发送不正确?

简短的回答: 将脚本保存为 UTF-8.

非 ASCII 字符由不同的二进制值来表示, 这取决于所选择的编码. 为了让这些字符被正确的解释, 您的文本编辑器和 AutoHotkey 必须在 同一个代码页. AutoHotkey v2 默认所有的脚本文件都是 UTF-8, 尽管可以通过 /CP 命令行开关来重写.

要在记事本中保存为 UTF-8 文件, 请在另存为对话框的 编码 下拉菜单中选择 UTF-8 或 UTF-8 with BOM. 请注意, Windows 10 1903 及以后版本的记事本默认为 UTF-8.

要读取缺少字节顺序标记的其他 UTF-8 文件, 请使用 `FileEncoding "UTF-8-RAW"`, FileRead 的 `*P65001` 选项, 或 FileOpen 的第三个参数`"UTF-8-RAW"`. `-RAW` 后缀可以省略, 但是在这种情况下, 任何新创建的文件都会有一个字节顺序标记.

请注意, 使用标准 INI 函数访问 INI 文件不支持 UTF-8; 它们必须保存为 ANSI 或 UTF-16.

### 为什么在某些游戏中 Hotstrings, Send 和 Click 不起作用?

不是所有的游戏都支持 AHK 发送键击和点击或获取像素颜色.

有一些替代方法, 请试试下面提及的方案. 如果这些都无效, 那么 AHK 可能不适用于您的游戏. 一些游戏含有防止反破解和作弊的措施, 如 GameGuard 和 Hackshield. 如果是, 则 AutoHotkey 很可能无法用于该游戏.

- 通过 SendPlay 函数, SendMode Play 或热字串选项 SP 来使用 SendPlay.

      SendPlay "abc"

      SendMode "Play"
      Send "abc"

      :SP:btw::by the way

      ; 或

      #Hotstring SP
      ::btw::by the way

  注意: SendPlay 在启用了用户账户控制时可能没有效果, 即使以管理员权限运行脚本.

- 使用 SetKeyDelay 增加延迟. 例如:

      SetKeyDelay 0, 50
      SetKeyDelay 0, 50, "Play"

- 试试 ControlSend, 在其他 Send 模式无效时它可能可以:

      ControlSend "abc",, GameTitle

- 试试在多种发送方式中使用按键的按下和弹起事件:

      Send "{KEY Down}{KEY Up}"

- 试试在按键的按下事件和弹起事件之间使用 Sleep:

      Send "{KEY down}"
      Sleep 10 ; 试试不同的毫秒数.
      Send "{KEY up}"

### 如何在玩游戏或平时 CPU 高负荷运行时改善性能?

如果脚本中的 Hotkeys, Clicks 或 Sends 在 CPU 高负荷运行时明显比正常情况下要慢, 提高脚本程序的优先级或许会有帮助. 要提高脚本进程的优先级, 在脚本开始的部分写入下面这行语句:

    ProcessSetPriority "High"

### 我的杀毒软件把 AutoHotkey 或已编译脚本标记为恶意软件. 它真的是病毒吗?

尽管文件被感染确实是可能的, 但多数情况下这些警报都是 误报, 这意味着防病毒程序是错误的. 一个常见的建议是将文件上传到在线服务, 例如 virustotal 或 Jotti 看看其他杀毒软件的查杀结果. 如果有疑问, 您可以将该文件发送给您的杀毒软件供应商确认. 这也可能有助于我们和其他 AutoHotkey 用户, 因为供应商可能会确认这是误报和改善他们的产品与 AutoHotkey 的兼容性.

对于已压缩的编译脚本来说, 误报可能更为常见, 例如使用 UPX(AutoHotkey 1.0 默认, AutoHotkey 1.1 中移除) 或 MPRESS(在AutoHotkey 1.1 中可选). AutoHotkey 安装时不带有压缩程序, 编译脚本时也默认不压缩.

## 常见任务

### 我可以在哪里找到官方发行版或更旧的版本?

访问 AutoHotkey 下载页面.

### 可以在 USB 驱动器中运行 AHK 吗?

请参阅 AutoHotkey.exe 的可移植性.

### 如何检索命令行操作的输出?

测试表明, 由于文件缓存的原因, 对于较少量的输出, 使用临时文件获取会比较快. 事实上, 如果文件在使用后立即被删除, 通常它并没有被真正地写到磁盘上. 例如:

    RunWait A_ComSpec ' /c dir > C:\My Temp File.txt'
    VarToContainContents := FileRead("C:\My Temp File.txt")
    FileDelete "C:\My Temp File.txt"

要避免使用临时文件(特别是在输出比较大时), 可以考虑使用 Run 函数示例中展示的 Shell.Exec() 方法.

### 如何让一个脚本关闭, 暂停, 挂起或重启其他的脚本?

首先, 这里有个关闭另一个脚本的例子:

    DetectHiddenWindows True  ; 许脚本隐藏的主窗口能被检测到.
    SetTitleMatchMode 2  ; 避免需要指定以下文件的完整路径.
    WinClose "ScriptFileName.ahk - AutoHotkey"  ; 更新它为脚本的实际名称(区分大小写).

其次 suspend 或 pause 另一个脚本, 请把上面脚本的最后一行替换为下列语句中的一行:

    PostMessage 0x0111, 65305,,, "ScriptFileName.ahk - AutoHotkey"  ; Suspend(挂起).
    PostMessage 0x0111, 65306,,, "ScriptFileName.ahk - AutoHotkey"  ; Pause(暂停).
    PostMessage 0x0111, 65303,,, "ScriptFileName.ahk - AutoHotkey"  ; Reload(重载).

### 如何在不退出脚本的情况下停止重复的动作?

通过按下热键来暂停或继续整个脚本, 需要给 Pause 指定热键, 如此例所示:

    ^!p::Pause  ; 按下 Ctrl+Alt+P 暂停脚本. 再次按下恢复.

要停止在 Loop 中重复的操作, 请参考下面这个可运行示例, 热键启动和停止自身重复动作. 换句话说, 按下热键将开始循环. 再次按下同样的热键将停止循环.

    #MaxThreadsPerHotkey 3
    #z::  ; Win+Z 热键(可根据您的喜好改变此热键).
    {
        static KeepWinZRunning := false
        if KeepWinZRunning  ; 这表明一个潜在的线程已经正在下面的循环中运行了.
        {
            KeepWinZRunning := false  ; 向那个线程的循环发出停止的信号.
            return  ; 结束此线程, 这样才可以让下面的线程恢复并得知上一行所做的更改.

    }
        ; Otherwise:
        KeepWinZRunning := true
        Loop
        {
            ; 以下四行是您要重复的动作(可根据您的需要修改它们):
            ToolTip "Press Win-Z again to stop this from flashing."
            Sleep 1000
            ToolTip
            Sleep 1000
            ; 但请不要修改下面的内容.
            if not KeepWinZRunning  ; 用户再次按下 Win-Z 来向循环发出停止的信号.
                break  ; 跳出此循环.
        }
        KeepWinZRunning := false  ; 复位, 为下一次使用热键做准备.
    }
    #MaxThreadsPerHotkey 1

### 如何在任意编辑器中获取上下文相关的 AutoHotkey 函数帮助?

为此 Rajat 创建了这个脚本.

### 如何检测一个网页何时加载完毕?

对于 Internet Explorer, 可能最可靠的方法是使用 DllCall 和 COM 正如 www.autohotkey.com/forum/topic19256.html 所演示的. 此外, 获取地址栏及状态栏相关内容的方法在 www.autohotkey.com/forum/topic19255.html 中被提到.

旧的, 稳定性稍差的方法:下面示例中的技术对使用 MS Internet Explorer 打开大多数网页时都有效. 类似的方法可能也适用于其他浏览器:

    Run "www.yahoo.com"
    MouseMove 0, 0  ; 阻止状态栏显示鼠标悬停链接, 而不是 "完成".
    WinWait "Yahoo! - "
    WinActivate
    if StatusBarWait("完成", 30)
        MsgBox "The page is done loading."
    else
        MsgBox "The wait timed out or the window was closed."

### 如何比较或操作日期与时间?

DateAdd 函数能对 YYYYMMDDHH24MISS 格式表示的时间字符串加上或减去一些天数, 小时, 分钟或秒. 后面的例子从指定的时间中减去 7 天:

    Result := DateAdd(VarContainingTimestamp, -7, "days")

要计算两个日期或时间之间的时间量, 请参阅 DateDiff, 其中给出了一个示例. 此外, 内置变量 A_Now 包含了当前本地时间. 最后, 这里有一些内置的 日期/时间变量, 也可以使用 FormatTime 函数来创建自定义格式的日期/时间字符串.

### 如何发送当前的日期和/或时间?

请使用 FormatTime 或日期和时间的内置变量..

### 如何发送文本到不活跃或隐藏的窗口?

请使用 ControlSend.

### 如何控制 Winamp, 即使在它未激活时?

请参阅自动化 Winamp.

### 如何改变 MsgBox 的按钮名称?

这里有个例子.

### 如何改变默认编辑器, 即通过上下文菜单或托盘图标打开的那个?

在 Edit 的示例部分可以找到能让您改变默认编辑器的脚本.

### 如何保存我的 GUI 控件的内容?

请使用 Gui.Submit. 例如:

    MyGui := Gui()
    MyGui.Add("Text",, "Enter some Text and press Submit:")
    MyGui.Add("Edit", "vMyEdit")
    MyGui.Add("Button",, "Submit").OnEvent("Click", Submit)
    MyGui.Show

    Submit(*)
    {
        Saved := MyGui.Submit(false)
        MsgBox "Content of the edit control: " Saved.MyEdit
    }

### 我能使用 AHK 画点什么吗?

请参阅 tic 写的 GDI+ 标准库. 它可以通过一些基本方法以有限的方式使用 Gui.

### 如何在窗口出现, 关闭或变成[不]活跃时开始一个动作?

使用 WinWait, WinWaitClose 或 WinWait[Not]Active.

这里列出了用户自己的解决办法, 例如 OnWin.ahk 和 [How to] Hook on to Shell to receive its messages.

## 热键, 热字串和重映射

### 如何让我的热键和热字串在 PC 启动时自动生效?

有几种方法可以让脚本(或任何程序) 在每次启动 PC 时自动启动. 最简单的方法是在开始菜单的启动文件夹中放置一个脚本的快捷方式:

1. 找到脚本文件后选中它, 接着按下 `Ctrl`+`C`.
2. 按下 `Win`+`R` 打开运行对话框, 然后输入 `shell:startup` 点击确定或按下 `Enter`. 这将打开当前用户的启动文件夹. 要打开所有用户的启动文件夹, 输入 `shell:common startup`(不过, 在这种情况下, 您必须以管理员权限进行).
3. 在文件夹窗口里右击, 点击 "粘贴快捷方式". 脚本的快捷方式现在应该在启动文件夹中了.

### 我在把鼠标按键作为热键使用时遇到问题. 能提供一些建议吗?

鼠标左键和右键应该可以正常设置为热键(例如, 热键 `#LButton::` 为 `Win`+左键). 同样地, 鼠标中键和鼠标滚轮的转动应该可以正常地设置为热键, 除非鼠标驱动直接控制这些按键.

如果您的鼠标驱动让系统可以看见这些按键的点击时, 第四个按键(XButton1) 和第五个按键(XButton2) 也可以设置为热键. 如果它们不可见 -- 或您的鼠标除了您使用的五个按键外还有更多的按键 -- 您可以尝试配置鼠标附带的软件(有时需要通过控制面板或开始菜单访问) 来实现当您按下其中的按键时发送键击. 然后可以在脚本中把这样的键击设置为热键. 例如, 如果您配置第四个按键来发送 `Ctrl`+`F1`, 然后在脚本中通过使用 `^F1::` 您可以把这个按键间接的设置为热键.

如果您有五键鼠标, 其中的第四和第五个按键不可见, 您可以尝试把鼠标驱动改变为 OS 自带的默认驱动. 这里假设您特殊的鼠标使用自己的驱动并且您不使用鼠标自带软件提供的功能.

### 如何将 tab 和空格键定义为热键?

使用它们的按键名称(Tab 和 Space) 而不用它们的字符. 例如, `#Space` 为 `Win`+`Space`, 而 `^!Tab` 为 `Ctrl`+`Alt`+`Tab`.

### 如何将按键或鼠标按钮重映射成其他键?

这在重映射页面进行了描述.

### 如何检测按键或按钮的双击?

像下面那样使用热键的内置变量:

    ~Ctrl::
    {
        if (ThisHotkey = A_PriorHotkey && A_TimeSincePriorHotkey < 200)
            MsgBox "double-press"
    }

### 如何让热键或热字串只在特定的程序中有效? 换句话说, 在特定的窗口不活动时我想让特定的按键执行它原来的功能.

首选的方法是使用 #HotIf. 例如:

    #HotIf WinActive("ahk_class Notepad")
    ^a::MsgBox "You pressed Control-A while Notepad is active."

### 如何让前缀按键执行它原来的功能, 而不是什么都不做?

请参考下面的例子, 其中把 Numpad0 作为前缀键:

    Numpad0 & Numpad1::MsgBox "You pressed Numpad1 while holding down Numpad0."

现在, 要让 Numpad0 在没有像上面那样用来触发热键时发送真正的 Numpad0 键击, 需要添加下面的热键:

     $Numpad0::Send "{Numpad0}"

使用前缀 $ 是为避免产生关于无效循环的警告对话框(因为此热键 "发送了它自己"). 此外, 上述动作在释放此按键的时候发生.

### 如何改变或禁用 Windows 内置的快捷键, 例如 Win+U(辅助工具管理器) 和 Win+R(运行)?

这里有一些示例.

### 如何在热字串中使用通配符或正则表达式?

使用 polyethene 写的脚本(含示例).

### 如何将不存在于我键盘布局中的键作为热键使用?

请参阅特殊按键.

### 我的小键盘上有个特殊的 000 键. 可以把它设成热键吗?

You can. 这个示例脚本将 `000` 键设成等号键. 你可以通过使用你的代码替换 `Send "="` 这行来更改这个动作.

dftg