# 脚本编译器指令 [v1.1.33+]

## 目录

- 介绍
- 控制脚本行为的指令:

- IgnoreBegin
- IgnoreEnd
- IgnoreKeep

- 控制可执行文件元数据的指令:

- 介绍
- AddResource: 为 .exe 添加一个资源.
- Bin / Base [v1.1.33.10+]: 指定 AutoHotkey 的二进制版本.
- ConsoleApp: 设置 Console 模式.
- Cont: 指定指令的延续行.
- Debug: 显示指令的调试文本.
- ExeName: 指定 .exe 的位置和名称.
- Let: 设置一个用户变量.
- Obey: 执行一个命令或表达式.
- PostExec: 编译后运行程序.
- ResourceID [v1.1.34+]: 为主脚本指定一个非标准的资源 ID.
- SetMainIcon: 设置主图标.
- SetProp: 设置 .exe 的一个属性.
- Set: 设置各种属性.
- UpdateManifest: 更改 .exe 的 manifest.
- UseResourceLang: 更改资源语言.

## 介绍

脚本编译器指令允许用户指定如何通过 Ahk2Exe 编译脚本的细节. 其中一些特点是:

- 能够改变版本信息(如名称, 描述, 版本...).
- 能够为编译后的脚本添加资源.
- 能够调整编译的一些选项.
- 能够从编译后的脚本中删除代码部分.

脚本编译器在源代码中寻找特殊的注释, 并将其识别为编译器指令. 所有的编译器指令都是由字符串 `@Ahk2Exe-` 引入的, 前面有注释标志(通常为 `;`).

## 控制脚本行为的指令

可以通过包装它们在指令中, 从编译后的脚本中删除代码片段:

    MsgBox This message appears in both the compiled and uncompiled script
    ;@Ahk2Exe-IgnoreBegin
    MsgBox This message does NOT appear in the compiled script
    ;@Ahk2Exe-IgnoreEnd
    MsgBox This message appears in both the compiled and uncompiled script

反过来说也是可以的, 即标记代码片段只在编译后的脚本中执行:

    /*@Ahk2Exe-Keep
    MsgBox This message appears only in the compiled script
    */
    MsgBox This message appears in both the compiled and uncompiled script

这比 A_IsCompiled 的优势在于, 在预处理过程中, 代码被完全从编译脚本中移除, 从而使编译脚本更小. 反之亦然: 不需要检查 A_IsCompiled 因为代码在未编译的脚本中的注释块中.

## 控制可执行程序元数据的指令

### 介绍

在这些指令的参数中, 支持以下转义序列: ````, ``,`, ``n`, ``r` 和 ``t`. 无论 参数的位置如何, 都需要对逗号进行转义. "Integer" 是指无符号的 16 位整数(0..0xFFFF).

如果需要, 指令参数可以通过使用 `%`(百分号) 括住变量名来引用以下标准内置变量列表:

组 1: A_AhkPath, A_AppData, A_AppDataCommon, A_ComputerName, A_ComSpec, A_Desktop, A_DesktopCommon, A_MyDocuments, A_ProgramFiles, A_Programs, A_ProgramsCommon, A_ScriptDir, A_ScriptFullPath, A_ScriptName, A_Space, A_StartMenu, A_StartMenuCommon, A_Startup, A_StartupCommon, A_Tab, A_Temp, A_UserName, A_WinDir.

组 2: A_AhkVersion, A_IsCompiled, A_IsUnicode, A_PtrSize.

除了这些变量名之外, 特殊变量 A_WorkFileName 还保存着处理后的 .exe 文件的临时名称. 这可以用来将文件名作为参数传递给任何需要访问生成的 .exe 文件的 PostExec 指令.

另外, 特殊变量 A_PriorLine 包含了紧接当前编译器指令之前的源代码行. 只忽略中间的空白行和注释, 以及任何中间的编译器指令行. 这个变量可以用来从脚本源代码中 "提取" 常量信息, 并在以后的编译器指令中使用它. 一个例子是访问脚本的版本号, 因为它可能会经常改变. 以这种方式访问版本号, 意味着在源代码中只需要更改一次, 更改的内容会被复制到必要的指令中. (有关详情, 请参阅下面的 RegEx 示例.)

同样, 也可以使用下面描述的 Let 和 Obey 指令, 创建格式为 `U_Name` 的特殊用户变量.

除了可用于指令参数外, 所有的变量都可以从任何 RT_MENU, RT_DIALOG, RT_STRING, RT_ACCELERATORS, RT_HTML 和 RT_MANIFEST 文件中访问, 提供给下面的 AddResource 指令.

如果需要, 从上述变量返回的值可以通过在内置变量名称结尾, 结束 `%` 的前面, 包括最多 2 个参数(称为 p2 和 p3) 来进行操作, 所有参数都用波浪号 `~` 分隔. 在 RegExReplace 函数的第 2 个和第 3 个参数中, p2 和 p3 参数将作为原义使用, 以操作返回的值. (请参阅 正则快速参考.) 请注意, p3 是可选的.

要在 p2 或 p3 中包含波浪号作为数据, 在其前面加上重音符, 即 ``~`. 要在 p2 或 p3 中包含重音符作为数据, 请将其加倍, 即 ````.

RegEx 示例:

-     %A_ScriptName~\.[^\.]+$~.exe%

  这将替换扩展名加上前面的句号, 在实际的脚本名称中用 `.exe` 替换.
  (`\.[^\.]+$~.exe` 表示扫描 `.` 后面跟着 1 或多个非-`.` 字符并后面跟着结束字符, 并将其替换为 `.exe`)

- 假设有源代码行中有两个编译器指令, 如下所示:

      CodeVersion := "1.2.3.4", company := "My Company"

      ;@Ahk2Exe-Let U_version = %A_PriorLine~U)^(.+"){1}(.+)".*$~$2%

      ;@Ahk2Exe-Let U_company = %A_PriorLine~U)^(.+"){3}(.+)".*$~$2%

  这些指令将版本号 `1.2.3.4` 复制到特殊变量 `U_version`, 将公司名称 `My Company` 复制到特殊变量 `U_company` 中, 供后面其他指令使用.
  (第一个正则表达式中的 `{1}` 在第二个正则表达式中改为 `{3}` 以便在第三个 `"` 之后选择提取公司名称.)

其他示例: 其他的工作示例可以从这里下载和检查.

### AddResource

将资源添加到已编译的可执行文件中. (另请参阅下面的 UseResourceLang)

    ;@Ahk2Exe-AddResource FileName , ResourceName

FileName
  要添加的资源的文件名. 资源的类型(作为整数或字符串) 可以通过附加一个星号显式指定: `*type Filename`. 如果省略, Ahk2Exe 会根据文件扩展名自动检测类型.
ResourceName
  (可选) 资源将具有的名称(可以为整数或字符串). 如果省略, 则默认为文件的名称(没有路径), 大写.

下面是缺省情况下触发它们的通用标准资源类型和扩展的列表.

- 2 (RT_BITMAP): `.bmp`, `.dib`
- 4 (RT_MENU)
- 5 (RT_DIALOG)
- 6 (RT_STRING)
- 9 (RT_ACCELERATORS)
- 10 (RT_RCDATA): 每一个其他的扩展名.
- 11 (RT_MESSAGETABLE)
- 12 (RT_GROUP_CURSOR): `.cur` (尚未支持)
- 14 (RT_GROUP_ICON): `.ico`
- 23 (RT_HTML): `.htm`, `.html`, `.mht`
- 24 (RT_MANIFEST): `.manifest`. 如果没有指定资源的名称, 则默认为 `1`

示例 1: 替换标准图标(除主图标外):

    ;@Ahk2Exe-AddResource Icon1.ico, 160  ; 替换掉 '蓝色 H'
    ;@Ahk2Exe-AddResource Icon2.ico, 206  ; 替换掉 '绿色 S'
    ;@Ahk2Exe-AddResource Icon3.ico, 207  ; 替换掉 '红色 H'
    ;@Ahk2Exe-AddResource Icon4.ico, 208  ; 替换掉 '红色 S'

示例 2: [v1.1.34+] 要把另一个脚本作为单独的 RCDATA 资源包括在内(请参阅 嵌入式脚本):

    ;@Ahk2Exe-AddResource MyScript.ahk, MYRESOURCE

### Bin / Base [v1.1.33.10+]

指定用于生成 .exe 文件的 AutoHotkey 的基础版本. 这个指令可以被 GUI 或 CLI 中指定的基文件参数所覆盖. 如果有必要, 这个指令可以被多次指定, 但只能在最顶层的脚本文件中指定(也就是说, 不能在 #Include 文件中). 编译器将为每个发现的 Bin/Base 指令至少运行一次. (如果要在这个指令上附加一个实际的注释, 必须使用 `;` 标志. 要想真正注释这个指令, 请在第一个注释标志后插入一个空格.)

    ;@Ahk2Exe-Bin  [Path\]Name , [Exe_path\][Name], Codepage ; Deprecated
    ;@Ahk2Exe-Base [Path\]Name , [Exe_path\][Name], Codepage ; [v1.1.33.10+]

[Path\]Name
  要使用的 *.bin 文件或在 [v1.1.33.10+] 中的 *.exe 文件. 如果没有提供扩展名, 则假定为 `.bin`. 可以为 Name 指定一个 DOS 掩码, 例如 `ANSI*`, `Unicode 32*`, `Unicode 64*` 或为这三种掩码指定 `*bit`. 如果没有指定路径, 则会搜索编译器文件夹中的标准 *.bin 或 *.exe 文件. 编译器将为每个匹配的 *.bin 文件运行. 任何内置变量替换的使用都必须是来自上述的组 1.
[Exe_path\][Name]
  (可选) 要给 .exe 的文件名. 任何提供的扩展名都将被替换为 `.exe`. 如果没有指定路径, 则会在脚本文件夹中创建 .exe 文件. 如果没有指定名称, .exe 将使用默认名称. (这个参数可以被 ExeName 指令覆盖.)
Codepage
  (可选) 覆盖用于处理脚本文件的默认代码页. (脚本应该以 Unicode 字节顺序标记(BOM) 开始, 因此不需要使用这个参数.)

### ConsoleApp

将可执行子系统更改为控制台模式.

    ;@Ahk2Exe-ConsoleApp

### Cont

指定前指令的延续行. 这允许格式化一个长行指令, 以便在源代码中容易读取.

    ;@Ahk2Exe-Cont Text

Text
  在处理前一个指令行之前, 附加到该指令行的文本. 文本开始于 `Cont` 关键字后面的单个空格之后.

### Debug

显示带有支持文本的消息框, 用于调试.

    ;@Ahk2Exe-Debug Text

Text
  要显示的文本. 在 `%` 符号之间包含的任何特殊变量, 请参阅 (manipulated) 内容.

### ExeName

指定生成的 .exe 文件的位置和名称.(另请参阅 Base 指令.) 这个指令可以被 GUI 或 CLI 中指定的输出文件覆盖.

    ;@Ahk2Exe-ExeName [Path\][Name]

[Path\][Name]
  .exe 文件的名称. 任何提供的扩展名都将被替换为 `.exe`. 如果没有指定路径, .exe 将在脚本文件夹中创建. 如果没有指定名称, .exe 将使用默认名称.

示例:

    ;@Ahk2Exe-Obey U_bits, = %A_PtrSize% * 8
    ;@Ahk2Exe-Obey U_type, = "%A_IsUnicode%" ? "Unicode" : "ANSI"
    ;@Ahk2Exe-ExeName %A_ScriptName~\.[^\.]+$%_%U_type%_%U_bits%

### Let

创建(或修改) 一个或多个用户变量, 这些变量可以通过 `%U_Name%` 来访问, 类似于内置变量(见上文).

    ;@Ahk2Exe-Let Name = Value , Name = Value, ...

Name
  变量的名称(带或不带前缀 `U_`).
Value
  要使用的值.

### Obey

执行独立于 AutoHotkey 的命令或表达式, 结果为 `U_Name`.

    ;@Ahk2Exe-Obey Name, CmdOrExp , Extra

Name
  要接收结果的变量名称(带或不带前缀 `U_`).
CmdOrExp

  要执行的命令或表达式.

  Command 格式必须使用 Name 作为输出变量(通常是第一个参数), 例如

      ;@Ahk2Exe-Obey U_date, FormatTime U_date`, R D2 T2

  Expression 的格式必须以 `=` 开头, 例如

      ;@Ahk2Exe-Obey U_type, = "%A_IsUnicode%" ? "Unicode" : "ANSI"

  表达式可以用命令格式来写, 例如

      ;@Ahk2Exe-Obey U_bits, U_bits := %A_PtrSize% * 8

  如果需要, 用 ``n` 分隔多个命令和表达式.

Extra
  (可选) 数字(1-9) 指定要返回的额外结果的数量. 例如, 如果 extra = 2, 结果将以 `U_name`, `U_name1` 和 `U_name2` 的形式返回. `name` 中的值必须先由表达式或命令设置.

### PostExec

指定在编译成功后, 在任何压缩程序应用于 .exe 文件之前(或之后) 要执行的程序.

    ;@Ahk2Exe-PostExec Program [parameters] , When, WorkingDir, Hidden, IgnoreErrors

Program [parameters]
  要执行的程序, 加上参数. 要允许访问已处理的 .exe 文件, 请指定特殊变量 A_WorkFileName 作为加引号的参数, 如 `"%A_WorkFileName%"`. 如果程序更改了 .exe, 则必须将更改的 .exe 移回程序指定的输入文件 `%A_WorkFileName%`. (注意, .exe 将包含二进制数据.)
When

  (可选) 在执行任何压缩之前, 则置空. 否则设置为压缩后运行的数字如下:

  - 0 - 只在没有指定压缩时运行.
  - 1 - 只在指定 MPRESS 压缩时运行.
  - 2 - 仅在指定 UPX 压缩时运行.
WorkingDir [v1.1.33.03+]
  (可选) 程序的工作目录. 即使包含空格, 也不要用双引号括起来. 如果省略, 将使用编译器的目录(Ahk2Exe).
Hidden [v1.1.33.03+]
  (可选) 如果设置为 1, 程序将被隐藏启动.
IgnoreErrors [v1.1.33.03+]
  (可选) 如果设置为 1, 则不会向用户报告程序启动或运行过程中发生的任何错误.

示例 1: (要使用这些例子, 首先要下载 BinMod.ahk 并根据下载的脚本中的说明进行编译.)

这个例子可以用来删除生成的 .exe 文件中对 "AutoHotkey" 的引用, 以掩盖它是一个编译过的 AutoHotkey 脚本:

    ;@Ahk2Exe-Obey U_au, = "%A_IsUnicode%" ? 2 : 1    ; Script ANSI or Unicode?
    ;@Ahk2Exe-PostExec "BinMod.exe" "%A_WorkFileName%"
    ;@Ahk2Exe-Cont  "%U_au%2.>AUTOHOTKEY SCRIPT<. DATA              "

示例 2: 这个例子将改变一个 UPX 压缩的 .exe 文件, 使它不能用 `UPX -d` 来解压:

    ;@Ahk2Exe-PostExec "BinMod.exe" "%A_WorkFileName%"
    ;@Ahk2Exe-Cont  "11.UPX." "1.UPX!.", 2

在 BinMod.ahk 脚本中还有其他例子.

### ResourceID

指定一个非标准的资源 ID, 用于使用 .exe 基文件编译的主脚本(请参阅 嵌入脚本). 这个指令可以被 GUI 或 CLI 中指定的资源 ID 所覆盖. 如果该指令出现在由 AddResource 指令插入的脚本中, 则会被忽略.

    ;@Ahk2Exe-ResourceID Name

Name
  要使用的资源 ID. 数字资源 ID 应该由一个哈希符号(#) 和一个十进制数字组成.

### SetMainIcon

覆盖用于编译的自定义 EXE 图标. (要改变其他图标, 请参阅 AddResource 示例.) 这个指令可以被 GUI 或 CLI 中指定的图标文件覆盖.

    ;@Ahk2Exe-SetMainIcon IcoFile

IcoFile
  (可选) 要使用的图标文件. 如果省略, 则使用默认的 AutoHotkey 图标.

### SetProp

更改已编译可执行文件的版本信息中的属性. 注意, 无论指定属性的顺序如何, 所有属性都按字母顺序处理.

    ;@Ahk2Exe-SetProp Value

Prop

  要更改的属性的名称. 必须是以下所列之一.

  属性 | 描述
  --- | ---
  CompanyName | 更改公司名称.
  Copyright | 更改法定版权信息.
  Description | 更改文件说明.
  FileVersion | 更改文件版本, 包括文本和原始二进制格式. (有关详情, 请参阅下面的 Version.)
  InternalName | 更改内部名称.
  Language | 更改语言代码. 请注意, 十六进制数字必须有 `0x` 前缀.
  LegalTrademarks | 更改合法商标信息.
  Name | 更改产品名称和内部名称.
  OrigFilename | 更改原始文件名信息.
  ProductName | 更改产品名称.
  ProductVersion | 更改产品版本, 包括文本和原始二进制格式. (有关详情, 请参阅下面的 Version.)
  Version | 更改文件版本和产品版本, 包括文本和原始二进制格式. Ahk2Exe 用可能出现在版本文本开头的以周期限定的数字(最多 4 个) 填充二进制版本字段. 未填写的字段被设置为零. 例如, `1.3-alpha` 会产生 `1.3.0.0` 的二进制版本号. 如果这个属性没有被修改, 它默认为用于编译脚本的 AutoHotkey 版本.

Value
  要设置属性的值.

### Set

改变 SetProp 指令未覆盖的编译后的可执行文件版本信息中的其他杂项属性. 请注意, 所有的属性都是按字母顺序处理的, 而不考虑它们被指定的顺序. 此指令仅用于特殊用途.

    ;@Ahk2Exe-Set Prop, Value

Prop
  要更改的属性名称.
Value
  属性将设置的值.

### UpdateManifest

更改 .exe 清单中的详细信息. 此指令仅供特殊用途.

    ;@Ahk2Exe-UpdateManifest RequireAdmin , Name, Version, UIAccess

RequireAdmin
  设置为 1, 可执行文件运行时需要管理员权限. 设置为 2, 可执行文件运行时请求最高可用权限. 设置为 0, 则保持不变.
Name
  (可选) 要在清单中设置的名称.
Version
  (可选) 要在清单中设置的版本.
UIAccess
  (可选) 设置为 1, 使清单中的 UIAccess 为 true.

### UseResourceLang

更改 AddResource 使用的资源语言. 这条指令是位置性的, 会影响后面所有的 AddResource 指令.

    ;@Ahk2Exe-UseResourceLang LangCode

LangCode
  语言代码. 请注意, 十六进制数字必须有 `0x` 前缀. 默认的资源语言是美国英语(0x0409).

dftg