有或没有代码块的组对象差异
Group-Object diffencies with or without code block
下面的代码生成 2 "identical" 哈希 table,但是在使用代码块分组的代码上我无法从键中获取项目。
$HashTableWithoutBlock =
Get-WmiObject Win32_Service | Group-Object State -AsHashTable
$HashTableWithBlock =
Get-WmiObject Win32_Service | Group-Object {$_.State} -AsHashTable
Write-Host "Search result for HashTable without using code block : " -NoNewline
if($HashTableWithoutBlock["Stopped"] -eq $null)
{
Write-Host "Failed"
}
else
{
Write-Host "Success"
}
Write-Host "Search result for HashTable with code block : " -NoNewline
if($HashTableWithBlock["Stopped"] -eq $null)
{
Write-Host "Failed"
}
else
{
Write-Host "Success"
}
输出:
Search result for HashTable without using code block : Success
Search result for HashTable with code block : Failed
两个Hashtable有什么区别?
如何获取按代码块分组的第二个项目?
编辑:不仅仅是解决方法,我想知道是否可以使用 table lookup 检索我想要的项目,如果可以, 怎么样?
两个 Hashtable
的区别在于 $HashTableWithBlock
的密钥包含在 PSObject
中。问题是 PowerShell 在将 PSObject
传递给方法调用之前通常会对其进行解包,因此即使您拥有正确的密钥,您仍然不能将其传递给索引器。要解决此问题,您可以创建辅助 C# 方法,该方法将使用正确的对象调用索引器。另一种方法是使用反射:
Add-Type -TypeDefinition @'
public static class Helper {
public static object IndexHashtableByPSObject(System.Collections.IDictionary table,object[] key) {
return table[key[0]];
}
}
'@
$HashTableWithBlock = Get-WmiObject Win32_Service | Group-Object {$_.State} -AsHashTable
$Key=$HashTableWithBlock.Keys-eq'Stopped'
#Helper method
[Helper]::IndexHashtableByPSObject($HashTableWithBlock,$Key)
#Reflection
[Collections.IDictionary].InvokeMember('','GetProperty',$null,$HashTableWithBlock,$Key)
这是我找到的一个解决方法,它真的不是很好:
$HashTableWithBlock =
Get-WmiObject Win32_Service | ForEach-Object -Process {
$_ | Add-Member -NotePropertyName _StateProp -NotePropertyValue $_.State -Force -Passthru
} |
Group-Object -Proerty _StateProp -AsHashTable
我的意思是,我想一旦你做了 ForEach-Object
你几乎还不如自己构建一个哈希表?
请注意,有趣的是,如果您改为在 ScriptProperty 上分组,这将 不会 起作用。我还没弄明白为什么。
其他张贴者是正确的,问题是密钥存储为 PSObject
但有一个内置的解决方案:使用 -AsString
开关和 -AsHashTable
.这将强制将密钥存储为字符串。你可以看看代码here
我已经在 GitHub 上为这个错误打开了一个 issue。
下面的代码生成 2 "identical" 哈希 table,但是在使用代码块分组的代码上我无法从键中获取项目。
$HashTableWithoutBlock =
Get-WmiObject Win32_Service | Group-Object State -AsHashTable
$HashTableWithBlock =
Get-WmiObject Win32_Service | Group-Object {$_.State} -AsHashTable
Write-Host "Search result for HashTable without using code block : " -NoNewline
if($HashTableWithoutBlock["Stopped"] -eq $null)
{
Write-Host "Failed"
}
else
{
Write-Host "Success"
}
Write-Host "Search result for HashTable with code block : " -NoNewline
if($HashTableWithBlock["Stopped"] -eq $null)
{
Write-Host "Failed"
}
else
{
Write-Host "Success"
}
输出:
Search result for HashTable without using code block : Success
Search result for HashTable with code block : Failed
两个Hashtable有什么区别?
如何获取按代码块分组的第二个项目?
编辑:不仅仅是解决方法,我想知道是否可以使用 table lookup 检索我想要的项目,如果可以, 怎么样?
两个 Hashtable
的区别在于 $HashTableWithBlock
的密钥包含在 PSObject
中。问题是 PowerShell 在将 PSObject
传递给方法调用之前通常会对其进行解包,因此即使您拥有正确的密钥,您仍然不能将其传递给索引器。要解决此问题,您可以创建辅助 C# 方法,该方法将使用正确的对象调用索引器。另一种方法是使用反射:
Add-Type -TypeDefinition @'
public static class Helper {
public static object IndexHashtableByPSObject(System.Collections.IDictionary table,object[] key) {
return table[key[0]];
}
}
'@
$HashTableWithBlock = Get-WmiObject Win32_Service | Group-Object {$_.State} -AsHashTable
$Key=$HashTableWithBlock.Keys-eq'Stopped'
#Helper method
[Helper]::IndexHashtableByPSObject($HashTableWithBlock,$Key)
#Reflection
[Collections.IDictionary].InvokeMember('','GetProperty',$null,$HashTableWithBlock,$Key)
这是我找到的一个解决方法,它真的不是很好:
$HashTableWithBlock =
Get-WmiObject Win32_Service | ForEach-Object -Process {
$_ | Add-Member -NotePropertyName _StateProp -NotePropertyValue $_.State -Force -Passthru
} |
Group-Object -Proerty _StateProp -AsHashTable
我的意思是,我想一旦你做了 ForEach-Object
你几乎还不如自己构建一个哈希表?
请注意,有趣的是,如果您改为在 ScriptProperty 上分组,这将 不会 起作用。我还没弄明白为什么。
其他张贴者是正确的,问题是密钥存储为 PSObject
但有一个内置的解决方案:使用 -AsString
开关和 -AsHashTable
.这将强制将密钥存储为字符串。你可以看看代码here
我已经在 GitHub 上为这个错误打开了一个 issue。