Há algumas recomendações que eu faria com seu script atual.
Primeiramente, uma única consulta grande quase sempre terá um desempenho melhor do que muitas consultas menores. Portanto, em vez de executar get-aduser
separadamente para cada UO de destino, eu as combinaria em uma única chamada usando uma UO comum de nível superior como base de pesquisa. Obviamente, isso pode acabar retornando resultados de UOs que você não deseja incluir. Mas é muito mais rápido filtrá-los depois.
Você também está chamando get-aduser
para cada resultado do primeiro conjunto de consultas apenas para filtrar lastLogonDate. Mas você poderia combinar esse filtro com o -ldapfilter
de suas consultas originais. É só uma questão de converter a versão -filter
com uma versão -ldapfilter
equivalente. O segredo para fazer isso é saber que lastLogonDate é apenas uma versão convertida Powershell do atributo lastLogonTimestamp. E você pode converter um valor normal de Powershell DateTime no formato que lastLogonTimestamp usa com o ToFileTime()
método.
A última coisa que me confundiu foi a parte (UserPrincipalName=*)
do seu ldapfilter. Em todos os domínios que já toquei, esse atributo sempre terá um valor (como SamAccountName ou DistinguishedName). Pode ser diferente do valor padrão de <SamAccoutnName>@<DomainFQDN>
, mas nunca está vazio. O filtro não está prejudicando nada necessariamente. É apenas uma coisa extra para o AD gastar os ciclos da CPU avaliando quando não precisa. Mas se você tem motivos para acreditar que pode estar vazio em seu ambiente, por favor, deixe-o entrar.
Então, aqui está como eu modificaria o seu script se eu entendesse suas intenções corretamente.
# 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 = @()
$TargetOUs += "OU=Users,OU=US-Location,OU=Americas,DC=Domain,DC=Domain,DC=com"
$TargetOUs += "OU=Users-Remote,OU=US-Location,OU=Americas,DC=Domain,DC=Domain,DC=com"
$TargetOUs += "OU=Contractors,OU=US-Location,OU=Americas,DC=Domain,DC=Domain,DC=com"
$TargetOUs += "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
P.S. Desconfie de tratar lastLogonTimestamp
(ou lastLogonDate
) como 100% preciso. Pode estar em qualquer lugar entre 9 a 14 dias desatualizados por design .