Powershell 带或不带代码块的组对象差异
下面的代码生成2个“相同”的哈希表,但是在使用代码块分组的哈希表上,我无法从键中获取项Powershell 带或不带代码块的组对象差异,powershell,powershell-4.0,Powershell,Powershell 4.0,下面的代码生成2个“相同”的哈希表,但是在使用代码块分组的哈希表上,我无法从键中获取项 $HashTableWithoutBlock = Get-WmiObject Win32_Service | Group-Object State -AsHashTable $HashTableWithBlock = Get-WmiObject Win32_Service | Group-Object {$_.State} -AsHashTable Write-Host "Search
$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
这两个哈希表之间的区别是什么
如何获取第二个按代码块分组的项目
编辑:不仅仅是一种解决方法,我想知道是否可以通过表查找来检索我想要的项,如果可以,如何检索?两个
哈希表之间的区别在于$HashTableWithBlock
将其键包装在PSObject
中。问题是PowerShell在将其传递给方法调用之前通常会展开PSObject
,所以即使您有正确的密钥,也不能只将其传递给indexer。为了解决这个问题,您可以创建helper C#方法,该方法将使用right对象调用indexer。另一种方法是使用反射:
添加类型-TypeDefinition@'
公共静态类助手{
公共静态对象IndexHashtableByPSObject(System.Collections.IDictionary表,对象[]键){
返回表[键[0]];
}
}
'@
$HashTableWithBlock=获取WmiObject Win32|u服务|组对象{$\uu.State}-AsHashTable
$Key=$HashTableWithBlock.Keys-eq“已停止”
#辅助方法
[Helper]::IndexHashtableByPSObject($HashTableWithBlock,$Key)
#倒影
[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
,你几乎可以自己构建一个哈希表
请注意,有趣的是,如果改为对ScriptProperty进行分组,这将不起作用。我还没有弄清楚原因。其他海报是正确的,问题在于密钥存储为PSObject
,但有一个内置解决方案:使用-AsString
开关和-AsHashTable
。这将强制将密钥存储为字符串。你可以看看代码
我在GitHub上打开了一个用于此bug的程序。我注意到,使用一个块,显然可以按多个属性分组,然后将哈希表键转换为一个对象。但是,如果只有一个属性,我会假设它是一个普通字符串,并且我的查找应该可以工作。.在$HashTableWithBlock中,PSObject
中包含了块键,因此Hashtable
无法正确比较它们。@PetSerAl我明白了,但是您如何进行正确的查找?即使我创建了一个带有属性的PSObject,我也怀疑比较会比较对象引用。如果不使用块,不能按多个属性分组吗?你到底想做什么?为什么必须使用哈希表?我只能建议重新创建哈希表
:$HashTableWithBlock.GetEnumerator()|%{$HashTableWithBlock=@{}}{$HashTableWithBlock.Add($..Key,$..Value)}
@PetSerAI谢谢,看起来很有趣。但是,我不明白为什么调用表[key[0]]不同。是因为.Net对IDictionary和Object的隐式强制转换吗?因为其他原因,这将起作用:$HashTableWithBlock[($HashTableWithBlock.Keys-eq'Stopped')[0]
@LukeMarlin PowerShell将打开此表达式的结果PSObject
($HashTableWithBlock.Keys-eq'Stopped')[0]
,并在索引器中只传递字符串。@PetSerAI感谢您的帮助。不过,我希望与C#Net相比,PS中没有太多其他奇怪的东西!