2016-04-21 42 views
3

我有一个Powershell脚本,它获取远程桌面用户会话的列表,并将它们通过SessionID放入散列。Powershell散列包含键不正确返回错误

# 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) 
} 

然后我就可以转储$ userSessionByID在PowerShell ISE中

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。

+1

sessionid是什么类型? '$ userSession.SessionId.Gettype()'返回什么? –

+0

我认为问题可能是$ userSession.SessionId.GetType()返回UInt32,而Get-Process返回SessionId是Int32的对象。 – bpeikes

+0

这是否意味着'$ userSessionBySessionID.ContainsKey(4 -as [uint32])'有效? – Matt

回答

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运营商,如果你使用的是含有整数-as变量,你可以做一个简单的投用然而[uint32]6会有帮助。

密钥本身可以靠近任何对象,并且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 
+0

这是问题所在。在键入对象字段时使用Powershell哈希值时,必须非常小心。引用密钥时,所有东西都应该转换为单一类型。 – bpeikes

+1

@bpeikes只是想确保你抓到了我刚做的一个编辑。你不需要使用'-as',你可以做'[uint32] 6'。我只表明它期望你可能使用变量而不是幻数。 – Matt

+0

谢谢。我想出了如何让它起作用。我总是在添加哈希时以及尝试获取值或测试是否存在时投射字段。请参阅下面的答案。 – bpeikes

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

0

阅读他人的答复后,我找出问题所在,即会话id,不同类型的GET-RDUserSession未来和获取进程时。代码更改为:

# 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]。