Vbscript 如果找到匹配项,则在注册表中搜索值删除父项

Vbscript 如果找到匹配项,则在注册表中搜索值删除父项,vbscript,Vbscript,我需要一个脚本的帮助,该脚本将遍历注册表中的特定值,并在找到匹配项后删除父项。我找到了一个代码,但它不起作用。我怀疑这是因为没有遍历注册表项进行匹配 Option Explicit Const HKEY_LOCAL_MACHINE = &H80000002 Const cRegKeyStartingPath = "SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall" Const cRegValueToF

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

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
选项显式
Const HKEY_本地_机器=&H8000002
Const cRegKeyStartingPath=“软件\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall”
Const cRegValueToFind=“Ossec HIDS”
Const cRegDataToMatch=“DisplayName”
Dim oReg、子键、ARR子键、sCurrentKey、sCurrentValuePath、iDeletedCount
iDeletedCount=0
设置oReg=GetObject(“winmgmts:{impersonationLevel=impersonate}!\\。\root\default:StdRegProv”)
oReg.EnumKey HKEY_LOCAL_机器、CREGKEY启动路径、ARRSUBKEY
出错时继续下一步
对于ARR子键中的每个子键
如果Err.Number=0,则在集合为空的情况下为'
sCurrentKey=“HKLM\”和cRegKeyStartingPath&subkey
sCurrentValuePath=sCurrentKey&“\”&cRegValueToFind
如果CustomRegrad(sCurrentValuePath)=cRegDataToMatch,则
Echo“将要删除”&sCurrentKey
DeleteRegKey sCurrentKey&“\”
iDeletedCount=iDeletedCount+1
如果结束
其他的
iDeletedCount=-1
如果结束
下一个
选择Case iDeletedCount
案例0
Echo“未找到匹配的键”
案例1
Echo“在HKLM\下找不到子键”&cRegKeyStartingPath
其他情况
Echo“Deleted”和iDeletedCount以及“keys”
结束选择
函数CustomRegrad(sRegValue)
迪姆奥谢尔酒店
暗转
设置oShell=CreateObject(“WScript.Shell”)
出错时继续下一步
呃,明白了
sRegReturn=oShell.重新研磨(sRegValue)
如果错误号为0,则
CustomRegrad=“读取值失败”
其他的
customRegRead=sRegReturn
如果结束
端函数
子删除注册表项(sKey)
迪姆奥谢尔酒店
设置oShell=CreateObject(“Wscript.Shell”)
oShell.regskey
端接头

如果有更干净/更好的方法,请提供建议。

我建议删除出现错误时出现的所有
,然后继续使用WMI方法。另外,您当前的代码不使用递归,因此您只能在
cRegKeyStartingPath
的立即子键中找到值。遍历任意深度的树需要递归

用于枚举给定键的值:

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
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
通过枚举给定项的子项并递归到这些子项中,可以遍历注册表:

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
要删除密钥,请使用该方法。必须删除哪个键的信息是您已有的:当
found
为true时,它是值枚举例程中变量
key
的值。但是,不能删除具有子键的键,因此必须先删除这些子键。可以从上面重复使用遍历例程的内容:

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
把所有东西放在一起,你会得到这样的结果:

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

您确认
cRegKeyStartingPath
指向注册表中的有效位置了吗?在我的机器(Windows 7)上,我有
Windows NT
,而不是
Windows
。此外-在调试时,通常最好关闭
On Error
语句-如果出现意外错误,这会有所帮助。CRegKeystartingpath是有效的。我不编码,但我怀疑这并不是通过子项进行的。如果您没有编写代码的经验,我会郑重建议您不要尝试使用您不理解的代码访问/修改注册表…我是在测试环境中进行此操作的。:)哇,谢谢你的剧本、分类和解释。但是,我无法让脚本运行并删除注册表项。我在做什么吗wrong@user347258没有任何信息很难说。我首先检查方法的返回代码,特别是
DeleteKey
rc=reg.DeleteKey root,key:WScript.Echo key&“:”&rc
。出于简单的原因,我从示例代码中省略了这些检查。验证所比较的字符串是否拼写正确。我的示例代码中的检查区分大小写。还要检查或删除前导/尾随空格(
Trim()
)。下面是注册表导出的修剪版本。[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{2BBD373C-E9E2-4A64-A17C-FC3F5BE25B7E}]“DisplayName”=“Ossec HIDS”“Language”=dword:00000409“版本”=dword:0207000“Windows安装程序”=dword:00000001“显示版本”=“2.7.0”“注释”=“Ossec HIDS(2.7.0)我已经复制并粘贴了这些值。我是一个新手程序员。我正在尽力理解代码。我仍然无法让它工作。@user347258您切换了值和数据。请改用这些值:
Const SearchValue=“DisplayName”:Const MatchData=“Ossec HIDS”
已经尝试过了。仍然不行。仅供参考