Subscribe via Email

Subscribe via RSS


Recent Posts

Creative Commons Attribution 4.0 International License
© Rakhesh Sasidharan

Find the computer from where an AD account is locked out

I want to find out where from a user account is locked out in my domain.

The manual way to do this would be to open up Event Viewer, scan the event logs on the DC for event ID 4740, open it up and see the message to identify the machine from where this account was locked out. But using PowerShell we can obviously automate this way easily!

First things first: how to scan the event logs using PowerShell? You can use either of Get-EventLog or Get-WinEvent. The former only works on the classic event logs while the latter works on both the classic and newer event logs such as those found in Windows Vista and later. I find the latter faster too, so let’s use that. Here’s me running that cmdlet to filter the security logs for event ID 4740 on a remote DC:

There’s only one event here so the details of that are returned. It gives us all the info we need at a glance: user name “User01” is locked thanks to a bad password attempt from the computer “MANGO”.


Now let’s go about making this prettier and better.

In the code above I am specifying the domain controller to query. That’s only helpful if I have an idea of the machine or site the user is trying to login to, and so know the domain controller responsible for that site. A better approach would be to query the domain controller with the PDC Emulator FSMO role for event ID 4740. This DC is the one that eventually processes the account lockout requests for all accounts in the domain.

The cmdlet Get-ADDomainContoller gives you the domain controller of the site you are in. Adding the switch -Filter * gives you all the domain controllers in the domain. And piping this through a where-object to filter out the domain controller with the “PDC Emulator” FSMO role gives you the domain controller we are interested in. Like thus:

The snippet above returns an object for the DC with the PDC Emulator role, to extract just the name do thus:

Next, let’s go about presenting the output above in a tidier format.

One thing to note is that all the info we want is in a property called Message.

So one option would be to do some fancy filtering using foreach-object like thus:

This will list out the multiple lockout entries with the timestamp on top in red.

A better option, however, is to use the Properties property, which is an array containing exactly the info we want as values.

Format-Table is your friend here:

A one line code that’s way better than opening Event Viewer and filtering through the logs manually.

And if you want to filter by the locked out status of a specific $user, pipe the output through a where-object like thus:

Get a list of machine names and logged on or active user(s)

The Win32_LoggedOnUser class gives a list of logged on users to a computer. It isn’t just users logged on interactively to the console or Remote Desktop (which is a good thing) but even users connected remotely via shared folders and such (not a good thing).

But just for the curious (and since I fiddled with it today) here’s how you can format the output of this class properly.

You can use PowerShell to get instances of this class via the Get-WMIObject cmdlet thus:

The output has a lot of material, so best to filter by the Antecedent property.

Instead of Format-Table you may use Select-Object or anything else you fancy.

To query remote computers using the -ComputerName switch.

The output isn’t precise. You get a list of local accounts as well, and there are repeat entries.

In my case I want to limit to the domain accounts. Also I want to skip accounts starting and ending with the “x” character (as these are my admin accounts) and any accounts entering with a “$” character (as these are machine accounts). And I want to eliminate the duplicates. So here’s what I did:

Once again, the beauty of PowerShell is that you can glue things together. So, for instance, if I want to get a list of machines in my domain along with the currently logged in users, I can do that.

To get a list of machines in a particular OU I use the following (this requires the ActiveDirectory module to be imported first!):

I already have the code for getting the logged in user on a machine, so all I need to do is pipe the output of the Get-ADComputer to Format-Table and tell it to populate the user column dynamically. Like thus:

The code within the Expression block is similar to the code for querying a single machine, except that I replace the machine name with $_.Name.

The output is a list of machines with the logged in user(s). If there are no logged in users that field is empty {} else it’s a single user name or a list of user names.

Of course, the Win32_LoggedOnUser class isn’t useful if users access each other’s machines via shared folders and such; but in that case it’s just a matter of replacing the Expression block above with code that gives more focussed results. Two great posts on how to list logged in users on a machine are this and this.

I wanted to expand the code above to also include IP addresses too. A PowerShell one-liner to get IP address from a name is the following:

To limit the output to just the IP address do the following:

And to restrict to just IPv4 addresses add the following:

Going by these it’s pretty obvious what we have to do to add an IP address column: