This script is supposed to grab users from several OUs and assign the users to one variable, then it takes the users from that variable and filters through each one based on last logon dates over 30 days of age. Then it exports to a CSV with some info I'd like.
The problem is, when I get to the foreach part, it searches through the entire directory and doesn't use the users in the variable I supplied.
Any criticism is greatly appreciated as well.
$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
There are a few recommendations I'd make with your current script.
First off, a single large query is almost always going to perform better than many smaller queries. So rather than running
get-aduser
separately for each target OU, I would combine them into a single call using a higher level common OU as the search base. Obviously, this may end up returning results from OUs you didn't want to include. But it's much faster to filter those out later.You're also calling
get-aduser
again for each result from the first set of queries just to filter on lastLogonDate. But you could instead combine that filter with the-ldapfilter
from your original queries. It's just a matter of converting the-filter
version with an equivalent-ldapfilter
version. The secret to doing this is knowing that lastLogonDate is just a Powershell converted version of the lastLogonTimestamp attribute. And you can convert a normal Powershell DateTime value into the format that lastLogonTimestamp uses with theToFileTime()
method.The last thing that confused me was the
(UserPrincipalName=*)
portion of your ldapfilter. In every domain I've ever touched, this attribute will always have a value (just like SamAccountName or DistinguishedName). It may be different than the default value of<SamAccoutnName>@<DomainFQDN>
, but it's never empty. The filter isn't hurting anything necessarily. It's just one extra thing for AD to spend CPU cycles evaluating when it doesn't need to. But if you have reason to believe it might be empty in your environment, by all means leave it in.So here's how I'd modify your script if I understand your intentions correctly.
P.S. Be wary of treating
lastLogonTimestamp
(orlastLogonDate
) as 100% accurate. It may be anywhere from 9 to 14 days out of date by design.I solved a similar request for multiple OUs with repeating the same set like the following multiple times with the OU specified:
It gets all enabled Accounts, with the properties Name, LastLogonDate, AccountExpirationDate, description, Department, title, UserPrincipalName and appends it to a csv-File. As stated in the other Answer 30 days can be not precise, so better call for 44 days just to be sure.
If "LastLogonDate" is empty, the user has never logged on, perhaps it is a new Account.
You never use the $user value in the Get-ADUser call...try changing the $UsersX value to the parameters you need to send to Get-ADUser and substitute them in...and since you're reusing the same LdapFilter, might as well make that a variable as well. (Also, you're reusing the "OU=Users,OU=US-Location" three times, I assume that's just for example purposes?)