June 22nd, 2023

How can I find out the last time a user logged on from C++?

The PowerShell Get-LocalUser cmdlet gives you information about a local user, including the last logon time.

PS> Get-LocalUser Fred | Format-List

AccountExpires         :
Description            :
Enabled                : True
FullName               :
PasswordChangeableDate : 04/02/2023 2:25:04 PM
PasswordExpires        :
UserMayChangePassword  : True
PasswordRequired       : False
PasswordLastSet        : 04/01/2023 2:25:04 PM
LastLogon              : 04/01/2023 2:28:41 PM
Name                   : Fred
SID                    : S-1-5-21-162119347-98882960-612995125-1001
PrincipalSource        : Local
ObjectClass            : User

How can you get this information from C++?

For historical reasons, commands for operating with local users are in the LAN Manager API family. That’s because MS-DOS was a single-user operating system, so the only time you had to worry about “users” was if you were operating over the network.

This is also why a bunch of user management operations are handled by NET.EXE. The NET.EXE program was the part of LAN Manager that gave you access to all the network magic stuff.

C:\> NET USER Fred

User name                    Fred
Full Name
Comment
User's comment
Country/region code          000 (System Default)
Account active               Yes
Account expires              Never

Password last set            04/01/2023 2:25:04 PM
Password expires             Never
Password changeable          04/02/2023 2:25:04 PM
Password required            No
User may change password     Yes

Workstations allowed         All
Logon script
User profile
Home directory
Last logon                   04/01/2023 2:28:41 PM

Logon hours allowed          All

Local Group Memberships      *Administrators
Global Group memberships     *None
The command completed successfully.

The native function for getting this information is NetUserGetInfo. In particular, asking for information level 2 gives you a USER_INFO_2 structure which contains, among other things, usri2_last_logon.

The documentation includes a sample program showing how to request various levels of information and then print the results, so I won’t bother repeating it here.

Topics
Code

Author

Raymond has been involved in the evolution of Windows for more than 30 years. In 2003, he began a Web site known as The Old New Thing which has grown in popularity far beyond his wildest imagination, a development which still gives him the heebie-jeebies. The Web site spawned a book, coincidentally also titled The Old New Thing (Addison Wesley 2007). He occasionally appears on the Windows Dev Docs Twitter account to tell stories which convey no useful information.

1 comment

Discussion is closed. Login to edit/delete existing comments.

  • Simon Kissane · Edited

    If you are ever short of ideas for blog posts, here's a list of very obscure questions on this topic and adjacent ones:

    (1) What is the relationship between net.exe and net1.exe–why do they both exist? is it true that some commands are implemented by the second but not the first? if so, why? (2) I believe that "Country/region code" was only ever used by downlevel clients (such as DOS, OS/2, Win3.x, maybe 9x/Me) – can you confirm that? (3) Did anything ever use the code page setting (usri2_code_page)? It seems odd that net.exe doesn't display it or let you change...

    Read more