As an IT admin, have you ever had a time when you needed a record of a particular user's login and logoff history?

There have probably been cases when you needed to track down a potential security breach or perhaps you had managers come to you because they suspected employees weren't working quite as hard as they should be. In any case, it was important that you figure out the amount of time the users logged onto a computer interactively in your Active Directory domain.

Being the excellent administrator you are, you might have gotten on Google and tried to figure this out; if so, you'd soon find that it's possible to get Windows to write events to the Security event log after a user logs on and logs off. "Great," you think. "All I need to do now is to grab those two events and figure out the difference to get the total session time." After digging a little deeper though, you'd soon realize that it's not quite that easy. It's possible for a session to be more than a simple user logon and logoff. What if the computer crashes? What if the user decides just to pull the plug? What if they're using Remote Desktop Protocol (RDP) to log into a server? These different scenarios may come into play, and you may need to account for them.

Tracking the past and present user session times accurately across multiple computers requires a few steps to make this happen.

  1. You must "turn on" the ability for the computers to begin logging this activity. You can do this through Active Directory auditing. You must enable and the appropriate audit policies and target them to the computers on which you'd like to track users.
  2. You must figure out which events correlate to the starting and stopping points for a user session. A user logon would be a good starting point, for example, and a computer shutdown would be a good stopping point, but there are many other combinations as well.
  3. You must figure out how to correlate a single session stop and an end event with a common identifier. You'll see that this is possible with a logon ID and a little bit of ingenuity to match up the others.
  4. You must have a method to query the event logs from all targeted computers to find all relevant events.
  5. You must be able to correlate a start session event and a stop session event, and finally take the difference between those to come up with the total time a user interactively logged in to a computer.

Enabling Active Directory auditing policies ^

The first task is to ensure your computers are generating the necessary events in their event logs. To do this, you'll need to enable three advanced AD audit policies: Audit Logoff, Audit Logon, and Audit Other Logon/Logoff Events. Combined, these three policies get you all of the typical logon and logoff events. In addition, the policies also get the workstation lock/unlock events, and even RDP connect/disconnects. This ensures we get all of the session start/stop events.

Enabling AD advanced auditing policies

Enabling AD advanced auditing policies

As you can see in the screenshot, I chose to create a Group Policy Object (GPO) called User Session History and set all to Success.

Defining session start and stop events ^

Once each computer picks up this GPO, it will begin generating a few different event IDs you should be concerned about. It's important to match up each of these events to a start or stop event. After defining these, you are then able to match up each one in the event logs and calculate the difference in time to come to an accurate total session time.

EventEvent IDEvent LogSession Start/Stop
RDP Session Reconnect4778SecurityStart
RDP Session Disconnect4779SecurityStop

All of these events are self-explanatory except for one that I should point out. You'll notice that I have a startup event with event ID 6005 labeled as a stop session event. Why? Because we'll use this event ID when the computer suddenly gets shut off without warning. Think of instances when the power goes out, or someone simply pulls the cord. There's no way to come up with a "logoff" time. The best we can do is figure out the next time the user came on. It's not an accurate representation, but it's the closest we'll be able to get.

Matching up start and stop session events ^

Once we've got all the IDs put together, we'll then need to match the session start event with the very next session end event. This might seem trivial, but in actuality, this is the hardest part of this process.

For many of the session start and stop events, Windows generates a unique Logon ID field. You can use this field to correlate a start and a stop session time. It is unique for each user logon session. If we can find a session start time and then look through the event log for the next session stop time with the same Logon ID, we've found that user's total session time.

User logon event showing the Logon ID

User logon event showing the Logon ID

User logoff event showing the Logon ID

User logoff event showing the Logon ID

You can see in the first screenshot above that the Administrator account on the LAB domain logged onto a computer called WIN81x86-1 on 10/3/15 at 11:02:05 AM. This generated event ID 4624 and is using the Logon ID of 0xD72BAA. Then, in the next screenshot, the computer generated an event ID 4647 at 11:03:28 AM when the user logged off and has a reference to that same Logon ID.

By matching up these two events and taking the difference in time, I can now see that the Administrator user account logged onto the computer for 1 minute and 23 seconds.

This was just a quick demonstration of actual logon/logoff scenarios. You'll find that when you review a computer in the "real world," you can't always depend on logon/logoff events if you'd like to find user session durations. Multiple scenarios may come into play, such as when a user locks her computer and comes back to unlock it. Perhaps she may lock her computer, and the power gets cut. There will be no unlock event; only a startup event. You need to watch out for these gotchas to be able to calculate user session history accurately.

A user session could consist of combinations of any of the following events.

Start EventStop Event
User LogonUser Logoff
User LogonComputer Startup
User LogonRDP Session Disconnect
User LogonLocked
RDP Session ReconnectRDP Session Disconnect
RDP Session ReconnectUser Logoff
RDP Session ReconnectLocked
RDP Session ReconnectComputer Startup
UnlockedComputer Startup
UnlockedRDP Session Disconnect
UnlockedUser Logoff

Now you see what you might think is an easy task quickly turns into something much more difficult to track accurately!

Using PowerShell to automate user login detection ^

Since the task of detecting how long a user logged on can be quite a task, I've created a PowerShell script called Get-UserLogonSessionHistory.ps1 available on Github. This script allows you to point it at a local or remote computer, query the event log with the appropriate filter, and return each user session.

Subscribe to 4sysops newsletter!

ComputerName          : FUSIONVM
Username              : Adam
StartTime             : 12/30/2016 9:01:52 AM
StartAction           : Logon
StopTime              : 1/22/2017 9:53:45 AM
StopAction            : Logoff
Session Active (Days) : 23.04
Session Active (Min)  : 33171.89
ComputerName          : DESKTOP-AVEQ7UN
Username              : Adam
StartTime             : 12/30/2016 8:54:14 AM
StartAction           : Logon
StopTime              : 12/30/2016 9:01:19 AM
StopAction            : Logoff
Session Active (Days) : 0
Session Active (Min)  : 7.08
ComputerName          : DESKTOP-AVEQ7UN
Username              : Adam
StartTime             : 12/30/2016 8:47:37 AM
StartAction           : Logon
StopTime              : 12/30/2016 8:53:07 AM
StopAction            : Logoff
Session Active (Days) : 0
Session Active (Min)  : 5.49
ComputerName          : DESKTOP-AVEQ7UN
Username              : Adam
StartTime             : 12/30/2016 8:43:50 AM
StartAction           : Logon
StopTime              : 12/30/2016 8:47:04 AM
StopAction            : Logoff
Session Active (Days) : 0
Session Active (Min)  : 3.23
ComputerName          : DESKTOP-AVEQ7UN
Username              : defaultuser0
StartTime             : 12/30/2016 8:42:39 AM
StartAction           : Logon
StopTime              : 12/30/2016 8:43:49 AM
StopAction            : Logoff
Session Active (Days) : 0
Session Active (Min)  : 1.18
  1. Shanif 6 years ago

    No other words.. Excellent.

  2. Peter 6 years ago

    My organisation runs a very simple login script which appends a users name, computer name, IP, Date and time, and method (console vs RDP) to a csv file on every login, and every logoff runs a similar script. As it is saved automatically and centrally we dont have to touch the PC at all. It is useful to find the users current IP address, which computers a user logs in to, and to check after hours logins. The file does get quite large so we archive it every few months manually. Not quite as forensic as the above approach but very simple.

    • Kent 6 years ago

      Great idea. Do you mind sharing that script? 🙂 or at least shed some lights what you used, PowerShell or something else? Cheers.

    • Savier 5 years ago

      Hi Peter,

      I’d like to learn a little morea about that script. How do I run the script? Where do I’ve to put it? Since I’m not the System Administrator at my organization I don’t know how to implement this script. Do you think you could help me with that info?

      Thanks in advance for your help.

  3. Thierry 6 years ago

    Noob question here : launching the script against my own computer I don’t get any output (no error either), what am I missing?

    Thank you

  4. Author
    Adam Bertram 6 years ago

    Did you enable auditing?

  5. Peter G 6 years ago

    @ Kent

    harks back to XP days but this bit still works

    @echo —                                                      —
    @echo —  Logging in …………………………………. —                                                       —
    @echo ———————————————————-

    :: comments for admin to tracks changes here
    :: set file server and local server
    Set FileSvr=File-02

    :: Get the PCs IP address
    call :GetIPAddress

    :: Get the date in ISO format (YearMonthDay)
    call :GetISODate

    :: Save a log of each logon, user account x computer x location x room etc.
    call :LogonLog

    :: exit clause for servers with names starting with SERV (change to suit your environment)
    if /i [%computername:~0,4%]==[SERV] (
    goto :Eof

    :: IE opens to our intranet page
    start iexplore

    :: End Main

    @echo ————————————————————–
    @echo Set ISODate…
    ::  Grab only the last 10 chars (DD/MM/YYYY or MM/DD/YYYY)…
    Set ISODate=%date:~-10%

    ::  If the date format is MM/DD/YYYY then convert it to DD/MM/YYYY…
    for /f “tokens=1-9 skip=1 delims=()-” %%i in (‘@echo. ^| date 2^>nul’) do (
    if /i [%%j]==[mm] ( Set ISODate=%ISODate:~3,2%/%ISODate:~0,2%/%ISODate:~6,4% )
    :: Now convert “DD/MM/YYYY” to YYYYMMDD…
    Set ISODate=%ISODate:~6,4%%ISODate:~3,2%%ISODate:~0,2%
    :: ——————————————————————-
    goto :Eof
    :: End GetISODate
    @echo ————————————————————–
    @echo Record Net Logon details…

    :: output to central log file – we set a “location” system environmental variable in each PC according to the site it is located at
    Set OutString=%Username%,%computername%,%Location%,%LogonServer%,%IP%,%date%,%time:~0,5%,%ISODate%,%ScriptVer%,%sessionname%,logon
    @echo %OutString% >> “\\%FileSvr%\NetworkData\_NetLogonLogs\%userdomain%.csv”

    :: output to users H drive (useful for checking the last time they logged in before archiving)
    @echo %OutString% >> “H:\%Username%’s LastLogon.csv”
    :: Clean up the temporary variables…
    Set ISODate=
    Set OutString=
    goto :Eof
    :: End LogonLog


    • Kent 6 years ago

      Nice. Thanks for sharing, Peter. I am going to give it a swing.

  6. Chris Bunn 6 years ago

    It can be cumbersome to manually audit. They show hundreds of logon and logoff events for the same user throughout the day. If you are looking for a easier way take a look at the software UserLock. UserLock records and reports on all user connection events to provide a central audit across the whole network – far beyond what Microsoft includes in Windows Server and Active Directory auditing.

  7. anand 5 years ago

    where will be the audit policies in windows 7?

  8. col 4 years ago

    Should this PS script function on a terminal server? If i turn on verbose it states it found 52 events which include logon\logoff etc. but it displays no output. It does work great on the workstations.

  9. barinder 4 years ago

    Hi adem,
    Thanks for sharing.

    i have tested in our environment. Followed same steps that you told. but when i run this script on domain it is asking for computer name. I fill the computername thenI don’t get any output (no error either), what am I missing?

    Thank you

  10. Bryce 4 years ago


    I am having the same issue, run the script from my PC query my PC and it returns blank. I have the auditing polices enabled.

    Does this need to be run from a DC?

  11. barinder 4 years ago

    Hi Adem,

    really, thisis amazing script. Could you please let me know where i can define computer name ?. i want to define in script instead of asking after run this script. I will to run this script by labtech so need to enter computer in script. Could you please let me know where i can put computer name.

    and second it is possible to export result into csv file ?

  12. David 4 years ago

    We were able to setup something similar. A VB executable runs at each user logon/logoff and records the user, computer, date/time and AD site; this is recorded into an SQL database. Another VB executable reads the SQL information, login histories can be viewed for a user or a computer. Been very useful having this information to track down a computer or user.

  13. Administrateur 3 years ago

    Hi Adam,

    Just one question, it is possible to export result into csv file please ?


  14. jason 3 years ago

    what am i missing ? how to use this script ?

    error below

    PS C:\Temp> .\logonscript.ps1 -parameter localhost
    Cannot process the "#requires" statement at line 1 because it is not in the correct format.
    The "#requires" statement must be in one of the following formats:
     "#requires -shellid <shellID>"
     "#requires -version <major.minor>"
     "#requires -pssnapin <psSnapInName> [-version <major.minor>]"
    At line:1 char:18
    + .\logonscript.ps1 <<<<  -parameter localhost
        + CategoryInfo          : ObjectNotFound: (:String) [], CommandNotFoundException
        + FullyQualifiedErrorId : CommandNotFoundException

  15. Rag-KS 1 year ago

    How to limit the report for the last 30 days?  Also can the script be modified to get all Computer logged into the Server during the last 30 days (rather than being a parameter)?

  16. Lorenzo 1 year ago

    Hello, I am trying the script but I am having an error:

    WARNING: Cannot convert ‘System.Object[]’ to the type ‘System.DateTime’ required by parameter ‘End’. Specified method is not supported.

    Someone knwo the way to fix it?

  17. Bob 11 months ago

    Hi Adam Bertram,
    I’m trying run this script but nothing is displayed as following. I don’t modify anything in the script

    PS C:\admin\scripts> .\Get-UserLogonSessionHistory.ps1
    PS C:\admin\scripts>

Leave a reply

Your email address will not be published.


© 4sysops 2006 - 2022


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


Log in with your credentials


Forgot your details?

Create Account