# Loop (注册表)

获取指定的注册表子键的内容, 每次一个项目.

## 新语法 [v1.1.21+]

    Loop, Reg, KeyName , Mode

### 参数

Reg

  原义单词 `Reg`(不区分大小写), 不可用变量或表达式.

KeyName

  注册表键的全名, 如 `HKLM\Software` 或 `%FullPathOfKey%`.

  必须以 HKEY_LOCAL_MACHINE, HKEY_USERS, HKEY_CURRENT_USER, HKEY_CLASSES_ROOT 或 HKEY_CURRENT_CONFIG(或这些的缩写, 如 HKLM) 开始. 要访问远程注册表, 请在前面加上计算机名和冒号, 就像在本例中一样: \\workstation01:HKEY_LOCAL_MACHINE

Mode

  如果为空或省略, 则只包含值且不递归子键. 否则, 指定一个或多个下列字母:

  - K = 包含键名.
  - V = 包含键值. K 和 V 都被省略时, 默认包含键值.
  - R = 递归子键. 若省略 R, KeyName 下的子键中的键名和键值都不会被包含.

## 传统语法

过时的: 不推荐在新脚本中使用此语法. 而是使用新语法.

    Loop, RootKey , Key, IncludeSubkeys?, Recurse?

### 参数

RootKey

  必须为 HKEY_LOCAL_MACHINE(或 HKLM), HKEY_USERS(或 HKU), HKEY_CURRENT_USER(或 HKCU), HKEY_CLASSES_ROOT(或 HKCR) 或 HKEY_CURRENT_CONFIG(或 HKCC) 的其中一个.

  要访问远程注册表, 请在前面加上计算机名和冒号, 例如: \\workstation01:HKEY_LOCAL_MACHINE

Key

  键名(例如 Software\SomeApplication). 如果为空或省略, 将获取 根键 的内容.

IncludeSubkeys?

  如果为空或省略, 则默认为 0(只获取值). 否则, 指定下列数字之一:

  - 0 = 不获取 Key 中包含的子键(仅获取值).
  - 1 = 获取所有的值和子键.
  - 2 = 仅获取子键(不获取值).
Recurse?(递归?)

- 0 = 不对子键进行递归.
- 1 = 对子键进行递归, 以便获取包含在其中的所有值和子键.

## 备注

当您想对注册表值或子键集合中的项逐个进行操作时, 注册表循环很有用. 值和子键以逆序获取(自下而上), 这样在循环中使用 RegDelete 不会扰乱循环自身.

下列变量存在于任何注册表循环中. 如果一个内层注册表循环包含在一个外层注册表循环中, 那么最内层循环的注册表项将具有优先权:

变量 | 描述
--- | ---
A_LoopRegName | 当前获取项的名称, 可以是值名或子键名. 在 Windows 注册表编辑器中, 值名为 "(默认)" 的项如果分配了值, 那么也会获取它的值, 不过此时相应的 A_LoopRegName 将是空的.
A_LoopRegType | 当前获取项的类型, 可以是下列单词的其中一个: KEY(即当前获取项为子键而不是值), REG_SZ, REG_EXPAND_SZ, REG_MULTI_SZ, REG_DWORD, REG_QWORD, REG_BINARY, REG_LINK, REG_RESOURCE_LIST, REG_FULL_RESOURCE_DESCRIPTOR, REG_RESOURCE_REQUIREMENTS_LIST, REG_DWORD_BIG_ENDIAN(在大多数 Windows 硬件上相当罕见). 如果当前获取项为未知类型, 那么此变量将为空.
A_LoopRegKey | 正在访问的根键名(HKEY_LOCAL_MACHINE, HKEY_USERS, HKEY_CURRENT_USER, HKEY_CLASSES_ROOT 或 HKEY_CURRENT_CONFIG). 访问远程注册表时, 此变量的值将不包含计算机名.
A_LoopRegSubKey | 当前子键名. 如果没有使用 Recurse 参数以递归查询其他子键时, 此变量的值与 Key 参数相同. 在递归查询时, 此变量的值将为当前获取项的完整路径, 其中不包含根键. 例如: Software\SomeApplication\My SubKey
A_LoopRegTimeModified | 当前子键或其中任何一个值的上次修改时间. 格式为 YYYYMMDDHH24MISS. 当前获取项不是子键(即 A_LoopRegType 不是单词 KEY) 时, 此变量将为空.

在注册表循环中使用下列命令时, 可以以一种简化的方式来操作当前获取项:

语法 | 描述
--- | ---
`RegRead, OutputVar` | 读取当前项. 如果当前项为键, ErrorLevel 将被置为 1 且 OutputVar 将被置空.
`RegWrite, Value` `RegWrite` | 写入到当前项. 如果省略 Value, 根据不同的类型当前项可能被置为 0 或空. 如果当前项为键, ErrorLevel 将被置为 1 且没有其他效果.
`RegDelete` | 删除当前项. 如果当前项为键, 它以及它所包含的所有子键和值都将被删除.

访问远程注册表时(通过上面描述的 RootKey 或 KeyName 参数), 需要注意以下事项:

- 目标机器上必须正在运行远程注册表服务.
- 如果您和目标计算机不在相同的域或者本地或远程用户名缺乏足够的权限(然而, 请参阅下文了解可能的解决方法) 时, 访问远程注册表可能失败.
- 在尝试访问远程注册表之前, 根据您的用户名所在的域, 工作组和/或权限, 您可能必须连接到共享设备, 例如通过映射驱动器. 建立这样的连接 -- 使用拥有访问或编辑注册表权限的远程用户名和密码 -- 也许可以顺带启用远程注册表访问.
- 如果您已经作为另一个用户连接到目标计算机(例如, 通过 Guest 用户映射驱动器), 您可能必须终止这个连接, 以允许远程注册表功能使用您当前登录的用户名重新连接和认证.
- 对于 Windows Server 2003 和 Windows XP 专业版, MSDN 中声明: "如果 [注册表服务器] 所在的计算机加入了工作组且启用了 强制以本地账户的来宾身份进行网络登录验证 策略, 此功能无效. 请注意如果计算机加入了工作组, 那么这项策略默认是启用的."
- 对于 Windows XP 家庭版, MSDN 中声明 "此功能总是无效". 家庭版没有注册表服务器和客户端, 尽管客户端可以从操作系统的某个 cab 压缩包提取.

请参阅 Loop 了解关于区块, Break, Continue 和 A_Index 变量(其存在于各种类型的循环中) 的相关信息.

## 相关

Loop, Break, Continue, 区块, RegRead, RegWrite, RegDelete, SetRegView

## 示例

删除用户输入的 Internet Explorer 的 URL 历史.

    Loop, HKEY_CURRENT_USER, Software\Microsoft\Internet Explorer\TypedURLs
        RegDelete

有效的测试脚本.

    Loop, Reg, HKEY_CURRENT_USER\Software\Microsoft\Windows, KVR
    {
        if (A_LoopRegType = "key")
            value := ""
        else
        {
            RegRead, value
            if ErrorLevel
                value := "*error*"
        }
        MsgBox, 4, , %A_LoopRegName% = %value% (%A_LoopRegType%)`n`nContinue?
        IfMsgBox, NO, break
    }

在整个注册表中递归搜索特殊值.

    SetBatchLines -1  ; 让搜索以最快速度进行.
    RegSearchTarget := "Notepad"  ; 告知子程序搜索的目标.
    Gosub, RegSearch
    return

    RegSearch:
    ContinueRegSearch := true
    Loop, Reg, HKEY_LOCAL_MACHINE, KVR
    {
        Gosub, CheckThisRegItem
        if not ContinueRegSearch ; 这里告知我们要停止搜索.
            return
    }
    Loop, Reg, HKEY_USERS, KVR
    {
        Gosub, CheckThisRegItem
        if not ContinueRegSearch ; 这里告知我们要停止搜索.
            return
    }
    Loop, Reg, HKEY_CURRENT_CONFIG, KVR
    {
        Gosub, CheckThisRegItem
        if not ContinueRegSearch ; 这里告知我们要停止搜索.
            return
    }
    ; 请注意: 我认为如果已经搜索了 HKEY_USERS, 那么可以不必搜索
    ; HKEY_CURRENT_USER.  同样地, 如果搜索了 HKEY_LOCAL_MACHINE,
    ; 那么可以不必搜索 HKEY_CLASSES_ROOT.
    return

    CheckThisRegItem:
    if (A_LoopRegType = "KEY")  ; 如果您也想检查键名, 那么移除这两行.
        return
    RegRead, RegValue
    if ErrorLevel
        return
    if InStr(RegValue, RegSearchTarget)
    {
        MsgBox, 4, , The following match was found:`n%A_LoopRegKey%\%A_LoopRegSubKey%\%A_LoopRegName%`nValue = %RegValue%`n`nContinue?
        IfMsgBox, No
            ContinueRegSearch := false  ; 告知我们的调用者停止搜索.
    }
    return

dftg