Powershell hash containskey错误地返回false

时间:2016-04-21 16:20:42

标签: powershell hash

我有一个Powershell脚本,它获取远程桌面用户会话列表,并通过SessionID将它们放入哈希值。

# Create a hashtable which contains all of the remote desktop sessions by SessionId
$userSessionBySessionID = @{}
ForEach($userSession in Get-RDUserSession -CollectionName $collectionName)
{
    $userSessionBySessionID.Add($userSession.SessionId, $userSession)
}
然后我可以在PowerShell ISE中转储$ userSessionByID

Name                           Value                                                                                                                                                                                                          
----                           -----                                                                                                                                                                                                          
9                              Microsoft.RemoteDesktopServices.Management.RDUserSession                                                                                                                                                       
8                              Microsoft.RemoteDesktopServices.Management.RDUserSession                                                                                                                                                       
7                              Microsoft.RemoteDesktopServices.Management.RDUserSession                                                                                                                                                       
6                              Microsoft.RemoteDesktopServices.Management.RDUserSession                                                                                                                                                       
5                              Microsoft.RemoteDesktopServices.Management.RDUserSession                                                                                                                                                       
4                              Microsoft.RemoteDesktopServices.Management.RDUserSession                                                                                                                                                       
2                              Microsoft.RemoteDesktopServices.Management.RDUserSession                                                                                                                                                       
1                              Microsoft.RemoteDesktopServices.Management.RDUserSession       

令人沮丧的是$ userSessionBySessionID.ContainsKey(4)返回false。我在这里错过了什么?我也尝试了$ userSessionBySessionID.ContainsKey(“4”),但也返回false。

3 个答案:

答案 0 :(得分:2)

  

我认为问题可能是$userSession.SessionId.GetType()返回[UInt32]

在测试中,这是你的问题。考虑以下测试,我使用[UInt32]创建哈希表。

$test = @{}
1..10 | %{$test.add($_ -as [uint32],$_%2)}

正如您所见,正在运行$test.containskey(6)会返回false。我也遇到$test.containskey("6")同样的问题。但是这会返回true ....

$test.containskey(6 -as [uint32])

注意:您不需要在此处使用-as运算符,因为您可以使用[uint32]6进行简单的转换,但是如果您使用的是包含整数的变量-as会有所帮助。

密钥本身可以靠近任何对象,containskey()在所有情况下都返回正确的结果。您的散列表没有带整数的密钥6.此外,[uint32] cannot be converted to [int] since it has a higher upper bound因此无法进行强制转换。这就是PowerShell或底层.Net不会进行“自动”转换的原因。在实践中,我认为在这种情况下不会发生这种情况。

点确定你是类型识别的。

与上面相同的例子,除了这次我们使用整数。

1..10 | %{$test.add($_,$_%2)}

$test.containskey(6)
True

$test.containskey("6")
False

当我用字符串创建键时,我可以反转调查结果。

1..10 | %{$test.add("$_",$_%2)}

$test.containskey(6)
False

$test.containskey("6")
True

答案 1 :(得分:0)

我测试过并发现$ userSessionBySessionID.ContainsKey(4)将返回false。但$ userSessionBySessionID.ContainsKey(“4”)返回true。

我使用的代码如下。请试一试,如果有帮助请告诉我:

    # Create a hashtable which contains all of the remote desktop sessions by SessionId
    $userSessionBySessionID = @{}

    Get-RDUserSession -CollectionName $collectionName | % {$userSessionBySessionID.Add($_.SessionId.ToString().Trim(), $_)}

更多技术信息

根据内部帮助定义包含密钥是:

bool ContainsKey(System.Object key)

您可以将字符串解析为此但不是整数。 您还可以通过运行以下代码来检查上述定义,即不带括号。它显示方法的定义和任何重载。:

$userSessionBySessionID.ContainsKey

答案 2 :(得分:0)

在阅读其他人的回复后,我弄清楚问题是什么,即来自Get-RDUserSession和Get-Process时,SessionId是一种不同的类型。代码更改为:

# Create a hashtable which contains all of the remote desktop sessions by SessionId
$userSessionBySessionID = @{}
ForEach($userSession in Get-RDUserSession -CollectionName $collectionName)
{
    $userSessionBySessionID.Add([long]$userSession.SessionId, $userSession)
}

$userSessionsRunningSurveyor = @()
ForEach($proc in Get-Process -IncludeUserName)
{
    $sessionId = [long]$proc.SessionId
    $execPath = $proc.Path
    Write-Debug "Checking for SessionID $sessionId, Path $execPath"
    if($userSessionBySessionID.ContainsKey($sessionId) -and $execPath -and $collectionPaths.ContainsKey($execPath))
    {
        $userName=$proc.UserName
        Write-Debug "Found user $userName running $execPath on SessionID $sessionId"
        $userSession = $userSessionBySessionID[$sessionId]
        $userSessionsRunningSurveyor += $userSession
    }
}

在添加密钥和检查密钥是否存在时,请注意转换为[long]。