2016-04-21 41 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]。