属性 有值但不能 select
Property has a value but cannot select it
我有一个功能可以检查注册表中是否有名为 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
并且它会 return "Citrix Receiver 4.7"
就像我想要的那样。我的问题是在某些机器上我得到这个:
Get-InstalledApps | Where-Object {$_.Displayname -like "*Citrix Receiver*"} | Select-Object DisplayName
DisplayName
-----------
就是这样。为什么没有列出值?如果我尝试 expandproperty
我会得到一个错误,因为它说什么都没有,但显然那里有东西,否则 Where-Object
不会在我的搜索中找到它。同样,在很多情况下,这段代码工作得很好,我得到了我想要的值,但在很多机器上,我得到的是你在上面看到的。
根据评论编辑:
我 运行 在用户的机器上执行此操作,我得到了我发布的结果。如果我 运行 它在我的机器上,我每次都会得到值 "Citrix Receiver 4.7" 。此外,在我的机器上,我没有得到名称和值列。只有大约 1/4 的机器我 运行 这段代码实际上给了我预期的价值。 Windows 7 vs Windows 10 件事?
在我看来你的函数 return 是一个 [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
您可以做的另一件事是将函数更改为 return 一个对象。
这真的很容易做到 [hashtable]
;所以说你的函数即将 return $hash
,而不是 return:
New-Object -TypeName PSObject -Property $hash
现在您可以使用普通的 cmdlet 套件并让它们按预期工作。
编辑: 看到您的代码后,您似乎已经将哈希表转换为对象,但您的输出却另有说明。如果是这种情况,它不会显示为 Name
和 Value
列,所以我仍然认为有问题并且输出是 [hashtable]
.
编辑 2: 使用有关平台差异的评论中的信息,这似乎正在发生,因为对象转换是通过添加到 [pscustomobject]
type accelerator 完成的PowerShell v3。由于问题机器是 运行 Windows 7,它可能是 运行 v2(这是 Win 7 附带的)。
建议:
- 干掉Windows7.
- 如果您不能这样做,请升级该机器上的 PowerShell(Windows 管理框架)。
- 无论哪种方式,请使用上面发布的
New-Object
。
我有一个功能可以检查注册表中是否有名为 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
并且它会 return "Citrix Receiver 4.7"
就像我想要的那样。我的问题是在某些机器上我得到这个:
Get-InstalledApps | Where-Object {$_.Displayname -like "*Citrix Receiver*"} | Select-Object DisplayName
DisplayName
-----------
就是这样。为什么没有列出值?如果我尝试 expandproperty
我会得到一个错误,因为它说什么都没有,但显然那里有东西,否则 Where-Object
不会在我的搜索中找到它。同样,在很多情况下,这段代码工作得很好,我得到了我想要的值,但在很多机器上,我得到的是你在上面看到的。
根据评论编辑:
我 运行 在用户的机器上执行此操作,我得到了我发布的结果。如果我 运行 它在我的机器上,我每次都会得到值 "Citrix Receiver 4.7" 。此外,在我的机器上,我没有得到名称和值列。只有大约 1/4 的机器我 运行 这段代码实际上给了我预期的价值。 Windows 7 vs Windows 10 件事?
在我看来你的函数 return 是一个 [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
您可以做的另一件事是将函数更改为 return 一个对象。
这真的很容易做到 [hashtable]
;所以说你的函数即将 return $hash
,而不是 return:
New-Object -TypeName PSObject -Property $hash
现在您可以使用普通的 cmdlet 套件并让它们按预期工作。
编辑: 看到您的代码后,您似乎已经将哈希表转换为对象,但您的输出却另有说明。如果是这种情况,它不会显示为 Name
和 Value
列,所以我仍然认为有问题并且输出是 [hashtable]
.
编辑 2: 使用有关平台差异的评论中的信息,这似乎正在发生,因为对象转换是通过添加到 [pscustomobject]
type accelerator 完成的PowerShell v3。由于问题机器是 运行 Windows 7,它可能是 运行 v2(这是 Win 7 附带的)。
建议:
- 干掉Windows7.
- 如果您不能这样做,请升级该机器上的 PowerShell(Windows 管理框架)。
- 无论哪种方式,请使用上面发布的
New-Object
。