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 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メソッドを使用します。どのキーを削除しなければならないかという情報は、あなたがすでに持っているものです:が true の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

戻りコード 6 (ハンドルが無効) を無効なhDefKey&h8000002(7 桁のみ) またはh80000002(アンパサンドがない) で再現できました。

于 2013-03-11T20:23:15.787 に答える