使用PowerShell在注册表项和值中搜索字符串
我想使用PowerShell查找特定配置单元中包含字符串使用PowerShell在注册表项和值中搜索字符串,powershell,Powershell,我想使用PowerShell查找特定配置单元中包含字符串foo,可能嵌入较长字符串中的所有注册表项和值。找到钥匙并不难: Get-ChildItem -path hkcu:\ -recurse -ErrorAction SilentlyContinue | Where-Object {$_.Name -like "*foo*"} 问题是我不知道找到值的最佳方法,因为我事先不知道属性的名称。我试过这个: Get-ChildItem -path hkcu:\ -recurse -erroracti
foo
,可能嵌入较长字符串中的所有注册表项和值。找到钥匙并不难:
Get-ChildItem -path hkcu:\ -recurse -ErrorAction SilentlyContinue | Where-Object {$_.Name -like "*foo*"}
问题是我不知道找到值的最佳方法,因为我事先不知道属性的名称。我试过这个:
Get-ChildItem -path hkcu:\ -recurse -erroraction silentlycontinue | get-itemproperty | where {$_.'(default)' -like "*foo*"}
但我有一个错误:
get-itemproperty : Specified cast is not valid.
At line:1 char:69
+ ... u:\ -recurse -erroraction silentlycontinue | get-itemproperty | where ...
+ ~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Get-ItemProperty], InvalidCastException
+ FullyQualifiedErrorId : System.InvalidCastException,Microsoft.PowerShell.Commands.GetItemPropertyCommand
即使我将
-ErrorAction SilentlyContinue
添加到获取项目属性中
此外,它只查找(默认)
键的值
另外,是否可以在一个命令中搜索所有配置单元?每个键都有一个
GetValueNames()
、GetValueKind()
和GetValue()
方法,可以让您枚举子值。您还可以使用GetSubKeyNames()
而不是依赖getchilditem-Recurse
来枚举键
要回答有关搜索多个配置单元的问题,请执行以下操作:\“Get ChildItem Registry::\”,您可以查看所有配置单元并在那里开始搜索。您可能希望坚持使用HKLM和HKCU(如果加载了其他用户配置单元,可能是HKU)
下面是我不久前在上创建的一个示例实现:
函数搜索注册表{
[CmdletBinding()]
参数(
[参数(必需,位置=0,ValueFromPipelineByPropertyName)]
[别名(“PsPath”)]
#要搜索的注册表路径
[string[]]$Path,
#指定是否也应搜索所有子键
[开关]$Recurse,
[参数(ParameterSetName=“SingleSearchString”,必填)]
#将根据键名、值名和值数据进行检查的正则表达式(取决于指定的开关)
[字符串]$SearchRegex,
[参数(ParameterSetName=“SingleSearchString”)]
#使用-SearchRegex参数时,此开关意味着将测试密钥名称(如果三个开关均未使用,则将测试密钥)
[开关]$KeyName,
[参数(ParameterSetName=“SingleSearchString”)]
#使用-SearchRegex参数时,此开关表示将测试值名称(如果三个开关均未使用,则将测试值名称)
[开关]$ValueName,
[参数(ParameterSetName=“SingleSearchString”)]
#使用-SearchRegex参数时,此开关意味着将测试值数据(如果三个开关均未使用,则将测试值数据)
[开关]$ValueData,
[参数(ParameterSetName=“MultipleSearchString”)]
#指定将仅根据键名称检查的正则表达式
[字符串]$KeyNameRegex,
[参数(ParameterSetName=“MultipleSearchString”)]
#指定仅根据值名称检查的正则表达式
[字符串]$ValueNameRegex,
[参数(ParameterSetName=“MultipleSearchString”)]
#指定仅根据值数据检查的正则表达式
[字符串]$ValueDataRegex
)
开始{
开关($PSCmdlet.ParameterSetName){
SingleSearchString{
$NoSwitchesSpecified=-非($PSBoundParameters.ContainsKey(“KeyName”)-或$PSBoundParameters.ContainsKey(“ValueName”)-或$PSBoundParameters.ContainsKey(“ValueData”))
如果($KeyName-或$NoSwitchesSpecified){$KeyNameRegex=$SearchRegex}
如果($ValueName-或$NoSwitchesSpecified){$ValueNameRegex=$SearchRegex}
如果($ValueData-或$NoSwitchesSpecified){$ValueDataRegex=$SearchRegex}
}
多重搜索字符串{
#不需要额外的工作
}
}
}
进程{
foreach($Path中的CurrentPath){
获取子项$CurrentPath-Recurse:$Recurse|
ForEach对象{
$Key=$\u
如果($KeyNameRegex){
详细写入(“{0}:检查KeyNamesRegex”-f$Key.Name)
如果($Key.PSChildName-匹配$KeyNameRegex){
写详细的“->找到匹配项!”
返回[PSCustomObject]@{
Key=$Key
Reason=“KeyName”
}
}
}
如果($ValueNameRegex){
详细写入(“{0}:检查ValueNamesRegex”-f$Key.Name)
如果($Key.GetValueNames()-匹配$ValueNameRegex){
写详细的“->找到匹配项!”
返回[PSCustomObject]@{
Key=$Key
Reason=“ValueName”
}
}
}
如果($ValueDataRegex){
详细写入(“{0}:检查ValueDataRegex”-f$Key.Name)
如果($Key.GetValueNames()|%{$Key.GetValue($|)})-match$ValueDataRegex{
写详细的“->匹配!”
返回[PSCustomObject]@{
Key=$Key
Reason=“ValueData”
}
}
}
}
}
}
}
我已经有一段时间没有看它了,我可以肯定地看到它的某些部分应该进行更改以使其更好,但它应该作为您的起点。这是对get-itemproperty的替换,它以一种简单的方式转储注册表。它很容易与where对象一起使用。您还可以通过管道将其连接到集合项
function Search-Registry {
<#
.SYNOPSIS
Searches registry key names, value names, and value data (limited).
.DESCRIPTION
This function can search registry key names, value names, and value data (in a limited fashion). It outputs custom objects that contain the key and the first match type (KeyName, ValueName, or ValueData).
.EXAMPLE
Search-Registry -Path HKLM:\SYSTEM\CurrentControlSet\Services\* -SearchRegex "svchost" -ValueData
.EXAMPLE
Search-Registry -Path HKLM:\SOFTWARE\Microsoft -Recurse -ValueNameRegex "ValueName1|ValueName2" -ValueDataRegex "ValueData" -KeyNameRegex "KeyNameToFind1|KeyNameToFind2"
#>
[CmdletBinding()]
param(
[Parameter(Mandatory, Position=0, ValueFromPipelineByPropertyName)]
[Alias("PsPath")]
# Registry path to search
[string[]] $Path,
# Specifies whether or not all subkeys should also be searched
[switch] $Recurse,
[Parameter(ParameterSetName="SingleSearchString", Mandatory)]
# A regular expression that will be checked against key names, value names, and value data (depending on the specified switches)
[string] $SearchRegex,
[Parameter(ParameterSetName="SingleSearchString")]
# When the -SearchRegex parameter is used, this switch means that key names will be tested (if none of the three switches are used, keys will be tested)
[switch] $KeyName,
[Parameter(ParameterSetName="SingleSearchString")]
# When the -SearchRegex parameter is used, this switch means that the value names will be tested (if none of the three switches are used, value names will be tested)
[switch] $ValueName,
[Parameter(ParameterSetName="SingleSearchString")]
# When the -SearchRegex parameter is used, this switch means that the value data will be tested (if none of the three switches are used, value data will be tested)
[switch] $ValueData,
[Parameter(ParameterSetName="MultipleSearchStrings")]
# Specifies a regex that will be checked against key names only
[string] $KeyNameRegex,
[Parameter(ParameterSetName="MultipleSearchStrings")]
# Specifies a regex that will be checked against value names only
[string] $ValueNameRegex,
[Parameter(ParameterSetName="MultipleSearchStrings")]
# Specifies a regex that will be checked against value data only
[string] $ValueDataRegex
)
begin {
switch ($PSCmdlet.ParameterSetName) {
SingleSearchString {
$NoSwitchesSpecified = -not ($PSBoundParameters.ContainsKey("KeyName") -or $PSBoundParameters.ContainsKey("ValueName") -or $PSBoundParameters.ContainsKey("ValueData"))
if ($KeyName -or $NoSwitchesSpecified) { $KeyNameRegex = $SearchRegex }
if ($ValueName -or $NoSwitchesSpecified) { $ValueNameRegex = $SearchRegex }
if ($ValueData -or $NoSwitchesSpecified) { $ValueDataRegex = $SearchRegex }
}
MultipleSearchStrings {
# No extra work needed
}
}
}
process {
foreach ($CurrentPath in $Path) {
Get-ChildItem $CurrentPath -Recurse:$Recurse |
ForEach-Object {
$Key = $_
if ($KeyNameRegex) {
Write-Verbose ("{0}: Checking KeyNamesRegex" -f $Key.Name)
if ($Key.PSChildName -match $KeyNameRegex) {
Write-Verbose " -> Match found!"
return [PSCustomObject] @{
Key = $Key
Reason = "KeyName"
}
}
}
if ($ValueNameRegex) {
Write-Verbose ("{0}: Checking ValueNamesRegex" -f $Key.Name)
if ($Key.GetValueNames() -match $ValueNameRegex) {
Write-Verbose " -> Match found!"
return [PSCustomObject] @{
Key = $Key
Reason = "ValueName"
}
}
}
if ($ValueDataRegex) {
Write-Verbose ("{0}: Checking ValueDataRegex" -f $Key.Name)
if (($Key.GetValueNames() | % { $Key.GetValue($_) }) -match $ValueDataRegex) {
Write-Verbose " -> Match!"
return [PSCustomObject] @{
Key = $Key
Reason = "ValueData"
}
}
}
}
}
}
}
function get-itemproperty2 {
# get-childitem skips top level key, use get-item for that
# set-alias gp2 get-itemproperty2
param([parameter(ValueFromPipeline)]$key)
process {
$key.getvaluenames() | foreach-object {
$value = $_
[pscustomobject] @{
Path = $Key -replace 'HKEY_CURRENT_USER',
'HKCU:' -replace 'HKEY_LOCAL_MACHINE','HKLM:'
Name = $Value
Value = $Key.GetValue($Value)
Type = $Key.GetValueKind($Value)
}
}
}
}
ls -r hkcu:\key1 | get-itemproperty2 | where name -eq name
Path Name Value Type
---- ---- ----- ----
HKCU:\key1\key2 name 1 DWord
ls -r hkcu:\key1 | get-itemproperty2 | where name -eq name | set-itemproperty -value 0
ls -r hkcu:\key1 | get-itemproperty2 | where name -eq name
Path Name Value Type
---- ---- ----- ----
HKCU:\key1\key2 name 0 DWord
# pipe 2 commands to one
$(get-item hkcu:\key1; ls -r hkcu:\key1 ) | get-itemproperty2
Path Name Value Type
---- ---- ----- ----
HKCU:\key1 multi {hi, there} MultiString
HKCU:\key1\key2 name 0 DWord
HKCU:\key1\key2 name2 0 String
HKCU:\key1\key2\key3 name3 {18, 52, 80} Binary
get-childitem -recurse HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall |
get-itemproperty | where { $_ -match 'Office16.PROPLUS' }