Create Active Directory Logon Reports with PowerShell. As we know, auditing in an Active Directory (AD) environment is crucial for security. It is vital to find out what the user has done and which system they logged in to. Therefore, one of the essential tasks most administrators are dealing with nowadays is finding where a user has logged on. This article will walk through a step-by-step guide to learn how to utilize the built in Event Viewer on domain controllers (DC), find where a user has logged on, and generate a comprehensive logon report using PowerShell.

So, let’s continue with article Create Active Directory Logon Reports with PowerShell. 

Create Active Directory Logon Reports

Create Active Directory Logon Reports with PowerShell


Since we will use the Event Viewer and monitor the events for days, we need to ensure that the size of our event logs is sufficient. Although, we may have already enabled these settings, we will review them again if other people need to increase the event log size.

If we have not changed any configuration before, the default size setting of our event log should be around 64 MB. However, the increase in size may need to happen, primarily if we deal with multiple DCs in our environment. For example, if we want to keep track of audit logons for several days, we will need far more space in the event viewer.

Creating a GPO

1. As the first step in preparing the environment, we will create a Group Policy Object (GPO) that contains the Event Log Size settings. Let us open the Group Policy Management Console (GPMC), create a GPO. To open the console, search for Group Policy or type gpmc.msc in the Run (Ctrl+R) window.

2. In the navigation panel, expand Forest: ForestName, expand Domains, expand DomainName, and then click Group Policy Objects. Next, click Action, and then click New.

3. Locate the path below inside the newly created GPO:

4. Change the Security event size based on our environments and requirements. In addition, if there are no concerns regarding disk space and performance, it is possible to configure settings at a maximum level of 4 GB.

5. The following step is optional if domain controllers do not have firewall settings. However, we must be able to query event logs from multiple domain controllers and possibly multiple sites. As a result, it is prudent to ensure that Remote Event Log Monitoring is enabled via the firewall.

Unfortunately, it is only possible to cover some details about configuring firewall settings. Still, the image below will show all the settings needed to enable Remote Event Log Monitoring on our domain controllers.

6. Now, connect the GPO we just created to the Domain Controllers OU and wait for some events to populate. The event depends on the environment, and we can start querying audits immediately or wait a couple of days. Now that we have correctly set up our logging, we can move to run the PowerShell script, which will be discussed in the next section of the article.

Up next with Create Active Directory Logon Reports with PowerShell is the main part of the article title. Please read on. 

Improve your Active Directory Security & Azure AD with Logon Reports

Try us out for Free, Access to all features. – 200+ AD Report templates Available. Easily customise your own AD reports.

Create AD Logon Reports with PowerShell

To begin, download and copy the script to a directory or folder. Alternatively, if you have git installed, we may run the following command.

					git clone https://github.com/InfraSOS/Get-UserLastLogon.git

The script uses the ActiveDirectory module, but we will not need to install it manually as the script checks for the module in our system. Once downloaded, launch PowerShell and navigate to the downloaded script’s folder or drive.

If we edit the downloaded file, we will see four main functions. These four main functions are Param, Begin, Process, and End.

Explaining the PowerShell Script

The Param section contains the parameters required to run the script. As shown in the code block below, we need three parameters for the script to work. We will explain these parameters later on.

					param (
    [Parameter(Mandatory = $true)]
    [Parameter(Mandatory = $false)]
    [Array]$Server = @((Get-ADDomainController -Filter *).Name) ,
    [Parameter(Mandatory = $false)]
    [Array]$Days = 90

As a best practice, variables and general information be placed in the Begin section to avoid overcrowding the main part of the script.

					[Array]$Table         = $null
    $DomainControllers    = $Server
    $AllDomainControllers = @((Get-ADDomainController -Filter *).Name)
    [Array]$ExclusionList = @($User,'krbtgt')
    $DCCount              = $DomainControllers.Count
    $UPN                  = ((get-addomain).DNSRoot).toUpper()
    $DateFilter           = "-"+$days
    $DateThen             = (((Get-Date).AddDays($DateFilter)).ToString("yyyy-MM-dd"))+"T20:30:00.000Z"
    $DateNow              = (Get-Date -Format yyyy-MM-dd)+"T20:30:00.999Z"
    $ForestRoot           = ((Get-ADForest).rootDomain).toUpper()
    $Counter              = 0

The Begin script also formulates a primary filter for querying the event log. Then, the script will send this filter to each DC to gather information. As we can see in these lines, there are some previously discussed variables, such as $UPN and $User.

					    [xml]$FilterXML = @"

	and TimeCreated[@SystemTime>='$DateThen' 
	and @SystemTime<='$DateNow']]] 
	and*[EventData[Data[@Name='TargetUserName'] and (Data='$User@$UPN')]]


The Process section is the essential function, where the script queries for the data to generate a report. The code block below is the foreach command which executes every time we log in to another DC to query data.

					Foreach($DCName in $DomainControllers){...}

We first gather events on our first DC. Then, the next step is to extract valuable information from each event and save it to an object before moving on to the next event. Once done with the first DC, the script moves to another DC and repeats the process.

Lastly, the End section will show the final generated report.

        $Table = $Table | Where-Object {($_.Location -notin $AllDomainControllers) -and ($_.Location -ne $ForestRoot) -and ($_.Location -notin $ExclusionList)} 
        $Table | Sort Time | FT Time,User,Location,Domain,DC -AutoSize 

Running the PowerShell Script

To start, open PowerShell and type the following command below to load the cmdlet into memory.

					. .\Get-UserLastLogon.ps1

When we press the Enter key, there might be an error indicating that the script’s execution is disabled due to the PowerShell execution policy, or there will be no error. In the event of an error, open a PowerShell console with administrative privileges, type the following commands below to allow script execution, and then repeat the previous command.

					Set-ExecutionPolicy RemoteSigned
. .\Get-UserLastLogon.ps1

Now that the script is fully loaded let us consider it an example to find out which workstations the user logged on to during the past 15 days. First, type the username with the –User parameter and the time frame with the –Days parameter and hit Enter

					Get-UserLastLogon -User marion -Days 15

As you may recall, we have another parameter called the -Server parameter. If we do not supply a value to the -Server parameter, we will consider all domain controllers to fill this parameter. Now, if we have a specific DC in mind to target for a search query, we can specify it as a value of the -Server parameter.

After running, the script will display a progress bar informing us of its status and how long it will take to complete. Now we can see a report generated after running the script. The report tells us which workstations the user has logged on to during the last 15 days.

					Time                  User   Location      Domain  DC
----                  ----   --------      ------  --
11/19/2022 7:31:11 AM marion DESKTOP-IGK57 abc.com MARION-DC01


Understanding the PowerShell Script

When we run the script, in the beginning, it checks whether the user account exists or not. Therefore, it is evident that if the entered username or ID does not exist, we do not need to run the remaining scripts.

In the following step, we compute the required variables and send them to the DC, along with the filter needed to query the events for our chosen user. Finally, the script sends a request to the first domain controller in the list, and the queried events related to the selected user are saved in a variable.

The list of saved events that the script will start, and the subsequent steps will involve gathering valuable data from the events. Finally, the script assigns the extracted data into a variable, such as the domain, DC name, login time, and login workstation.

In the end, the script runs through the following DC and repeats the process.

The script will display a list of computers to us once it contacts the final DC and gathers its information.

					Time                  User   Location      Domain  DC
----                  ----   --------      ------  --
11/19/2022 7:31:11 AM marion DESKTOP-IGK57 abc.com MARION-DC01


Thank you for reading Create Active Directory Logon Reports with PowerShell. We shall conclude.

Create Active Directory Logon Reports Conclusion

In this guide, we learned how to use the essential event viewer and combine it with PowerShell scripts to find a list of workstations where a user has logged on. The script queries all DCs in a domain, finds the results, and parses them into a readable format that we can export as a report. Remember to run to check for the prerequisites before running the provided script.


Try InfraSOS for FREE

Invite your team and explore InfraSOS features for free

Marion Mendoza

Marion Mendoza

Windows Server and VMware SME. Powershell Guru. Currently working with Fortune 500 companies responsible for participating in 3rd level systems support across the enterprise. Acting as a Windows Server engineer and VMware Specialist.

Leave a comment

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