简体   繁体   中英

Powershell script to disable expired users within an OU

I have been trying to create a Powershell script to Disable accounts which have expired (AccountExpires).

Import-Module ActiveDirectory
Get-ADUser -filter * -SearchBase "OU Goes Here" -Properties AccountExpires, Enabled | Where-Object {$_.Enabled -eq $True} | ForEach {
        If (($_.accountExpires -gt [DateTime]::MaxValue.Ticks) -or ($_.accountExpires -eq 0)) {$ActExp = "Never"}
        Else {$ActExp = [datetime]::FromFileTime($_.accountexpires)}
        "$_.Name,$ActExp"
    }
Select-Object name,@{Name="AccountExpires";Expression={[datetime]::FromFileTime($_.properties."AccountExpires")}}

This generates a list of accounts that have an expiry date, but I don't seem to be able to generate a list of accounts that have already expired, and then how can I disable them all in one go?

Thanks

While you can do Get-ADUser -Filter * and then filter out the accounts on the client side, this transfers all user objects from the AD through the wire every time, but you immediately discard 99% of them. When there are many user objects in the directory, that's is a bit of a waste.

I would prefer letting the server side filter the objects, which can be achieved with an LDAP filter. The filter for "all expired accounts that are enabled" would look like this:

(&
    (AccountExpires>=1)
    (AccountExpires<=637154628247641991)
    (!(UserAccountControl:1.2.840.113556.1.4.803:=2))
)

ie AccountExpires>=1 AND AccountExpires<={current date} AND NOT Account is disabled . The last part looks somewhat convoluted, but it's not too hard:

In PowerShell we can set up and use this filter like follows. Disabling the affected accounts then is only a matter of piping them into Disable-ADAccount

$filterString = "
(&
    (AccountExpires>=1)
    (AccountExpires<=$([DateTime]::Now.ToFileTime()))
    (!(UserAccountControl:1.2.840.113556.1.4.803:=2))
)" -replace "`r`n"

Get-ADUser -LDAPFilter $filterString | Disable-ADAccount -WhatIf

The -replace "`r`n" is only necessary because Get-ADUser is picky about newlines in the LDAP filter string.

It seems like you want to determine the account expiration status of a subset of users. Then you want to disable the users who have already expired. The code below should help get you closer to your goal.

$CurrentTime = (Get-Date).ToFileTime()
$CalculatedProperty = @{
    Label='AccountExpires'
    Expression = { if (!$_.AccountExpires -or $_.AccountExpires -ge [datetime]::MaxValue.ToFileTime()) {
                       "Never"
                   } 
                   elseif ($_.AccountExpires -le $CurrentTime) {
                       "Expired"
                   }
                   else { 
                       [datetime]::FromFileTime($_.AccountExpires)
                   }
                 }
}

$users = Get-ADUser -filter "Enabled -eq '$true'" -SearchBase "OU Goes Here" -Properties AccountExpires |
    Select-Object SamAccountName,Name,$CalculatedProperty
$users | Where AccountExpires -eq 'Expired' | Foreach-Object {
    Disable-ADAccount -Identity $_.SamAccountName -WhatIf
}

$users will contain all of the user objects and the account expiration status. You will need to remove the -WhatIf parameter if you are happy with the results. If you run $users | Where AccountExpires -eq 'Expired' $users | Where AccountExpires -eq 'Expired' , you will see what accounts would be targeted for disabling.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM