【发布时间】:2020-03-05 15:21:38
【问题描述】:
以下代码试图做一件事。它试图查找自上次运行作业以来已添加到 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
我显然不理解某些东西。
任何建议将不胜感激。
【问题讨论】:
-
存在一个 key 并不意味着它引用的值不是
$null:) -
@MathiasR.Jessen 可能解决了它 - 重现错误:
$hash = @{MyKey = $null}; $hash.MyKey; $hash.MyKey.GetType()。因为哈希表查找键,但返回值,$UserIDsFromPEALM_ALL_USERSFileHashTable.$key.GetType()试图获取值的类型。我不确定是否有可能获得这样的密钥类型。 -
如果你想要循环内的键类型,只需执行
$key.GetType():) -
@MathiasR.Jessen 好的,但我的意思是在我的例子中,当没有循环时。
-
嗯,可以有多个键 - 如果你只想要第一个:
$hash.Keys[0].GetType()