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

Raymond Chen

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.

1 comment

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

  • Simon Kissane 0

    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 it (4) can you confirm the actual purpose of the UF_MNS_LOGON_ACCOUNT flag – PowerShell docs claim it has something to do with Majority Node Set in Windows Clustering, but I think that’s a mistaken inference; I personally suspect it is a disused historical vestige of the old Microsoft Services for NetWare product (SNW, and related File and Print Services for NetWare aka FPNW) – can you confirm? (5) I notice even in Windows 10 x64 (10.0.19041.1466), net1.exe (but not net.exe) still contains the UTF-16LE strings FPNWCLNT.DLL and NWAPI32.DLL (and hence I assume some code to control SNW/FPNW must still be in there) – but were those DLLs ever shipped for 64-bit Windows? (6) In the SDK/DDK, km/ntifs.h and um/NTSecAPI.h mention “MSV1_0_MNS_LOGON” and “#define LOGON_GRACE_LOGON” which is annotated as “// Values returned by the MSV1_0_MNS_LOGON SubAuthentication DLL” – has this got something to do with SNW/FPNW and the UF_MNS_LOGON_ACCOUNT flag? Old KB article 192696 mentions a bug whereby SNW didn’t maintain the grace logon counter correctly, but says the bug was fixed in a Windows NT4.0 service pack (it doesn’t say which one) (7) According to the documentation, usriX_params/USER_INFO_1013 is used by “services for Macintosh, file and print services for NetWare, and the Remote Access Server (RAS)”–am I correct that it is now purely a legacy field, and no currently supported Microsoft software actually uses it? (8) The format of that field has never (to my knowledge) been publicly documented. I understand there are some good reasons why you don’t want to / aren’t allowed to talk about the format of undocumented data structures, but if I am right that it is now purely a historical vestige, are you allowed to make an exception in that case?

    Maybe my questions are too obscure. I have no practical need for answers to any of them, they are purely driven by intellectual/historical curiosity. But if you ever decided to blog on any of them, you’d have at least one happy reader.

Feedback usabilla icon