在多个 OU 上获取 ADUser 并过滤结果

And*_*vis 2 powershell active-directory windows-server-2008-r2 powershell-v3.0

该脚本应该从多个 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 
Run Code Online (Sandbox Code Playgroud)

Rya*_*ger 5

我会对您当前的脚本提出一些建议。

首先,单个大查询几乎总是比许多小查询执行得更好。因此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
Run Code Online (Sandbox Code Playgroud)

PS 小心对待lastLogonTimestamp(或lastLogonDate)为 100% 准确。根据设计,它可能会过期 9 到 14 天