Skip to main content

Changing the Account Expiration Date on all Users with PowerShell

This is a question that I took from PowerShell.com and presented to my PowerShell class.  My intent was to demonstration some research methods using MSDN.  In truth, I had no idea how complicated that this could be.

The user needed to advance all user account expiration dates by 90 days from the current date. 

image

Take a look at the AccountExpires property.  I did a little internet research on the properties of an Active Directory User Object. Here is what I found out about the AccountExpires attribute.  It is the number of 100-nanosecond intervals from January 1, 1601.  OK, who thinks of this stuff?  I was hoping this would be a System.DateTime object, but we are not so lucky.  So, I set off to make it one.

Another issue is once I have it in a DateTime object, how do I change it back into this 100-nanosecond format? Doing a little research of the DateTime object on MSDN gave me the class information for this object.   Clicking on the Ticks property gave me the answer that I was hoping for.

The value of this property represents the number of 100-nanosecond intervals that have elapsed since 12:00:00 midnight, January 1, 0001, which represents DateTime.MinValue. It does not include the number of ticks that are attributable to leap seconds.

I’m assuming that the year 0001 is a typo or the 1601 from the other documentation is a typo.  With this information in hand, off to coding I go.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

ForEach ($User in (Get-ADUser -filter * -Properties AccountExpires))

{

    # Retrive the date that a user account will Expire as a DateTime object.

    $User |

    Select-Object -ExpandProperty AccountExpires |

    ForEach-Object {

 

        # If the account is set to never expire, then do not change the date.

        If (([double]$User.AccountExpires -ne 9223372036854775807) –and

            ($User.AccountExpires -gt 0))

            {

                $Date = [DateTime]$_

                Write-output $Date.AddYears(1600).ToLocalTime()

               

                # Set the expiration date for 90 days into the future

                $User |

                Set-ADUser -AccountExpirationDate ((Get-Date).AddDays(90)).Ticks   

            }

        }  # End ForEachObject Loop

} # End ForEach ($User in (Get-ADUser -filter * -Properties AccountExpires))

Lines 1 – 20 contain a ForEach loop that pulls one user object at a time and stores the object in the variable $User.

Line 4 starts a PowerShell pipeline that runs all the way to line 19.  Line 4 Pass the $User object into the pipeline.

Line 5 Extracts out the AccountExpires property value.

Line 6 starts a ForEach loop that runs until line 19.

Lines 9 and 10 makes sure that we do not touch any user object that is either the built in administrator or has an account that is set to never expire.  The value 9223372036854775807 is the content for “Account Never Expires”. Current Windows 8 clients have a maximum date of of 3155378975999999999, or December 31, 9999 12:00:00 AM.  I guess this will be the new Mayan end of the world date for a future generation.

Line 12 utilizes the .NET class [DateTime] to great a DateTime object out of the AccountExpires information.  Fortunately, it accepts the 100-nanosecond format.

Line 13 can be removed.  It will display what the accounts are being set to in case you are interested.

Line 16 pipes the current user object to the pipeline and sends it to Set-ADUser.

Line 17 sets the AccountExpires property to 90 days in the future using the DateTime objects AddDays() method and then extracting the number of Ticks this new date represents.

Comments

Popular posts from this blog

Adding a Comment to a GPO with PowerShell

As I'm writing this article, I'm also writing a customization for a PowerShell course I'm teaching next week in Phoenix.  This customization deals with Group Policy and PowerShell.  For those of you who attend my classes may already know this, but I sit their and try to ask the questions to myself that others may ask as I present the material.  I finished up my customization a few hours ago and then I realized that I did not add in how to put a comment on a GPO.  This is a feature that many Group Policy Administrators may not be aware of. This past summer I attended a presentation at TechEd on Group Policy.  One organization in the crowd had over 5,000 Group Policies.  In an environment like that, the comment section can be priceless.  I always like to write in the comment section why I created the policy so I know its purpose next week after I've completed 50 other tasks and can't remember what I did 5 minutes ago. In the Group Policy module for PowerShell V3, th

Return duplicate values from a collection with PowerShell

If you have a collection of objects and you want to remove any duplicate items, it is fairly simple. # Create a collection with duplicate values $Set1 = 1 , 1 , 2 , 2 , 3 , 4 , 5 , 6 , 7 , 1 , 2   # Remove the duplicate values. $Set1 | Select-Object -Unique 1 2 3 4 5 6 7 What if you want only the duplicate values and nothing else? # Create a collection with duplicate values $Set1 = 1 , 1 , 2 , 2 , 3 , 4 , 5 , 6 , 7 , 1 , 2   #Create a second collection with duplicate values removed. $Set2 = $Set1 | Select-Object -Unique   # Return only the duplicate values. ( Compare-Object -ReferenceObject $Set2 -DifferenceObject $Set1 ) . InputObject | Select-Object – Unique 1 2 This works with objects as well as numbers.  The first command creates a collection with 2 duplicates of both 1 and 2.   The second command creates another collection with the duplicates filtered out.  The Compare-Object cmdlet will first find items that are diffe

How to list all the AD LDS instances on a server

AD LDS allows you to provide directory services to applications that are free of the confines of Active Directory.  To list all the AD LDS instances on a server, follow this procedure: Log into the server in question Open a command prompt. Type dsdbutil and press Enter Type List Instances and press Enter . You will receive a list of the instance name, both the LDAP and SSL port numbers, the location of the database, and its status.