1

下面的代码试图做一件事。它试图查找自上次运行作业以来已添加到 Active Directory 组的 ID。

它通过从 Active Directory 组中读取用户 ID 并将它们与前一天保存在文件中的 ID 进行比较来实现这一点。

我首先将 AD 组读入哈希表 ($ADUsersHashtable),然后将文件读入类似的哈希表 ($YesterdaysADUsersFile) 两个哈希表都使用 UserID 作为键。然后我检查 $ADUsersHashtable 中的每个 ID 是否在 $YesterdaysADUsersFile 中。位于 $ADUsersHashtable 但不在 $YesterdaysADUsersFile 中的 ID 是自上次运行此作业以来添加到 AD 的 ID。

问题是,如果 $YesterdaysADUsersFile 中有多个条目,则 containskey 方法总是返回 true(请参见下面的输出)

如果我删除文件中除一个条目之外的所有条目,则代码将按预期工作。

如果我在文件中有多个条目,则代码无法按预期工作。

以下是将 AD 和文件读入哈希表然后比较密钥的代码。

$scriptName = $MyInvocation.MyCommand.Name
$LogFile = "D:\Polarion\data\logs\User Access Dates\$scriptName.log"
$Today = Get-Date
$outDate = get-date -format "yyyy-MM-dd"
Add-content $LogFile "$Today Running $scriptName"
$MyServer = $env:computername
Add-content $LogFile "`t$Today Running on $MyServer"

#Will be populated with IDs from AD that i didn't find yesterday
$NewUsersFile = "D:\Polarion\data\logs\User Access Dates\NewUsersInPEALM_ALL_USERSADGroup.txt" 
clear-content $NewUsersFile #I only want the new users from todays AD group.

$ADUsersHashtable = @{} #Contains IDs of the members in the AD Group.
Get-ADGroupMember -Identity PEALM_ALL_USERS -Recursive `
    | Get-ADObject -Properties SamAccountName, mail `
    | select SamAccountName, mail `
    | foreach {$ADUsersHashtable.Add($_.SamAccountName, $_.mail)}
#$ADUsersHashtable

$YesterdaysADUsersFile = "D:\Polarion\data\logs\User Access Dates\UserIdFromPEALM_ALL_USERS.txt" #Contains the IDs that I knew about the last time this ran.
$YesterdaysADUsersHashTable = @{}
$YesterdaysADUsersHashTable = Get-Content($YesterdaysADUsersFile) | 
    foreach {$_.ToString().Replace(":", "=")} | 
    ConvertFrom-StringData
$YesterdaysADUsersHashTable

$NoNewUsersFound = $true
foreach ($UserIDFromAD in $ADUsersHashtable.keys){ #For each user ID in Todays AD group
    if ($YesterdaysADUsersHashTable.containsKey($UserIDFromAD)){ #If the UserID is in Yesterdays list ignore it.
        write-host YesterdaysADUsersHashTable contains key $UserIDFromAD
    } else {
        $NoNewUsersFound = $false
        write-host YesterdaysADUsersHashTable Doesnt contains key $UserIDFromAD 
        write-host "`tadding $UserIDFromAD to the $NewUsersFile file."
        Add-content $LogFile "`t$Today Adding $UserIDFromAD to $NewUsersFile file"
        Add-Content $NewUsersFile "$UserIDFromAD : $outDate" #if its not in yesterdays list write it to the new users file.
    }
}
if ($NoNewUsersFound){
    Add-content $LogFile "`t$Today No new users IDs found in Active Directory."
}
#Clear-Content $YesterdaysADUsersFile #we want to overwrite the file, not append to it. 
#$ADUsersHashtable.keys `
#    | %{ Add-Content $YesterdaysADUsersFile "$_ : $($ADUsersHashtable.$_)" } #writes the content of the hashtable to a file.

以下是文件(因此 $YesterdaysADUsersHashTable)中有两个条目时的输出。前四行是 $YesterdaysADUsersHashTable 的转储。接下来的五行来自 if-containskey 块中 write-host 命令的输出。它们表明 hashtable.containskey 对 $ADUsersHashtable 中的每个键都返回 true。但是这些键不在 $YesterdaysADUsersHashTable 中,这是我不明白的。

Name                           Value                                                                                                                                               
----                           -----                                                                                                                                               
QZMRW2                         xxxx.xxxx@xxxx.com                                                                                                                 
dzrbcn                         xxxx.xxxx@xxxx.com  

YesterdaysADUsersHashTable contains key QZMRW2
YesterdaysADUsersHashTable contains key dzrbcn
YesterdaysADUsersHashTable contains key MZDP2G
YesterdaysADUsersHashTable contains key BZ5LBQ
YesterdaysADUsersHashTable contains key FZ080Y

$YesterdaysADUsersHashTable 显然不包含“MZDP2G”、“BZ5LBQ”或“FZ080Y”

而且,如果我从文件中删除除一个用户 ID 之外的所有内容,则代码似乎可以正常工作。$YesterdaysADUsersHashTable 现在只有一个条目“QZMRW2”并且代码似乎可以工作。

Name                           Value                                                                                                                                               
----                           -----                                                                                                                                               
QZMRW2                         xxxx.xxxx@xxxx.com  

YesterdaysADUsersHashTable contains key QZMRW2
YesterdaysADUsersHashTable Doesnt contains key dzrbcn
    adding dzrbcn to the D:\Polarion\data\logs\User Access Dates\NewUsersInPEALM_ALL_USERSADGroup.txt file.
YesterdaysADUsersHashTable Doesnt contains key MZDP2G
    adding MZDP2G to the D:\Polarion\data\logs\User Access Dates\NewUsersInPEALM_ALL_USERSADGroup.txt file.
YesterdaysADUsersHashTable Doesnt contains key BZ5LBQ
    adding BZ5LBQ to the D:\Polarion\data\logs\User Access Dates\NewUsersInPEALM_ALL_USERSADGroup.txt file.
YesterdaysADUsersHashTable Doesnt contains key FZ080Y

我显然不明白somehting。

任何建议将不胜感激。

4

2 回答 2

0

我通过将 hashtable.containskey 更改为 -contains 来使代码工作。在下面的代码片段中,我注释了包含 .containsKey($UserIDFromAD) 的行,并添加了包含 $UserIDsFromFile.keys -contains $UserIDFromAD 的行。代码现在按预期工作。

这必须与按引用检查和按值检查之间的区别有关。我知道这在 Java 中是如何工作的,但在 Powershell 中却不知道。

#if ($UserIDsFromFile.containsKey($UserIDFromAD)){ #If the UserID is in Yesterdays list ignore it.
if ($UserIDsFromFile.keys -contains $UserIDFromAD){ #If the UserID is in Yesterdays list ignore it.
于 2020-03-06T13:40:27.157 回答
0

仅仅因为一个键存在并不意味着对应的值不存在$null

请参阅下面的示例:

$a = @{ keyName = "Value" }
$b = @{ keyName = $null }

foreach($key in $a.Keys){
    if($b.ContainsKey($key)){
        $bValue = $b[$key] # or `$b.$key` if the key is a string

        if($null -eq $bValue){
            Write-Host "Key '$key' exists in '`$b', but its value is `$null :("
        }
    }
}

如果没有有关如何填充哈希表的详细信息,很难说出原因:)

于 2020-03-05T15:42:15.350 回答