如果匹配找到删除父密钥,则搜索注册表的值

时间:2013-03-11 17:11:58

标签: vbscript

我需要一个脚本的帮助,该脚本将遍历注册表中的特定值,一旦找到匹配项,就删除父键。我找到了一个代码,但它不起作用。我怀疑这不是遍历注册表项以进行匹配。

Option Explicit

Const HKEY_LOCAL_MACHINE   = &H80000002 
Const cRegKeyStartingPath  = "SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
Const cRegValueToFind      = "Ossec HIDS"
Const cRegDataToMatch      = "DisplayName" 

Dim oReg, subkey, arrSubKeys, sCurrentKey, sCurrentValuePath, iDeletedCount
iDeletedCount = 0

Set oReg=GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\default:StdRegProv")
oReg.EnumKey HKEY_LOCAL_MACHINE, cRegKeyStartingPath, arrSubKeys

On Error Resume Next
For Each subkey In arrSubKeys
    If Err.Number = 0 Then 'in case the collection is empty
        sCurrentKey = "HKLM\" & cRegKeyStartingPath & subkey
        sCurrentValuePath = sCurrentKey & "\" & cRegValueToFind
        If customRegRead(sCurrentValuePath) = cRegDataToMatch Then
            WScript.Echo "Going to delete "&sCurrentKey
            DeleteRegKey sCurrentKey&"\"
            iDeletedCount = iDeletedCount + 1
        End If
    Else
        iDeletedCount = -1
    End If
Next

Select Case iDeletedCount
    Case 0
        WScript.Echo "No matching keys found"
    Case -1
        WScript.Echo "No subkeys found below HKLM\"&cRegKeyStartingPath
    Case Else
        WScript.Echo "Deleted " & iDeletedCount & " keys"
End Select

Function customRegRead(sRegValue)

    Dim oShell
    Dim sRegReturn

    Set oShell = CreateObject("WScript.Shell")

    On Error Resume Next
    Err.Clear
    sRegReturn = oShell.RegRead(sRegValue)
    If Err.Number<>0 Then
        customRegRead = "Failed To Read Value"
    Else
        customRegRead = sRegReturn
    End If  

End Function

Sub DeleteRegKey(sKey)

    Dim oShell
    Set oShell = CreateObject("Wscript.Shell")
    oShell.RegDelete sKey

End Sub

如果有更清洁/更好的东西请告知。

1 个答案:

答案 0 :(得分:2)

我建议删除所有出现的On Error Resume Next并坚持使用WMI方法。此外,您当前的代码不使用递归,因此您只能在cRegKeyStartingPath的直接子键中查找值。遍历任意深度的树都需要递归。

使用EnumValues枚举给定键的值:

rc = reg.EnumValues(HKLM, key, names, types)

该方法成功返回0,因此您可以通过评估返回代码来检查错误。调用完成后,变量names包含一个数组名称为keyNull的数组,如果该键不包含任何值(缺少默认值,即)。因此,检查给定键中是否存在特定值的代码可能如下所示:

reg.EnumValues HKLM, key, names, types
If Not IsNull(names) Then
  For Each name In names
    If name = "foo" Then
      reg.GetStringValue HKLM, key, name, data
      If data = "bar" Then
        'delete key here
        Exit For
      End If
    End If
  Next
End If

您可以通过EnumKey枚举给定键的子键并递归到这些子键来遍历注册表:

Sub TraverseRegistry(root, key)
  reg.EnumKey root, key, subkeys
  If Not IsNull(subkeys) Then
    For Each sk In subkeys
      TraverseRegistry root, key & "\" & sk
    Next
  End If
End Sub

要删除密钥,请使用DeleteKey方法。必须删除的键必须删除的信息:当key为真时,它是值枚举例程中变量found的值。但是,您无法删除具有子项的键,因此您必须先删除那些。您可以从上面重新使用遍历例程的东西:

Sub DelKey(root, key)
  reg.EnumKey root, key, subkeys
  If Not IsNull(subkeys) Then
    For Each sk In subkeys
      DelKey root, key & "\" & sk  'delete subkeys first
    Next
  End If
  'at this point all subkeys have already been deleted, so we can
  'now delete the parent key
  reg.DeleteKey root, key
End Sub

把所有东西放在一起,你得到这样的东西:

Const HKLM = &h80000002

Const StartKey    = "SOFTWARE\Wow...ion\Uninstall"
Const SearchValue = "DisplayName"
Const MatchData   = "Ossec HIDS"

Set reg = GetObject("winmgmts://./root/default:StdRegProv")

FindAndDeleteKey HKLM, StartKey, SearchValue, MatchData

Sub FindAndDeleteKey(root, key, value, data)
  reg.EnumValues HKLM, key, names, types
  If Not IsNull(names) Then
    For Each name In names
      If name = value Then
        reg.GetStringValue HKLM, key, name, regdata
        If regdata = data Then
          DelKey root, key
          Exit Sub
        End If
      End If
    Next
  End If

  'value not found in current key => continue search in subkeys
  reg.EnumKey root, key, subkeys
  If Not IsNull(subkeys) Then
    For Each sk In subkeys
      FindAndDeleteKey root, key & "\" & sk, value, data
    Next
  End If
End Sub

Sub DelKey(root, key)
  reg.EnumKey root, key, subkeys
  If Not IsNull(subkeys) Then
    For Each sk In subkeys
      DelKey root, key & "\" & sk  'delete subkeys first
    Next
  End If
  'at this point all subkeys have already been deleted, so we can
  'now delete the parent key
  reg.DeleteKey root, key
End Sub

由于您正在寻找具有特定数据的特定值,因此您甚至可以简化FindAndDeleteKey()

Sub FindAndDeleteKey(key)
  'Try to read the value directly. If the value doesn't exist this will
  'simply return a non-zero return code and set data to Null.
  reg.GetStringValue HKLM, key, SearchValue, data
  If Not IsNull(data) Then
    'value does exist
    If data = MatchData Then
      DelKey HKLM, key
      Exit Sub
    End If
  End If

  'value not found in current key => continue search in subkeys
  reg.EnumKey HKLM, key, subkeys
  If Not IsNull(subkeys) Then
    For Each sk In subkeys
      FindAndDeleteKey key & "\" & sk
    Next
  End If
End Sub

编辑:以下是生成一些调试输出的版本。通过cscript debug_sample.vbs在命令提示符下运行它。请注意,由于您要删除HKLM中的内容,因此必须在启用UAC时以“管理员”身份运行脚本。

Const HKLM = &h80000002

Const StartKey    = "SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
Const SearchValue = "DisplayName"
Const MatchData   = "Ossec HIDS"

Set reg = GetObject("winmgmts://./root/default:StdRegProv")

FindAndDeleteKey StartKey

Sub FindAndDeleteKey(key)
  WScript.Echo "[HKLM\" & key & "]"
  rc = reg.GetStringValue(HKLM, key, SearchValue, data)
  If Not IsNull(data) Then
    WScript.Echo """" & SearchValue & """=""" & data & """"
    If data = MatchData Then
      DelKey HKLM, key
      Exit Sub
    End If
  Else
    WScript.Echo "'" & SearchValue & "' not found in [HKLM\" & key & "], rc=" & rc
  End If

  reg.EnumKey HKLM, key, subkeys
  If Not IsNull(subkeys) Then
    For Each sk In subkeys
      FindAndDeleteKey key & "\" & sk
    Next
  End If
End Sub

Sub DelKey(root, key)
  reg.EnumKey root, key, subkeys
  If Not IsNull(subkeys) Then
    For Each sk In subkeys
      DelKey root, key & "\" & sk
    Next
  End If
  rc = reg.DeleteKey(root, key)
  WScript.Echo "Deleting [HKLM\" & key & "], rc=" & rc
End Sub

我能够使用无效的hDefKey值重现返回代码6(句柄无效),例如&h8000002(仅限7位)或h80000002(缺少&符号)。