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.
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.