Как удалить значение реестра REG_DWORD, где значение реестра, например '* String *', с помощью PowerShell? - PullRequest
1 голос
/ 22 апреля 2019

PowerShell представляет значения реестра (и их данные реестра) в виде массива в $\_.Property в родительском разделе реестра.Как выбрать и удалить только те значения реестра, для которых значение равно \*String\*?

Я пытался выполнить поиск по максимуму и минимуму в StackOverflow и в Google, пробуя множество комбинаций, включающих Get-Item, Get-ItemProperty,Get-ChildItem, Select-Object (включая параметр -ExpandProperty) и Where-Object, чтобы выбрать нужные значения реестра (до перехода к включению удаления).Сейчас я нахожусь в такой ситуации, когда совершенно не понимаю и не могу понять, как просто найти значения реестра, например \*Text\*, существующие в определенном разделе реестра, и удалить их.Что-то такое простое кажется таким сложным!Я не знаю, как работать с данными в массивах!

Get-Item -Path HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\SharedDLLs

Каждое значение реестра указывается как часть массива в $\_.Property для ключа реестра HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\SharedDLLs.Я ожидал результатов, в которых я мог бы сделать что-то вроде $\_.RegistryValue -Like '\*Text\*' | Remove-Item, чтобы удалить значения реестра, соответствующие \*Text\*.

Для пояснения, чтобы обеспечить правильное техническое использование определенного словаря, «ключ реестра» отображается в виде папкив regedit.exe.

«Значение реестра» - это запись любого типа, например REG\_SZ, REG\_DWORD, REG\_MZ и т. д.Значение реестра содержит «данные реестра», и в зависимости от типа реестра это может быть строка, 32-разрядное значение (иногда выражается как 1, 0 или 0x000000, 0x000001).

Мы частоссылаются на «значения реестра» как «ключи реестра» (что является неправильным техническим использованием) и «данные реестра» как «значения реестра» (также неправильное техническое использование), а «ключи реестра» - как папки / расположение / «это место вреестр ".

Ответы [ 2 ]

0 голосов
/ 23 апреля 2019

Поставщик реестра ужасен. Я просто хотел бы, чтобы get-itemproperty работал так:

# get-itemproperty2.ps1

# get-childitem skips top level key, use get-item
# can't remove default name
param([parameter(ValueFromPipeline)]$key)

process { 
  $valuenames = $key.getvaluenames() 

  if ($valuenames) { 
    $valuenames | foreach {
      $value = $_
      [pscustomobject] @{
        Path = $key -replace 'HKEY_CURRENT_USER',
          'HKCU:' -replace 'HKEY_LOCAL_MACHINE','HKLM:'
        Name = $Value
        Value = $Key.GetValue($Value)
        Type = $Key.GetValueKind($Value)
      }
    }
  } else {
    [pscustomobject] @{
      Path = $key -replace 'HKEY_CURRENT_USER',
        'HKCU:' -replace 'HKEY_LOCAL_MACHINE','HKLM:'
        Name = ''
        Value = ''
        Type = ''
    }
  }
}

Тогда вы можете просто сделать что-то вроде:

PS C:\users\me> get-item hkcu:\key1 | get-itemproperty2

Path       Name  Value    Type
----       ----  -----    ----
HKCU:\key1 name1 value1 String
HKCU:\key1 name2 value2 String


PS C:\users\me> get-item hkcu:\key1 | get-itemproperty2 | where name -eq name1

Path       Name  Value    Type
----       ----  -----    ----
HKCU:\key1 name1 value1 String


PS C:\users\me> get-item hkcu:\key1 | get-itemproperty2 | where name -eq name1 | Remove-ItemProperty -whatif
What if: Performing the operation "Remove Property" on target "Item: HKEY_CURRENT_USER\key1 Property: name1".


PS C:\users\me> get-childitem -recurse hkcu:\key1 | get-itemproperty2

Path                      Name  Value     Type
----                      ----  -----     ----
HKCU:\key1\key2           name2 value2  String
HKCU:\key1\key2                 default String
HKCU:\key1\key2\key3      name3 value3  String
HKCU:\key1\key2\key3\key4
0 голосов
/ 22 апреля 2019

Удаление значений реестра только фильтром имени значения:

Обновление на основе вашего собственного упрощения:

# The target registry key's full path.
$keyPath = 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\SharedDLLs'

# Pass the value name pattern to Remove-ItemProperty's -Name parameter.
# Remove `-WhatIf` if the preview suggests that the operation works as intended.
Remove-ItemProperty -Path $keyPath -Name *Text* -WhatIf

Подводный камень : Есливы хотите использовать выражение подстановки , например *Text* с -Name, вы должны объединить его с -Path вместо -LiteralPath, даже если путь к ключу сам по себе не является подстановочным знаком;с
-LiteralPath, -Name также принимается буквально (дословно).

Если вам нужно использовать -LiteralPath (например, если буквальный путь содержит символ *, например,как в HKEY_CLASSES_ROOT\*):

# The target registry key's full path.
$keyPath = 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\SharedDLLs'

# Get an array of all value names that match the name wildcard pattern.
$valueNames = (Get-Item -LiteralPath $keyPath).Property -like '*Text*'

# Pass the array of value names to Remove-ItemProperty's -Name parameter.
# Remove `-WhatIf` if the preview suggests that the operation works as intended.
if ($valueNames) {
  Remove-ItemProperty -LiteralPath $keyPath -Name $valueNames -WhatIf
}

Обратите внимание на использование Get-Item вместо Get-ItemProperty. [1]

Get-Item возвращает объектпредставляет весь ключ типа [Microsoft.Win32.RegistryKey], который PowerShell украшает свойством примечания .Property, которое содержит массив всех имен значений ключа.

Важно : в массиве .Property PowerShell преобразует имя значения по умолчанию , которое представляет собой пустую строку ('')на уровне API, в имя '(default)'.

Применение оператора -like к массиву LHS заставляет его действовать как фильтр , который возвращает только подчиненныймассив соответствующих элементов.

Remove-ItemProperty -Name параметр напрямую принимает массив имен свойств (значений реестра) для удаления из целевого ключа.


Удаление значений по имени значения и / или фильтру данных:

Примечание. Из-за использования общего параметра -PipelineVariable для этого решения требуется PSv4 +.

# The target registry key's full path.
$keyPath = 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\SharedDLLs'

$pattern = '*Text*'

# Look for $pattern in both the name and the data.
# Remove `-WhatIf` if the preview suggests that the operation works as intended.
Get-Item -LiteralPath $keyPath -PipelineVariable key |
  ForEach-Object Property | 
    Where-Object { 
      $valueName = ($_, '')[$_ -eq '(default)'] # translate '(default)' to '' for API
      $valueName -like $pattern -or $key.GetValue($valueName) -like $pattern 
    } |
      Remove-ItemProperty -LiteralPath $keyPath -WhatIf
  • -PipelineVariable key сохраняет экземпляр [Microsoft.Win32.RegistryKey], возвращаемый Get-Item в переменной $key для последующего использования в конвейере.

  • ForEach-Object Property перечисляет имена значений целевого ключа(с помощью свойства примечания .Property PowerShell добавляет к выходному экземпляру [Microsoft.Win32.RegistryKey], как обсуждалось).

  • Внутри сценария Where-Object block, $_ затем ссылается на имеющееся имя значения, а $key.GetValue(<valueName>) используется для извлечения связанных данных.

    • Важно : В массиве .PropertyPowerShell переводит имя значения по умолчанию , которое представляет собой пустую строку ('') на уровне API, в имя '(default)';таким образом, если $_ равно '(default)', вы должны перевести его на '' перед вызовом $_.GetValue(<valueName>), что и делает
      ($_, '')[$_ -eq '(default)'].
  • Независимо от того, какие имена значений соответствуют критериям, они затем передаются в Remove-ItemProperty, что неявно связывает эти имена с его параметром -Name.

Если вы просто хотите - список соответствующих значений и их данных , см. этот ответ .


[1] Get-ItemProperty -Path $keyPath -Name *Text* технически тоже работает, но вывод один объект типа [pscustomobject], чьи свойства необходимо перечислить с помощью отражения , поскольку имена свойств отражают совпадающие имена значений;делая это с помощью .psobject.properties, как показано в , этот ответ работает и позволяет фильтровать также по данным , ловушка заключается в том, что поставщик реестра PowerShell автоматически добавляет свои собственные свойства в коллекциюсвойства, а именно PSPath, PsParentPath, PSChildName, PSDrive, PSProvider, что означает, что подстановочное выражение, которое фильтрует по имени, может случайно включить их или, что еще хуже, если существуют значения с тем же именемна ключе (хотя маловероятно), свойства провайдера переопределяют их.

...