HelloThere,
we get AD-Users from an import script that runs daily and if a user was found in a csv we write the current date in the extensionattribute1 in format "dd-MM-yyyy".
Now we want to calculate if a AD user has a different date in the extensionattribute1 (minus 90 days) then we want to inform their managers what should happen to those accounts.
Interesting is, with my query we get correct Users and some Users between 30 and 90 Days. I don't know what is wrong in my code or with the syntax - can someone pls help? Thanks
sorry, i am not a PowerShell Pro by now but working on it :D
Greetings
# get date -90 Days
$date = (Get-Date).AddDays(-90).ToString("dd-MM-yyyy")
$date
# it gets "27-08-2022" -> so the script should only show users less than this date
# query for extensionattribute1 less than 90 days
get-aduser -properties ExtensionAttribute1 -filter {(enabled -eq "true") -and (extensionAttribute1 -gt $date)}
# here the output is partial correct, we get users with an extensionattribute1 from
# 31-05-2022
# 30-06-2022
# 29-07-2022
# but also some Users with a date from between 30 and 90 days what is incorrect =/
# 30-09-2022
# 31-10-2022
You should not compare date strings against eachother, especially not when you use date format "dd-MM-yyyy", since that is a non-sortable date format. (you might get away with it if you would have used format 'yyyy-MM-dd'..)
Instead, convert the value found in the ExtensionAttribute1 to a DateTime object first and compare that to a real reference DateTime object.
Try
# get date -90 Days
$date = (Get-Date).AddDays(-90).Date # set to midnight with time part '00:00:00'
# query for extensionattribute1 less than 90 days
Get-ADUser -Properties ExtensionAttribute1 -Filter 'Enabled -eq $true -and ExtensionAttribute1 -like "*"' |
Where-Object {[datetime]::ParseExact($_.ExtensionAttribute1, 'dd-MM-yyyy', $null) -gt $date}
Related
I'm working on scripts which send emails to users 14, 10, 7, 3 days before password expiring.
Password expires in 60 days.
If I set like below it works for accounts with 3 and less days to expiring. I don't want accounts with 2 days, 1 day, etc.
$ExpiringUsers = $AdUsers | where PasswordLastSet -lt (get-date).AddDays(-57)
If I set like below it doesn't work at all
$ExpiringUsers = $AdUsers | where PasswordLastSet -eq (get-date).AddDays(-57)
How to set equal 3 days not more not less.
Thanks!
You need to define and filter by a time range, for example, set equal 3 days not more not less would be like this:
$start = [datetime].AddDays(-3) # => April 2 at 12:00 AM
$finish = [datetime].AddDays(-2) # => April 3 at 12:00 AM
# Note `-lt $finish` instead of `-le $finish`
$AdUsers | Where-Object { $_.PasswordLastSet -ge $start -and $_.PasswordLastSet -lt $finish }
A better approach is to use msDS-UserPasswordExpiryTimeComputed for checking how long until the account credential expires:
$serviceAccounts =
'acct1#domain.tld',
'acct2#domain.tld
$daysLeft = 20
$expiringAccounts = ( $serviceAccounts | Foreach-Object {
Get-AdUser -Filter "(UserPrincipalName -eq '$_' -Or sAMAccountName -eq '$_' ) -And ( PasswordNeverExpires -eq 'false' )" -Properties msDS-UserPasswordExpiryTimeComputed |
Where-Object { ( New-TimeSpan -Start $currentDate -End ( [DateTime]::FromFileTime( $_.'msDS-UserPasswordExpiryTimeComputed' ) ) ).Days -le $daysLeft }
} )
As written, this code will gather the accounts expiring within 20 days. Adjust $daysLeft to control the remaining threshold until expiry.
Note that [DateTime]::FromFileTime is required to transpose the value ofmsDS-UserPasswordExpiryTimeComputed from the file-time format it is stored in AD as to a workable DateTime object.
You can define the account as a sAMAccountName or in Universal Principal Name (UPN) format.
This also exemplifies using AD filters in order to have AD return only the objects you need for this query, minimizing the local processing performed with Where-Object.
The notable exception is msDS-UserPasswordExpiryTimeComputed; because it is a Constructed Attribute within Active Directory, neither AD filters or LDAP filters can evaluate it and so this must be done via additional local processing.
Here is an answer I have also written which goes into deeper detail on using the AD filter syntax.
What is wrong with PasswordLastSet for checking credential expiration if you know the account's lifecycle?
The problem with checking PasswordLastSet is that, while it works, if the threshold until expiry changes on the Active Directory side, your script will need to be updated or it will incorrectly identify accounts whose credential is set to expire soon. It also becomes more difficult to track which accounts are beholden to different lifecycles in environments where not all accounts are beholden to the same security policies.
For all employees of our company, who left the company, we set the attribute msExchExtensionCustomAttribute1 to the date, when the employee will leave the company.
I would like to get all AD users with Get-ADUser, where the first value of the list is set and the date value of the first value in the attribute is younger than the current date.
How can i achieve this with Powershell? With Filter?
I tried this:
Get-ADUser -Filter {msExchExtensionCustomAttribute1 -gt Get-Date}
but i got an ADFilterPArsingException
Try following code
Get-ADUser -Filter * -Properties * | ?{$_.msExchExtensionCustomAttribute1} | ?{[datetime]::ParseExact($_.msExchExtensionCustomAttribute1, "dd.MM.yyyy", $null) -lt (get-date)}
Hello and thank you for taking the time to read this.
I am writing a program that will look back at a certain date range and then return the values that I specify in a get-aduser cmdlet
The code I have thus far is here:
$grabDate = Read-Host 'enter how many days back you want to search'
$date = Get-Date
$desiredDate = $date.AddDays(- $grabDate)
Write-Host $desiredDate 'to' $date 'is your search range'
Pause
Get-ADUser -Filter * -Properties Name, LastLogonDate | Where-Object { $date.AddDays(- $grabDate) } | Select-Object name, LastLogonDate
I know that this is not the cleanest code and there are some redundant steps my main focus is on the line:
Get-ADUser -Filter * -Properties Name, LastLogonDate | Where-Object { $date.AddDays(- $grabDate) } | Select-Object name, LastLogonDate
when I enter 30 days to search back, I am getting strange entries from 2016, does anyone see anything strange with my code?
No need for the pipeline here - just use a little simple math, a conversion from string to int, and use the -Filter parameter as it was designed.
Set $grabDate like this, so you get an actual int value, not a string
# Convert Read-Host input to an integer, and multiply by -1 to get the negative value
$grabDate = [Convert]::ToInt32( (Read-Host 'enter how many days back you want to search' ) ) * -1
Then call Get-ADUser with the following -Filter parameter:
# Use the filter to return only the users who haven't logged on in the
# last $grabDate days
Get-ADUser -Filter "LastLogonDate -ge '$((Get-Date).AddDays( $grabDate ))'"
This way, you only return the ADUsers you care about and you don't have to process the list of users a second time. Using -Filter * can be a costly operation, especially in larger AD environments.
Import-Module ActiveDirectory
# Set the number of days since last logon
$DaysInactive = 90
$InactiveDate = (Get-Date).Adddays(-($DaysInactive))
#-------------------------------
# FIND INACTIVE USERS
#-------------------------------
# Below are four options to find inactive users. Select the one that is most appropriate for your requirements:
# Get AD Users that haven't logged on in xx days
$Users = Get-ADUser -Filter { LastLogonDate -lt $InactiveDate -and Enabled -eq $true } -Properties LastLogonDate | Select-Object #{ Name="Username"; Expression={$_.SamAccountName} }, Name, LastLogonDate, DistinguishedName
$daysOld = "-90"
$currentDate = get-date
$removeIfBefore = $currentDate.AddDays($daysOld)
$vpnuserstest = Get-ADGroupMember VPN_users -Recursive | select samaccountname | foreach ($_.samaccountname) {
Get-ADUser $_.samaccountname -Properties samaccountname, whenCreated |
Select-Object samaccountname,#{n='Days Since Created';e={($((Get-Date)) - $($_.WhenCreated)).Days}} |
Format-table -AutoSize}
Detailed Description:
I am taking the users in the group VPN_users and searching for their "samaccountname" and "whenCreated" properties. Then I would like to take today's date and go back 90 days. Anyone who's "whenCreated" date falls within that 90 day window, I want to add to a table so that I can export it later.
When I run the above code, I get everything listed as I would like, but it still includes everyone who's "whenCreated" property is above 90 days.
Sorry if the code looks "frankenstein'd" together....because it is. I took different aspects from different Google searches and threw them together.
Here's one way: Construct a timestamp-string and use with the -LDAPFilter parameter. Example:
$daysOld = 90
$timestampUTC = (Get-Date).AddDays(-$daysOld).ToUniversalTime()
$timestampString = "{0:yyyyMMddHHmmss.0Z}" -f $timestampUTC
Get-ADUser -Properties whenCreated -LDAPFilter "(whenCreated<=$timestampString)"
If you want to limit results to users that are a member of a particular group, you can update the LDAP query filter. Example:
$daysOld = 90
$timestampUTC = (Get-Date).AddDays(-$daysOld).ToUniversalTime()
$timestampString = "{0:yyyyMMddHHmmss.0Z}" -f $timestampUTC
Get-ADUser -Properties whenCreated -LDAPFilter "(&(whenCreated<=$timestampString)(memberOf=CN=Group Name,OU=Container,DC=fabrikam,DC=com))"
(Sorry if my English is bad, I'm a French guy).
I'm trying to automate some tasks on my AD and i was looking for a powershell commands which could list the users who didn't connect the last three months.
I tried using the lastlogontimestamp attribute but i can't make it work.
Here is what my command actually look like :
$date = new-object System.DateTime -ArgumentList #(2015,8,1,0,0,0)
Get-ADUser -Filter { -not (LastLogonTimeStamp -le "$date") }
Any ideas ?
The lastLogonTimestamp attribute is stored as a 64-bit integer representing a FILETIME timestamp.
You can convert your DateTime object to this format with the ToFileTime() method.
I would suggest using the Get-Date cmdlet rather than New-Object System.DateTime
# Current time -3 months:
$Threshold = (Get-Date).AddMonths(-3).ToFileTime()
# Retrieve the users
Get-ADUser -LDAPFilter "(&(lastlogontimestamp < $Threshold))"