0

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

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

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

4

1 回答 1

2

我建议删除所有出现的On Error Resume NextWMI 方法并坚持使用。此外,您当前的代码不使用递归,因此您只能在cRegKeyStartingPath. 您需要递归来遍历任意深度的树。

用于EnumValues枚举给定键的值:

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

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

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(缺少 & 号)。

于 2013-03-11T20:23:15.787 回答