代码之家  ›  专栏  ›  技术社区  ›  noz3r0

属性具有值,但无法选择该值

  •  2
  • noz3r0  · 技术社区  · 7 年前

    我有一个函数,用于检查注册表中名为Get-InstalledApps的卸载项

    Function Get-InstalledApps {
        param (
            [Parameter(ValueFromPipeline=$true)]
            [string[]]$ComputerName = $env:COMPUTERNAME,
            [string]$NameRegex = ''
        )
    
        foreach ($comp in $ComputerName) {
            $keys = '','\Wow6432Node'
            foreach ($key in $keys) {
                try {
                    $reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $comp)
                    $apps = $reg.OpenSubKey("SOFTWARE$key\Microsoft\Windows\CurrentVersion\Uninstall").GetSubKeyNames()
                } catch {
                    continue
                }
    
                foreach ($app in $apps) {
                    $program = $reg.OpenSubKey("SOFTWARE$key\Microsoft\Windows\CurrentVersion\Uninstall\$app")
                    $name = $program.GetValue('DisplayName')
                    if ($name -and $name -match $NameRegex) {
                        [pscustomobject]@{
                            ComputerName = $comp
                            DisplayName = $name
                            DisplayVersion = $program.GetValue('DisplayVersion')
                            Publisher = $program.GetValue('Publisher')
                            InstallDate = $program.GetValue('InstallDate')
                            UninstallString = $program.GetValue('UninstallString')
                            Bits = $(if ($key -eq '\Wow6432Node') {'64'} else {'32'})
                            Path = $program.name
                        }
                    }
                }
            }
        }
    }
    

    然后我获取所需的显示名称/版本。我目前的问题是,它似乎只在某些机器上起作用。例子:

    Get-InstalledApps | Where-Object {$_.Displayname -like "*Citrix Receiver*"}
    
    Name                           Value
    ----                           -----
    InstallDate
    ComputerName                   Computer
    DisplayName                    Citrix Receiver 4.7
    Bits                           64
    UninstallString                C:\ProgramData\Citrix\Citrix Receiver 4.7\TrolleyExpress.exe /uninstall /cleanup
    Path                           HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\CitrixOnlinePluginPackWeb
    Publisher                      Citrix Systems, Inc.                                                              
    DisplayVersion                 14.7.0.13011
    

    这很好,我得到了我想要的。现在我通常只是插嘴 | Select-Object Displayname -ExpandProperty Displayname 它会回来的 "Citrix Receiver 4.7" 就像我想要的那样。我的问题是,在某些机器上,我得到的是:

    Get-InstalledApps | Where-Object {$_.Displayname -like "*Citrix Receiver*"} | Select-Object DisplayName
    
    DisplayName
    -----------
    

    就这样。为什么没有列出值?如果我试着 expandproperty 我得到了一个错误,因为它说什么都没有,但很明显,有什么东西在那里或 Where-Object 在我的搜索中找不到它。同样,在很多情况下,这段代码工作得很好,我得到了我想要的值,但在很多机器上,我得到了您上面看到的结果。

    从注释中编辑:

    我在用户的机器上运行这个,然后得到我发布的结果。如果我在我的机器上运行它,每次都会得到值“Citrix Receiver 4.7”。此外,在我的机器上,我没有获得名称和值列。在我运行此代码的机器中,只有大约四分之一的机器实际给了我预期的值。Windows 7 vs Windows 10?

    1 回复  |  直到 7 年前
        1
  •  1
  •   briantist    7 年前

    在我看来,您的函数返回 [hashtable] ,但您使用它就像它是一个具有属性的对象一样。

    这正好适合 Where-Object 因为 .Member 语法用于访问 [哈希表] 价值观,但它不适用于 Select-Object 因为它是在实际属性上运行的。

    那么你能做什么呢?

    如果你想把它作为 [哈希表] ,并坚持在管道中进行,您可以使用 ForEach-Object :

    Get-InstalledApps | 
        Where-Object {$_.Displayname -like "*Citrix Receiver*"} |
        ForEach-Object -Process { $_.DisplayName }
    

    Get-InstalledApps | 
        Where-Object {$_.Displayname -like "*Citrix Receiver*"} |
        ForEach-Object -MemberName Item -ArgumentList DisplayName
    

    您可以做的另一件事是更改函数以返回对象。

    使用 [哈希表] ; 假设您的函数即将返回 $hash ,而不是返回:

    New-Object -TypeName PSObject -Property $hash
    

    现在,您可以使用普通的cmdlet套件,并让它们按预期工作。


    编辑: 看到代码后,看起来您已经在将哈希表转换为对象了,但您的输出显示了不同的结果。它不会显示为 Name Value 如果是这样的话,那么我仍然认为有问题,输出是 [哈希表] .

    编辑2: 根据来自平台差异评论的信息,这似乎是因为对象转换是使用 [pscustomobject] type accelerator 这是在PowerShell v3中添加的。由于有问题的机器运行的是Windows 7,它可能运行的是v2(这是Win 7附带的)。

    建议:

    1. 摆脱Windows 7。
    2. 如果无法做到这一点,请在该计算机上升级PowerShell(Windows Management Framework)。
    3. 无论哪种方式,使用 New-Object 如上所述。
    推荐文章