Today I will show you how to build a PowerShell script that looks up and displays information about Active Directory users. Your helpdesk staff can use the script to retrieve information from Active Directory without having to know PowerShell. You can tailor the script specifically to your needs.

Mike Kanakos

Mike is a Windows IT pro located in the Research Triangle Park area of North Carolina with 13+ years of experience as an admin and 20 years in the field. He specializes in Active Directory, Azure AD, Group Policy, and automation via PowerShell. You can follow Mike's blog at networkadm.in or on Twitter at @MikeKanakos.

In my example, we're going to create a tool that displays the most common fields needed to help employees who are calling into the helpdesk for assistance and display that info in a simple, easy-to-read output. I am going to walk you through building this script piece by piece and then present the final solution at the end of this article.

My goal is make it simple to display all the relevant the Active Directory fields related to user account status, account expiration, password status, as well as when they last set their password and when it will expire. I would also like to know if the account is locked out. Finally, I also need to display the common employee info fields (name, address, department, manager, title, etc.). The tool also needs to be simple for my helpdesk staff to use since they sometimes deal with a large volume of calls.

Of course, you can just run Get-ADUser to retrieve information about Active Directory users. However, you usually can't expect helpdesk staff to be typing in super-long commands like the one below to get the info they need.

The block of code above produces the following output:

Looking up employee info with Get ADUser

Looking up employee info with Get ADUser

This syntax works fine and gets us most of what we need without a ton of work. Overall, this is close to what I am looking to achieve. We could stop right here and call it a day, and for many people this would a usable solution. However, it isn't the most elegant solution, and more importantly, the output above is missing the password-expiration date, and the manager field is not easily readable. I think we can do better.

I certainly wouldn't expect someone to type in all that data over and over. We're close, but we must make it simple to type. Also, when I look at these fields, I see two sets of data: employee information and account status information. But the fields are not organized in any way, and the output is just a long table.

Let's address the two problem fields first. The manager field is not formatted as I would prefer: I would like to see first name and last name. We can fix this by doing a lookup on the manager's name and returning the manager's SAMAccountName. I used SAMAccountName because the DisplayName is listed as Last name, First name. This is not what I wanted, but you may like this field better for your version of this script.

I am using Get-ADUser a second time to look up the SamAccountName of the manager and then I am saving that value to a variable named $Manager.

The password expiration is tricky because it's a special field that isn't easy to find if you don't know what you’re looking for and the value is not in a human-readable form by default. I'll need to make two changes to get the desired result. The first thing I need to do is add the field "msDS-UserPasswordExpiryTimeComputed" to my  original Get-ADuser query, and then I need to convert the data returned to a format we can make sense of.

Here I convert the msDs-UserPasswordExpiryTimeComputed value to a readable date value and save the output to a variable named $PasswordExpiry

Now that I have all the fields I need, I can work on breaking up the original output into two distinct groups (employee information and account status information), but using Select-Object to display the fields probably isn’t going to give me the desired result. I could feed that data from Get-ADUser into two separate arrays, and then I could display each array separately. Using arrays lets me rename fields in Active Directory like "given name" and "surname" to more commonly used names like FirstName and LastName. Let's see what those arrays look like.

The result is we have taken the information from our original lookup and have split the data into two smaller groups. Those groups now contain field names that are more user friendly as well. You could argue that this isn't necessary, and you would not be wrong.

The reason for doing this extra work is to get the output organized in the way I want it displayed with the field names I want. I could instead have run Get-ADuser twice in one script. The first Get-ADUser could have got just the account info fields, and then I could've run Get-ADuser again to lookup the Account status fields.

However, those two calls still would not convert the msDs-UserPasswordExpiryTimeComputed value to a readable date value, so I would still need to do more work afterwards. For me, arrays offer more flexibility with formatting and naming and allow me to add other fields that weren't available with the original Get-ADuser query.

Also, I believe that it's not enough just to build a tool that gives me the desired result. Instead, the tool should also be well documented, easy to follow, and built using best practices. Arrays are a better solution to the problem, and my code will be easier to understand.

Lastly, I'd like to remind you that the fields I chose may not be the ones you want to use. It's only a small amount of work to customize this as you wish. Let's see what the output of the two arrays looks like:

The output of the two arrays

The output of the two arrays

We have broken up the output into two smaller groups. I think that output is better organized and easier to read at a glance, which was my main concern when starting this project. The result is that helpdesk staff members will have an easier time finding the info they need.

I prefer to run my tools as functions. This means we need to name our function and include help files so people have something to reference when they have questions. The script below is formatted as a function, which means you'll have to load the function to run it. I'll assume you already know how to do that. I named my function Get-EmployeeInfo. The syntax is simple to type:

Get EmployeeInfo syntax

Get EmployeeInfo syntax

The result is that we have a tool that is easy to use, with a simple syntax that results in a customized output that is easy to read. I also created code that follows best practices, is succinct, portable, and well documented.

My hope is that you found this article insightful, and it helps you build your own functions using customized lookups. Please leave me some feedback in the comments section so I can continue to write useful articles. If there is something you would love to see me write about or if you have a specific question about this or any or my other articles, please feel free to leave me a note as well.

Join the 4sysops PowerShell group!

8+

Users who have LIKED this post:

  • avatar
  • avatar
  • avatar
Share
24 Comments
  1. Pat Richard 1 year ago

    One thing this doesn't account for is a user who has 'password never expires'. The [datetime]::FromFileTime code throws an error.

    1+

  2. Author
    Mike Kanakos 1 year ago

    Hi Pat,

    One thing this doesn't account for is a user who has 'password never expires'. The [datetime]::FromFileTime code throws an error.

    That a valid point and an oversight on my part when I was designing this script. Last month, I posted a password expiration reminder script and accounted for that scenario. We could take that portion of code and implement here very easily. The code to do that check would be something like this:

    Get-ADUser -filter {Enabled -eq $True -and PasswordNeverExpires -eq $False}

    I can go back and edit this script later today to account for your scenario. Thanks for pointing that out.

    2+

    • Pat Richard 1 year ago

      What I did was just throw the $PasswordExpiry line into a Try{} block, such as:

      try {$PasswordExpiry = [datetime]::FromFileTime($Employee.'msDS-UserPasswordExpiryTimeComputed')}
      catch{}

      And that seemed to work fine.

      I also changed it to be a single object for the output.

      2+

      Users who have LIKED this comment:

      • avatar
      • Author
        Mike Kanakos 1 year ago

        I think in hindsight it would have been smarter for me to check for a non-expiring password and alert the user doing the check to that condition.

        "Password never expires" is not really a problem per se, instead, the issue is that it causes an error in the original version script. It could be a valid config for certain accounts and, as such, probably should be surfaced to the person running the script in some way.

        1+

  3. PowerMe! 1 year ago

    Thanks Mike for summarizing this. I think I can use this to refine my user search PS scrapbook. Just to add I use my select parameters in an array that I call into the command as bellow.

    In fact I put all my select arrays to a file and call them in the commands.

    2+

    • Author
      Mike Kanakos 1 year ago

      Interesting idea. I never thought of doing that way. I'll have to try that out soon.

      1+

  4. Armando Hernandez Rodriguez 1 year ago

    Hello I have this error and I know now why?

    Get-ADUser : Cannot validate argument on parameter 'Identity'. The argument is null or an element of the argument collection contains a null value.
    At C:\Get-EmployeeInfo.ps1:63 char:29
    + $Manager = ((Get-ADUser $Employee.manager).samaccountname)
    + ~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidData: (:) [Get-ADUser], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.ActiveDirectory.Management.Commands.GetADUser

     

    1+

    • Author
      Mike Kanakos 1 year ago

      Hello Armando,

      Get-ADUser : Cannot validate argument on parameter 'Identity'. The argument is null or an element of the argument collection contains a null value.

      The error message means that you did not enter a username to lookup. Why don't you paste your syntax here and I'll point you in the right direction.

      A valid syntax would be:

      Get-EmployeeInfo username

      replace username with the actual username you want to look up.

       

      2+

      Users who have LIKED this comment:

      • avatar
      • O'Neil Wilson 1 year ago

        Getting my feet wet with PowerShell and this is a great start.  Keep it coming..  Thanks Mike.

        2+

        Users who have LIKED this comment:

        • avatar
        • Author
          Mike Kanakos 1 year ago

          Thanks O'neil! Glad I can be of some value to you. I 've got plenty more to share!

          2+

          Users who have LIKED this comment:

          • avatar
          • O'Neil Wilson 1 year ago

            Send it all over.  I'm willing to learn from the pros...

            1+

  5. Armando Hernandez Rodriguez 1 year ago

    Hi Mike, i use this sintax: Get-EmployeeInfo username and replace username for myuser, for example:

    Get-EmployeeInfo armando and I get:

    PS C:> Get-EmployeeInfo armando
    Get-ADUser : Cannot validate argument on parameter 'Identity'. The argument is null or an element of the argument collection contains a null value.
    At C:\Users\adm_es00594132\Documents\Get-EmployeeInfo.ps1:61 char:29
    + $Manager = ((Get-ADUser $Employee.manager).samaccountname)
    + ~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidData: (:) [Get-ADUser], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.ActiveDirectory.Management.Commands.GetADUser

    Where i need to put or define the username??

    1+

  6. Armando Hernandez Rodriguez 1 year ago

    Hi Mike, in think i got it, the problem is the username, my username is es00594132,

    why I can´t put es00594132 in a variable? for example:

    PS C:\> $username = es00594132
    es00594132 : The term 'es00594132' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that
    the path is correct and try again.
    At line:1 char:13
    + $username = es00594132
    + ~~~~~~~~~~
    + CategoryInfo : ObjectNotFound: (es00594132:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

    Thank you very much.

    1+

    • Author
      Mike Kanakos 1 year ago

      Hi Armando,

      I think you already figured out that 'Armando' is not your username, so Get-ADUser throws an error.

      Powershell thinks you are typing a string of text but text need to be in enclosed with single or double quotes for it to be recognized as a string value. For example, I get the same error as you if I type the same thing:

      The bold text tells me Powershell thinks the data is a string value, so I should have used quotes.

      the value is accepted without issue.

      Let's go back to the first issue. Please don't take this the wrong way, if you know this already, I apologize... but this is a function, not a script. you can't just run the code and make it work. You have to load it into memory first.

      Did you load the function? After loading the function (called dot sourcing), then you can run the function.

      Please write back and I will attempt to help more or send me an email at mkanakos@gmail.com and I would be glad to try and help.

      1+

  7. Pat Richard 1 year ago

    Here's a tweaked version that deals with 'never expire', as well as outputting a single object, and incorporates support for pipeline input. Also, the URL in your comment block is incorrect.

    1+

  8. Moin Ahmed 3 months ago

    HELP!!

    I am pulling my hair and nothing seems to be helpful. I am trying to get below information for all Active users in AD, can you PLEASE help??

    SamAccountName, AccountExpirationDate, Department, Givenname, Surname, EmailAddress, title, Manager, EmployeeType, LastLogonDate

     

    0

    • Author
      Mike Kanakos 3 months ago

      Hi Moin,

       

      Are u asking for a simple output of all employees and the output should have all the fields you mentioned listed?

      0

      • Moin Ahmed 3 months ago

        Hi Mike,

        Yes, simple output exported to .txt or .csv format with all the fields in it.

        0

  9. Author
    Mike Kanakos 3 months ago

    Here you go!

    another way of doing the same thing that is a little easier to read would

    2+

    Users who have LIKED this comment:

    • avatar
    • Moin Ahmed 3 months ago

      Tried first one, works great! however, give below error at finish;

      Get-Aduser : Not a valid Win32 FileTime.
      Parameter name: fileTime
      At line:3 char:1
      + Get-Aduser -filter "enabled -eq '$true'" -property $props | Select-Ob ...
      + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          + CategoryInfo          : InvalidArgument: (:) [Get-ADUser], ArgumentOutOfRangeException
          + FullyQualifiedErrorId : Not a valid Win32 FileTime.
      Parameter name: fileTime,Microsoft.ActiveDirectory.Management.Commands.GetADUser

      0

      • Author
        Mike Kanakos 3 months ago

        Moin,

        I ran both without issue. I did see that there were some backslash's missing from the Export-CSV cmdlet. I fixed that above. Re-copy code and re-test. 

        1+

        • Moin Ahmed 3 months ago

          tried again, worked! Thank you so much 

          Can we also get below information in addition?

           

          Date of user account creation

          Is the user account active or inactive

          Password expiry date

          0

          • Moin Ahmed 3 months ago

            Hi Mike, 

            I was able to figure out about account creation date.

            Only thing now I am pending is Password expiry Date, can you please help me incorporate this with the existing script?

            0

  10. Moin Ahmed 3 months ago

    Hi Mike,

    I figured out about the account creation date and the script you provided earlier gives only active accounts.

    All now I need is to get Password Expiry date incorporated with the same script. 

    If you can please assist.

    0

Leave a reply

Your email address will not be published. Required fields are marked *

*

© 4sysops 2006 - 2019

CONTACT US

Please ask IT administration questions in the forums. Any other messages are welcome.

Sending

Log in with your credentials

or    

Forgot your details?

Create Account