我需要一个脚本的帮助,该脚本将遍历注册表中的特定值,一旦找到匹配项,就删除父键。我找到了一个代码,但它不起作用。我怀疑这不是遍历注册表项以进行匹配。
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
如果有更清洁/更好的东西请告知。
答案 0 :(得分:2)
我建议删除所有出现的On Error Resume Next
并坚持使用WMI方法。此外,您当前的代码不使用递归,因此您只能在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
(缺少&符号)。