question

MikeLehmann-8939 avatar image
0 Votes"
MikeLehmann-8939 asked RichMatheisen-8856 answered

comparing dates with Powershell

I need to delete AD users based on expiry date greater than 30 days

I can pull the users that are expired and their expiry date easy enough:

 $Today = (Get-Date).ToString("dd-MM-yyyy")
 $DeleteDate = (Get-Date $date).AddDays(-30).ToString("yyyyMMdd")
    
 Get-ADUser -Filter 'enabled -eq $false' -Properties AccountExpirationDate | Select sAMAccountName, AccountExpirationDate


But I want to delete only those where the AccountExpirationDate is > 30 days.

Could someone pls help me with an expression to do this?

note my PS skill is rudimentary so simpler is better

Thanks



windows-server-powershell
· 3
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Inactive, Enabled and Expired are not the same! Just because an account is inactive does mean it's disabled or expired!

Based on your description, you're looking for inactive accounts. I think this reflects what you're looking for:

 Search-ADAccount -AccountInactive -TimeSpan -30:00:00:00 -UsersOnly


0 Votes 0 ·

Thanks
They aren't the same, I need to use expiry date and not 'Accountinactive' which is effectively the last login attribute in AD. using this isn't reliable as not all users connect to AD regularly to update the LL timestamp
We have a script from HR which sets the expiry date for user as they are offboarded. I need to delete them 30 days after the date the account is expired

0 Votes 0 ·

Sorry for the misunderstanding. Try this, then:

 $CutoffDate = (get-date).AddDays(-30).Date
 Search-ADAccount -AccountExpired -UsersOnly |
     Where-Object { ($_.AccountExpirationDate).Date -lt $CutoffDate}
1 Vote 1 ·
AndreasBaumgarten avatar image
0 Votes"
AndreasBaumgarten answered

Maybe this helps (not tested):

 # Get Account Expiration Date
 $AccountExpirationDate = Get-ADUser -Filter 'enabled -eq $false' -Properties AccountExpirationDate | Select AccountExpirationDate
    
 # This is just for testing
 #$AccountExpirationDate = (Get-Date).AddDays(-45)
    
 # Create a Delete Date
 $DeleteDate = (Get-Date).AddDays(-30)
 # Compare Account Expiration Date with Delete Date
 if ($AccountExpirationDate -lt $DeleteDate)
     {Write-Output "Expiration Date is older than 30 Days"
     # Add  your code here
     }
 else {Write-Output "Expiration Date is not older than 30 Days"
     # Add your code here
     }



(If the reply was helpful please don't forget to upvote and/or accept as answer, thank you)

Regards
Andreas Baumgarten

5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

MikeLehmann-8939 avatar image
0 Votes"
MikeLehmann-8939 answered

Thanks the above gives an error:

Cannot compare "@{sAMAccountName=xx; AccountExpirationDate=28/11/2020 12:00:00 AM}" to "20201108" because the objects are not the same type or the object "@{sAMAccountName=xxx;

I tried converting the date to string like this
$DeleteDate = (Get-Date).AddDays(-30).ToString("yyyyMMdd")

but same error

5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

IanXue-MSFT avatar image
1 Vote"
IanXue-MSFT answered MikeLehmann-8939 commented

Hi,

The above script gives the error because $AccountExpirationDate is an array of type ADUser. To expand the AccountExpirationDate property you can add the parameter -ExpandProperty. Or you could try the following script

  $date = Get-Date
  $deletedate = $date.AddDays(-30)
  Get-ADUser -Filter 'enabled -eq $false' -Properties AccountExpirationDate -SearchBase "OU=test2,DC=contoso,DC=com" | 
  Where-Object{ $_.AccountExpirationDate -and ($_.AccountExpirationDate -lt $deletedate)} | Select-Object sAMAccountName, AccountExpirationDate

Best Regards,
Ian Xue
============================================
If the Answer is helpful, please click "Accept Answer" and upvote it.
Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

· 3
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Thanks you Ian this works

0 Votes 0 ·

Keep in mind that you're not comparing just a calendar date here, you're comparing date and time. If you run the script at, say, 9AM and an account had an expiration set for 10AM it won't be detected until the next day. I don't know if that's a problem for you or your HR people but it's something to keep in mind. That's why the code I suggested uses only the date and ignores the time.

1 Vote 1 ·

Understood, this is an issue with the existing script as it does not set a time, only a date so AD treats the actual expiry as next occurrence of 00:00 on the expiry date.

This in itself is an issue as the account would not actually become expired until midnight on the staff last day so there is a 7 hour gap between 5pm when user walks out for the last time and midnight when his account actually expires. We also have staff all over the world in different TZ so this isnt really working well as is but that's a different issue

0 Votes 0 ·
MikeLehmann-8939 avatar image
0 Votes"
MikeLehmann-8939 answered IanXue-MSFT edited

Sorry, I'm back..

I need to fit this into an existing script that has a 'If ($Null -ne $DisabledUsers)' loop and I'm having trouble getting the delete part to work. Is there a way to do this as a one liner like this simply by adding a pipe with Remove-ADuser command?

Remove-ADuser seems to work when piped onto a Search-ADAccount cmd but not Get-ADuser

For instance:

this works, and deletes the found users (but uses the wrong criteria I want)

 Search-ADAccount -SearchBase $SearchBase -AccountInactive -UsersOnly -TimeSpan 30.00:00:00 | Where-Object {$_.enabled -eq $false} | Remove-ADUser

This does not work and gives an error when Remove-ADuser is added at the end

 Get-ADUser -Filter 'enabled -eq $false' -Properties AccountExpirationDate -SearchBase $SearchBase | 
       Where-Object{ $_.AccountExpirationDate -and ($_.AccountExpirationDate -lt $deletedate)} | Select-Object sAMAccountName, AccountExpirationDate | Remove-ADuser



This is the bit of script I need to change, effectively I need to make it delete users based on expiry date rather than last login date

 $DisabledUsers = Search-ADAccount -SearchBase $SearchBase -AccountInactive -UsersOnly -TimeSpan 30.00:00:00 | Where-Object {$_.enabled -eq $false} | Select SAMAccountName
    
         If ($Null -ne $DisabledUsers) {   
                         
            Search-ADAccount -SearchBase  $SearchBase -AccountInactive -UsersOnly -TimeSpan 30.00:00:00 | Where-Object {$_.enabled -eq $false} | Remove-ADUser -Confirm:$False


Search and Get seem to return the SAMaccountname in a different format

Sorry If this is dumb questions, I am not a scripter

· 1
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

The input of Remove-ADUser should be type Microsoft.ActiveDirectory.Management.ADUser, but the output of Select-Object is of
type Selected.Microsoft.ActiveDirectory.Management.ADUser. If you want to remove the AD user, there's no need to select properties.

 Get-ADUser -Filter 'enabled -eq $false' -Properties AccountExpirationDate -SearchBase $SearchBase | 
        Where-Object{ $_.AccountExpirationDate -and ($_.AccountExpirationDate -lt $deletedate)} | Remove-ADuser
0 Votes 0 ·
RichMatheisen-8856 avatar image
0 Votes"
RichMatheisen-8856 answered

I tried to post this a a comment but it won't let me! So here's an answer that's really just a comment!

IanXue-MSFT has given you a way to fix your problem -- by piping the expected object type to the Remove-ADUser. However, you should also understand that you can use Select-Object -- but you have to provide a property in the resulting object named "Identity". You can check the help for the Remove-ADUser to see that you can pipe that property name and provide a sAMAccount as its value. To do that you'd use a calculated property:

 Select-Object @{name='Identity';expression={$_.sAMAccountName}}

As IanXue-MSFT pointed out, you don't need the Select-Object in this case. Also, note that the Remove-ADUser will, by default, prompt you for permission before it removes the account. See the Notes section of cmdlet's help:

"By default, this cmdlet prompts for confirmation as it is defined with High impact and the default value of the $ConfirmPreference variable is High. To bypass prompting for confirmation before removal, you can specify -Confirm:$False when using this cmdlet."

5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.