具有或不具有代码块的组对象差异

时间:2015-01-28 10:37:04

标签: powershell powershell-v4.0

下面的代码生成2个“相同”的Hashtables,但是在使用代码块分组的代码块中,我无法从密钥中获取项目。

$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

两个Hashtables有什么区别?

如何获取按代码块分组的第二个项目?

编辑:不仅仅是一种解决方法,我想知道是否可以通过表格查找检索我想要的项目,如果是,那该怎么办?

2 个答案:

答案 0 :(得分:4)

两个Hashtable之间的区别在于$HashTableWithBlock将其密钥包含在PSObject中。问题是PowerShell在将它传递给方法调用之前通常会解开PSObject,所以即使你有正确的密钥,你仍然不能将它传递给索引器。要解决此问题,您可以创建帮助程序C#方法,该方法将使用正确的对象调用indexer。另一种方法是使用反射:

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)

答案 1 :(得分:0)

这是我发现的一种解决方法,实际上并不是很好:

$HashTableWithBlock = 
    Get-WmiObject Win32_Service | ForEach-Object -Process {
        $_ | Add-Member -NotePropertyName _StateProp -NotePropertyValue $_.State -Force -Passthru
    } |
    Group-Object -Proerty _StateProp -AsHashTable

我的意思是,我猜你曾经做过ForEach-Object,你几乎可以自己建立一个哈希表吗?

请注意,有趣的是,如果您在ScriptProperty上进行分组,这将。我还没弄清楚原因。