我有一个函数可以检查注册表中是否有名为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
}
}
}
}
}
}
然后我抓住DisplayName / Version以获得我需要的东西。我目前的问题是它似乎只适用于某些机器。例如:
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”的值。另外,在我的机器上,我没有获得Name和Value列。我运行此代码的机器中只有大约1/4实际上给了我预期的值。 Windows 7与Windows 10的关系?
答案 0 :(得分:1)
在我看来,你的函数返回[hashtable]
,但你正在使用它,就像它是一个具有属性的对象。
这恰好适用于Where-Object
,因为.Member
语法适用于访问[hashtable]
值,但它不适用于Select-Object
,因为它在实际属性上运行
那你能做什么?
如果您希望将其保留为[hashtable]
,并坚持在管道中执行此操作,则可以使用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
您可以做的另一件事是更改函数以返回对象。
使用[hashtable]
这很容易做到;所以说你的函数即将返回$hash
,而是返回:
New-Object -TypeName PSObject -Property $hash
现在,您可以使用正常的cmdlet套件并让它们按预期工作。
看到你的代码后, 编辑,看起来你已经将哈希表转换为一个对象了,但你的输出却说不然。如果是这种情况,它不会显示为Name
和Value
列,所以我仍然认为出现了错误,输出为[hashtable]
。
编辑2:,其中包含有关平台差异的评论信息,这似乎正在发生,因为对象转换是使用PowerShell v3中添加的[pscustomobject]
type accelerator完成的。由于有问题的机器运行的是Windows 7,它可能正在运行v2(这是Win 7附带的)。
建议:
New-Object
。