通過多個 OU 獲取 ADUser 並過濾結果
該腳本應該從多個 OU 中獲取使用者並將使用者分配給一個變數,然後從該變數中獲取使用者並根據超過 30 天的最後登錄日期過濾每個使用者。然後它會導出到包含一些我想要的資訊的 CSV。
問題是,當我到達foreach部分時,它搜尋整個目錄並且不使用我提供的變數中的使用者。
任何批評都非常感謝。
$30days = (get-date).adddays(-30) $Users1 = Get-ADUser -SearchBase 'OU=Users,OU=US-Location,OU=Americas,DC=Domain,DC=Domain,DC=com' -LdapFilter '(UserPrincipalName=*)(extensionAttribute9=*)' $Users2 = Get-ADUser -SearchBase 'OU=Users-Remote,OU=US-Location,OU=Americas,DC=Domain,DC=Domain,DC=com' -LdapFilter '(UserPrincipalName=*)(extensionAttribute9=*)' $Users3 = Get-ADUser -SearchBase 'OU=Contractors,OU=US-Location,OU=Americas,DC=Domain,DC=Domain,DC=com' -LdapFilter '(UserPrincipalName=*)(extensionAttribute9=*)' $Users4 = Get-ADUser -SearchBase 'OU=Temps,OU=US-Location,OU=Americas,DC=Domain,DC=Domain,DC=com' -LdapFilter '(UserPrincipalName=*)(extensionAttribute9=*)' $Users5 = Get-ADUser -SearchBase 'OU=Users,OU=US-Location,OU=Americas,DC=Domain,DC=Domain,DC=com' -LdapFilter '(UserPrincipalName=*)(extensionAttribute9=*)' $Users6 = Get-ADUser -SearchBase 'OU=Users,OU=US-Location,OU=Americas,DC=Domain,DC=Domain,DC=com' -LdapFilter '(UserPrincipalName=*)(extensionAttribute9=*)' $Users = $Users1,$Users2,$Users3,$Users4,$Users5,$Users6 $useraccountsover30days = foreach ($user in $($Users)){Get-ADUser -filter {lastlogondate -le $30days} -Properties lastlogondate} $lastlogonreadable = $useraccountsover30days | Select-Object SamAccountName,lastlogondate $lastlogonreadable | Export-Csv C:/Users/myname/Desktop/Usersover30days.csv
我會對您目前的腳本提出一些建議。
首先,單個大型查詢幾乎總是比許多小型查詢執行得更好。因此
get-aduser
,我不會為每個目標 OU 單獨執行,而是將它們組合成一個呼叫,使用更高級別的公共 OU 作為搜尋庫。顯然,這最終可能會返回您不想包含的 OU 的結果。但是稍後過濾掉它們要快得多。您還
get-aduser
為第一組查詢中的每個結果再次呼叫只是為了過濾 lastLogonDate。但是您可以將該過濾器與-ldapfilter
原始查詢中的過濾器結合使用。只需將-filter
版本轉換為等效-ldapfilter
版本即可。這樣做的秘訣是知道 lastLogonDate 只是 lastLogonTimestamp 屬性的 Powershell 轉換版本。您可以將普通的 Powershell DateTime 值轉換為 lastLogonTimestamp 與該ToFileTime()
方法一起使用的格式。最後讓我感到困惑的是
(UserPrincipalName=*)
你的 ldapfilter 部分。在我接觸過的每個域中,這個屬性總是有一個值(就像 SamAccountName 或 DistinguishedName)。它可能與 的預設值不同<SamAccoutnName>@<DomainFQDN>
,但它永遠不會為空。過濾器不一定會傷害任何東西。AD 在不需要時花費 CPU 週期進行評估只是一件額外的事情。但是,如果你有理由相信它在你的環境中可能是空的,那麼一定要把它留在裡面。因此,如果我正確理解您的意圖,這就是我將如何修改您的腳本。
# make the comparison value using ToFileTime() $30daysago = (Get-Date).AddDays(-30).ToFileTime() # make the combined ldapfilter value $LdapFilter = "(&(lastLogonTimestamp<=$30daysago)(extensionAttribute9=*)" # make an array of the OU DNs you care about $TargetOUs = @( "OU=Users,OU=US-Location,OU=Americas,DC=Domain,DC=Domain,DC=com" "OU=Users-Remote,OU=US-Location,OU=Americas,DC=Domain,DC=Domain,DC=com" "OU=Contractors,OU=US-Location,OU=Americas,DC=Domain,DC=Domain,DC=com" "OU=Temps,OU=US-Location,OU=Americas,DC=Domain,DC=Domain,DC=com" ) # define your common search base $base = "OU=US-Location,OU=Americas,DC=Domain,DC=Domain,DC=com" # get your combined results and the additional attributes you care about $OldUsers = get-aduser -ldapfilter $LdapFilter -searchbase $base -pr lastLogonDate # convert the target OU list into a regular expression we can compare each DN against in a single comparison call $regex = "" $TargetOUs | %{ $regex += ".*," + [Regex]::Escape($_) + "$|" } $regex = $regex.Substring(0,$regex.Length-1) # filter the results that aren't in your target OUs # (depending on your OU layout, it might be more efficient to flip this # and define the OUs you explicitly want to leave out) $FilteredUsers = $OldUsers | ?{ $_.DistinguishedName -match $regex } # export your CSV (sorted for good measure) $FilteredUsers | select SamAccountName,LastLogonDate | sort LastLogonDate | export-csv C:/Users/myname/Desktop/Usersover30days.csv
PS 請注意不要將
lastLogonTimestamp
(或lastLogonDate
)視為 100% 準確。根據設計,它可能會過期 9 到 14 天。