如何获取注册表项的值,并且仅使用 powershell 获取值

Posted

技术标签:

【中文标题】如何获取注册表项的值,并且仅使用 powershell 获取值【英文标题】:How do I get the value of a registry key and ONLY the value using powershell 【发布时间】:2013-03-19 22:33:36 【问题描述】:

谁能帮我提取注册表项的值并将其放入 PowerShell 中的变量中?到目前为止,我已经使用了Get-ItemPropertyreg query,虽然两者都会拉取值,但两者都会添加额外的文本。我只需要注册表项中的字符串文本和键中的字符串文本。我确信我可以创建一个函数来去除多余的文本,但如果有什么变化(即 reg 键名),它可能会影响这一点。

【问题讨论】:

这是个好问题,但请注意Get-ItemProperty 不会添加额外的文本;相反,它返回一个 object,其中一个 properties 包含所需的数据。额外的文本来自返回对象的默认输出格式(对象结构的表示).. 【参考方案1】:
$key = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion'
(Get-ItemProperty -Path $key -Name ProgramFilesDir).ProgramFilesDir

我从不喜欢提供程序是如何实现的:/

基本上,它使每个注册表值成为具有PsPathPsParentPathPsChildnamePSDrivePSProvider 属性的PSCustomObject 对象,然后是其实际值的属性。因此,即使您按名称要求项目,要获得其值,您也必须再次使用该名称。

【讨论】:

嗨@Andy:为什么不直接(Get-ItemProperty -Path $key).ProgramFilesDir 来避免冗余?这对我行得通;但在某些情况下,它不会...? @msorens 查看 charleswj81 对 M Jeremy Carter 的回复。 来自 C#,C++ powershell 非常不直观。但是一旦你弄清楚它的怪癖,你就会明白 shell 的强大部分。【参考方案2】:

这些答案中没有一个适用于值名称包含空格、点或其他在 PowerShell 中保留的字符的情况。在这种情况下,您必须按照 http://blog.danskingdom.com/accessing-powershell-variables-with-periods-in-their-name/ 将名称用双引号括起来 - 例如:

PS> Get-ItemProperty Registry::HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\VisualStudio\SxS\VS7

14.0         : C:\Program Files (x86)\Microsoft Visual Studio 14.0\
12.0         : C:\Program Files (x86)\Microsoft Visual Studio 12.0\
11.0         : C:\Program Files (x86)\Microsoft Visual Studio 11.0\
15.0         : C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\
PSPath       : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\VisualStudio\SxS\V
               S7
PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\VisualStudio\SxS
PSChildName  : VS7
PSProvider   : Microsoft.PowerShell.Core\Registry

如果您想访问 14.0、12.0、11.0、15.0 中的任何一个值,接受答案的解决方案将不起作用 - 您将不会得到任何输出:

PS> (Get-ItemProperty Registry::HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\VisualStudio\SxS\VS7 -Name 15.0).15.0
PS>

有效的是引用值名称,为了安全起见,无论如何您都应该这样做:

PS> (Get-ItemProperty "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\VisualStudio\SxS\VS7" -Name "15.0")."15.0"
C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\
PS> 

因此,接受的答案应该这样修改:

PS> $key = "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\VisualStudio\SxS\VS7"
PS> $value = "15.0"
PS> (Get-ItemProperty -Path $key -Name $value).$value
C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\
PS> 

这适用于 PowerShell 2.0 到 5.0(尽管您可能应该在 v5 中使用 Get-ItemPropertyValue)。

【讨论】:

【参考方案3】:

Harry Martyrossian 在his own answer 的评论中提到Get-ItemPropertyValue cmdlet 是在 Powershell v5 中引入的,它解决了问题:

PS> Get-ItemPropertyValue 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion' 'ProgramFilesDir'
C:\Program Files

PowerShell v4- 的替代方案:

这里尝试保留效率,同时消除重复值名称的需要,但是,这仍然有点麻烦:

&  
  (Get-ItemProperty `
      -LiteralPath HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion `
      -Name $args 
  ).$args 
 ProgramFilesDir

通过使用脚本块,值名称可以作为参数传入一次,然后参数变量($args)可以在块内简单地使用两次。

或者,一个简单的辅助函数可以减轻痛苦:

function Get-RegValue([String] $KeyPath, [String] $ValueName) 
  (Get-ItemProperty -LiteralPath $KeyPath -Name $ValueName).$ValueName


注意:以上所有解决方案绕过Ian Kemp's 的回答中描述的问题 - 用作属性时需要对某些值名称使用显式引用 姓名;例如,.'15.0' - 因为值名称是作为 parameters 传递的,并且属性访问是通过 variable 进行的;例如,.$ValueName


至于其他答案:

Andy Arismendi's helpful answer 解释了必须重复值名称以便有效获取值数据的烦恼。 M Jeremy Carter's helpful answer 更方便,但对于具有大量值的键可能是性能缺陷,因为必须构造具有大量属性的对象。

【讨论】:

【参考方案4】:

我不确定这是否已更改,或者是否与您使用的 PS 版本有关,但使用 Andy 的示例,我可以删除 -Name 参数,我仍然可以得到值注册项目:

PS C:\> $key = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion'
PS C:\> (Get-ItemProperty -Path $key).ProgramFilesDir
C:\Program Files


PS C:\> $psversiontable.psversion

Major  Minor  Build  Revision
-----  -----  -----  --------
2      0      -1     -1

【讨论】:

现在和一直都是这样。您的方法在技术上没有任何问题,但是它比指定要返回的特定属性效率低。您的方法将查询所有属性,然后在返回之前将它们过滤掉。 为了说明问题,看看下面两个 PowerShell 单行代码运行时间的不同:measure-command1..10|%[void]( Get-ItemProperty HKLM:\software\microsoft\windows\currentversion\installer\Folders -Name 'C:\Windows\PCHEALTH\' )measure-command1..10|%[void]( Get-ItemProperty HKLM:\software\microsoft\windows\currentversion\installer\Folders )【参考方案5】:

给定一个具有两个属性的键 \SQL

我会在以下情况下使用“MSSQLSERVER”,其中我不确定使用点符号的属性名称是什么:

$regkey_property_name = 'MSSQLSERVER'
$regkey = get-item -Path 'HKLM:\Software\Microsoft\Microsoft SQL Server\Instance Names\SQL'
$regkey.GetValue($regkey_property_name)

【讨论】:

【参考方案6】:

嗯,你需要在这里具体。据我所知,注册表中的键是属性的“文件夹”。那么你的意思是获取财产的价值吗?如果是这样,请尝试以下操作:

(Get-ItemProperty HKLM:\Software\Microsoft\PowerShell\1\PowerShellEngine -Name PowerShellVersion).PowerShellVersion

首先我们使用Get-ItemProperty 获得一个包含我们需要的属性的对象,然后我们从该对象中获得我们需要的属性的值。这会将属性的值作为字符串返回。上面的示例为您提供了“legacy”/compatibility-mdoe powershell(1.0 或 2.0)的 PS 版本。

【讨论】:

【参考方案7】:

不确定此功能是在哪个版本出现的,但您可以使用类似的方法返回数组中多个子注册表项的所有属性:

$InstalledSoftware = Get-ChildItem "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" | ForEach-Object Get-ItemProperty "Registry::$_"

仅添加此内容是因为 Google 出于相关原因将我带到这里,我最终想出了上述用于疏通注册表的单行代码。

【讨论】:

【参考方案8】:

以下代码将枚举某个注册表项的所有值,对它们进行排序并返回值名称:由冒号 (:) 分隔的值对:

$path = 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\.NETFramework';

Get-Item -Path $path | Select-Object -ExpandProperty Property | Sort | % 
    $command = [String]::Format('(Get-ItemProperty -Path "0" -Name "1")."1"', $path, $_);
    $value = Invoke-Expression -Command $command;
    $_ + ' : ' + $value; ;

像这样:

DbgJITDebugLaunchSetting : 16
DbgManagedDebugger : "C:\Windows\system32\vsjitdebugger.exe" PID %d APPDOM %d EXTEXT "%s" EVTHDL %d
InstallRoot : C:\Windows\Microsoft.NET\Framework\

【讨论】:

问题是关于获取特定值的数据,没有额外信息。除此之外,您的代码依赖于 .NET 方法调用,可以更轻松地在 PowerShell 中以本机方式完成。 对于 PowerShell v. 5.0 及更高版本,请使用新的 cmdlet - Get-ItemPropertyValue: $value = Get-ItemPropertyValue -Path $regKeyPath -Name $valueName; 使用 v5+ Get-ItemPropertyValue 是一个很好的提示,谢谢。虽然您已经使您的答案稍微更像 PowerShell,但它仍然回答了一个没有被问到的问题,并且您给出的答案仍然远非 PowerShell 惯用的。更惯用的版本是:(Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\.NETFramework').psobject.properties | ? Name -notlike 'PS*' | Sort-Object Name | Select-Object Name, Value。此外,除非您想在一行中放置多个语句,否则没有理由以 ; 终止语句。【参考方案9】:

如果您创建一个对象,您将获得更易读的输出,并获得一个具有您可以访问的属性的对象:

$path = 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\.NETFramework'
$obj  = New-Object -TypeName psobject

Get-Item -Path $path | Select-Object -ExpandProperty Property | Sort | % 
$command = [String]::Format('(Get-ItemProperty -Path "0" -Name "1")."1"', $path, $_)
$value = Invoke-Expression -Command $command
$obj | Add-Member -MemberType NoteProperty -Name $_ -Value $value

Write-Output $obj | fl

示例输出: 安装根目录:C:\Windows\Microsoft.NET\Framework\

还有对象: $obj.InstallRoot = C:\Windows\Microsoft.NET\Framework\

事情的真相是,这比它需要的要复杂得多。这是一个更好的例子,也更简单:

$path = 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\.NETFramework'
$objReg = Get-ItemProperty -Path $path | Select -Property *

$objReg 现在是一个自定义对象,其中每个注册表项都是一个属性名称。您可以通过以下方式查看格式化列表:

write-output $objReg

InstallRoot        : C:\Windows\Microsoft.NET\Framework\
DbgManagedDebugger : "C:\windows\system32\vsjitdebugger.exe"

并且您可以访问对象本身:

$objReg.InstallRoot
C:\Windows\Microsoft.NET\Framework\

【讨论】:

以上是关于如何获取注册表项的值,并且仅使用 powershell 获取值的主要内容,如果未能解决你的问题,请参考以下文章

如何读取注册表项的值c#

请问如何使用批处理命令改变注册表项的权限?

批处理如何设置注册表项的权限

React Native - 如何从父级获取 FlatList 项的值

VB.NET 如何获取datagridview选中项的值

如何获取 AlertDialog 中自定义列表视图的单击项的值?