Powershell.registry搜索项目值为“”的显示名称

时间:2014-11-08 10:25:34

标签: powershell get registry key

在Powershell的帮助下,我需要找到注册表项,其中Value Displayname喜欢' Cisco ',并从值名称' Uninstallstring&#获取此关键数据39 ;. 我知道这听起来有点奇怪,但是这个应用程序在每台计算机上都有不同的卸载字符串。

所以

ForEach-Object -InputObject (Get-ChildItem 'HKLM:\software\microsoft\windows\currentversion\uninstall') {
  $single_item = $_ | Get-Item
  $single_item_properties = $single_item | Get-ItemProperty | Select-Object -Property DisplayName,UninstallString | Where-Object {($_.DisplayName -like '*Cisco*TSP*')}
  $uninstall_str = ($single_item_properties | Select UninstallString)
  $str_to_execute=$uninstall_str.UninstallString  -replace '" .*','"'
  $str_to_execute
  Start-Process -FilePath $str_to_execute -ArgumentList '-s','-f1"\\sandbox\Common.Installs\Utils\un.iss"' -Wait -PassThru
}

此脚本为我们提供了错误

  

UninstallString

     
     

" C:\ Program Files(x86)\ InstallShield安装信息{01A05F96-E34D-4308-965C-65DCA4AF114D} \ setup.exe"

     

Start-Process:由于错误导致无法执行此命令:系统找不到指定的文件。

问题是结果不是字符串类型。

我无法将其转换为字符串。

2 个答案:

答案 0 :(得分:0)

您显示的输出似乎与您提供的代码不符。当我执行你的代码时,我会根据自己的搜索获得uninstallstring。当我第一次看到输出时,我想" 哦......他忘了他正在将一个带有UninstallString属性的对象传递给Start-Process "。但是当我查看你的代码时,我可以看到你通过$uninstall_str.UninstallString来解释这个问题。所以我不确定究竟是什么错误,但是使用-ExpandProperty的{​​{1}}

Select-Object

但如果您愿意,我们可以制作一个班轮。

$uninstall_str = $single_item_properties | Select -ExpandProperty UninstallString
$str_to_execute=$uninstall_str -replace '" .*','"'

答案 1 :(得分:0)

这里有几个问题。

  1. 虽然 ForEach-Object 具有 -InputObject 参数,但它主要用于获取管道输入。正如文档所说,

      

    当您将InputObject参数与ForEach-Object一起使用时,而不是将命令结果传递给ForEach-Object,而不是将InputObject值 - 即使该值是作为命令结果的集合,例如-InputObject(Get-过程) - 被视为单个对象。由于InputObject无法从数组或对象集合返回单个属性,因此建议如果使用ForEach-Object对已定义属性中具有特定值的对象的对象集合执行操作,则应使用ForEach-Object。管道

    在您的代码中,scriptblock只执行一次, $ single_item 实际上是一个包含 Get-ChildItem 输出的数组。为了一次迭代结果一个元素,您需要将输出传递给 ForEach-Object ......

    Get-ChildItem 'HKLM:\software\microsoft\...' | ForEach-Object {
    

    ...或者更好的是,使用 foreach 控件结构,它通常运行得更快(尽管它使用更多内存):

    foreach ($single_item in (Get-ChildItem 'HKLM:\software\microsoft\...')) {
    
  2. 将每个元素管道化为 Get-Item 是多余的。您可以直接管道到 Get-ItemProperty

  3. 您不需要选择属性以使用 Where-Object 对其进行过滤。因此,使用Select-Object -Property DisplayName,UninstallString创建具有两个属性的PSCustomObject,然后在代码中稍后检索该PSCustomObject的 UninstallString 属性是多余的。只需首先使用 Where-Object 进行过滤,然后使用| Select -ExpandProperty UninstallString获取 UninstallString 的值。

    (有关使用 -ExpandPropery 开关的原因的说明,请参阅this answer。)

  4. 使用 -ExpandProperty ,如果返回的任何键没有 UninstallString 属性,则会出现错误,因此您可能需要添加-ErrorAction SilentlyContinue选择对象语句。

  5. 全部放在一起:

    foreach ($single_item in (Get-ChildItem 'HKLM:\software\microsoft\windows\currentversion\uninstall')) {
      $uninstall_str = $single_item `
      | Get-ItemProperty `
      | ?{$_.DisplayName -like '*Cisco*TSP*'} `
      | Select-Object -ExpandProperty UninstallString -ErrorAction SilentlyContinue
      $str_to_execute = $uninstall_str -replace '" .*','"'
      Start-Process -FilePath $str_to_execute -ArgumentList '-s','-f1"\\sandbox\Common.Installs\Utils\un.iss"' -Wait -PassThru }
    }
    

    如果保证不超过一个匹配项目,您可以更紧凑地执行此操作:

    $str_to_execute = (
      Get-ChildItem 'HKLM:\software\microsoft\windows\currentversion\uninstall' `
      | Get-ItemProperty `
      | ?{$_.DisplayName -like 'Microsoft*'}
    ).uninstallstring $uninstall_str -replace '" .*','"'
    

    即使PowerShell v3 +中有多个匹配键,更紧凑的版本实际上也能正常工作,但是在v2中,如果有多个匹配键,它将返回null。

    BTW, Where-Object 的缩写。同样, ForEach-Object 的缩写(仅当您将其用作管道中的过滤器时,但 应如何<无论如何都要使用它。)