27

I am hoping that somewhere in Active Directory the "last logged on from [computer]" is written/stored, or there is a log I can parse out?

The purpose of wanting to know the last PC logged on from is for offering remote support over the network - our users move around pretty infrequently, but I'd like to know that whatever I'm consulting was updating that morning (when they logged in, presumably) at minimum.

I'm also considering login scripts that write the user and computer names to a known location I can reference, but some of our users don't like to logout for 15 days at a time.

If there is an elegant solution that uses login scripts, definitely mention it - but if it happens to work for merely unlocking the station, that would be even better!

12 Answers 12

27

As part of our logon script I have that information (and more) logged into a hidden share on a server, with one log file per user. A logoff scripts adds the time the user logged off to the same log file. Easy to set up, no cost and the information is there in an easy to read format.

6
  • Plus, by appending to the log, you get a historical record, which can be very handy at times. Jul 30, 2009 at 21:49
  • 1
    Implemented this for now, probably will move to a vbs with more features in the future :) So far, using a VERY simple batch logon script: echo %date%,%time%,%username%,logon,%computername% >> \\server\logon$\logons.csv Open with Excel, and you're set!
    – Garrett
    Sep 7, 2010 at 23:50
  • Does the login script run as the user, in which case the user could also go in and modify the log?
    – James Yale
    Jan 31, 2011 at 16:29
  • @James, this is why I use hidden a hidden share to store the logs. Of course it will depend on just how savvy your users are, as the location can be obtained by simply reading the script. I don't have that problem with my current set of users. :) Jan 31, 2011 at 17:21
  • 1
    I did something similar, except the logon script made a call to a web service which updated a database. The database had a web front-end to view current status. However, it was problematic for mobile users.
    – Nic
    Feb 1, 2011 at 7:39
11

We do this via logon script which updates the computer object's description in AD.

You need to perform a custom delegation of control to allow "Authenticated Users" to write the description property of computer objects in the domain/s.

Once that's done, all you need is a script that generates whatever information you want and writes the properties to the computer object. This script is then assigned as a login script via a Group Policy object linked to the domain.

We put a timestamp, username, IP(s) in the description field. The timestamp comes first because it makes it easy to quickly see "old" computer objects by sorting on the description field.

Here's the script I wrote for this if you want to use it as a starting point:

On Error Resume Next

Set objSysInfo = CreateObject("ADSystemInfo") 'Bind to AD
Set objNet = CreateObject("WScript.Network")

strCompDN = objSysInfo.ComputerName 'DN for computer, e.g. "CN=VISTAWORKSTATION,OU=Child OU Name,OU=Parent OU Name,DC=domain,DC=com"
Set objComp = GetObject("LDAP://" & strCompDN) 'IADsComputer object

strUserDN = objSysInfo.UserName 'DN for user, e.g. "CN=John Smith,OU=Child OU Name,OU=Parent OU Name,DC=domain,DC=com"
Set objUser = GetObject("LDAP://" & strUserDN) 'IADsUser object

strUsrLogin = LCase(objNet.UserName)

strNow = Now
strDateStamp = DatePart("yyyy",strNow) & _
    Right("0" & DatePart("m",strNow), 2) & _
    Right("0" & DatePart("d",strNow), 2) & _
    "@" & _
    Right("0" & DatePart("h",strNow), 2) & _
    Right("0" & DatePart("n",strNow), 2)

'RegExp object used to perform a simple match on IP address
Set objRE = New RegExp
objRE.IgnoreCase = True
'Note this regexp pattern isn't "correct" for matching an IPv4 address properly, but since WMI will return an
'array of IP addresses, this is sufficient to distinguish IPv4 vs IPv6
objRE.Pattern = "^\d+\.\d+\.\d+\.\d+$"

strIP = ""

'Connect to WMI and retreive all network adapters
Set objWMI = GetObject("winmgmts:")
Set colNICs = objWMI.ExecQuery("SELECT * FROM Win32_NetworkAdapterConfiguration")

'Get the IP(s) assigned to whichever network adapter has our default gateway
If colNICs.Count > 0 Then
    For Each objNIC in colNICs
        If IsArray(objNIC.DefaultIPGateway) Then
            arrIP = objNIC.IPAddress
            For i = 0 To UBound(arrip)
                If objRE.Test(arrIP(i)) Then strIP = strIP & " " & arrIP(i)
            Next
            strMAC = objNIC.MACAddress
        End If  
    Next
End If

strIP = Trim(strIP)

objComp.Description = strDateStamp & " " & strUsrLogin & " " & strIP
objComp.Put "extensionAttribute1", strUsrLogin
objComp.Put "extensionAttribute2", strIP
objComp.Put "extensionAttribute3", strMAC

objComp.SetInfo
2
  • How to delegate authenticated users write permissions explicity to the description field object in AD?
    – NULL.Dude
    Mar 1, 2019 at 5:08
  • I did something similar, I used startup (not logon) script to get computer and timestamp into log file , that one runs under system credentials, so its safe from user hands, then to get the username I also used login script, that one does run under user credentials, but it didn't write directly to db instead it wrote txt file that was read from another script that runs with admin credentials whenever that txt file is modified and writes to the db.
    – arana
    Apr 5, 2023 at 17:13
7

I had to achieve the same result for similar reasons; somehow determine which machine a specific user logged in from. I wanted to know "before the fact", and couldn't change user login scripts as discussed above.
I used powershell on the DC that the user was authenticating against to parse the Security event log:

get-eventlog "Security" | where {$_.Message -like "*Username*" -AND "Source Network Address"} | export-csv C:\Temp\test.csv

Crack open the .csv with excel or your fav editor and look for the most recent entry that shows both the Account Name (Username) and the Source Network Address within the same event.
This might not be a 100% reliable solution (depending on DHCP lease times, etc.), but it worked for me.

6

You can enable auditing for account logon events. These events (including workstation unlock) will be stored in the DC's security log.

There are also third party tools that can make this easier, such as True Last Logon.

0
4

I just write the user name (as well as other info, like date and time, some program versions and so on) into the computer description using a logon script. That way I can pull all the info from AD Users & Computers quickly and easily, and as a bonus have a good way of identifying which PCs still in AD haven't been used in a while (and are therefore most likely dead machines).

4

ThatGraemeGuy, thanks for excellent script! I had to rewrite it in PowerShell, but it still works.

$CompDN = "(&(objectCategory=computer)(objectClass=computer)(cn=$env:COMPUTERNAME))"
$strCompDN = [string]([adsisearcher]$CompDN).FindOne().Properties.distinguishedname
$objComp = [ADSI]("LDAP://"+$strCompDN)

# quit if computer is a server or DC
if (($strCompDN -like '*Controller*') -or ($strCompDN -like '*SERVER*')) { exit }

$strUsrLogin = $env:username
$strDateStamp = Get-Date -f 'yyyy-MM-dd@HH:mm'
$IPPattern = "^\d+\.\d+\.\d+\.\d+$"

$colNICs = gwmi Win32_NetworkAdapterConfiguration
if ($colNICs.Count -gt 0) {
foreach ($objNIC in $colNICs){
        if ($objNIC.DefaultIPGateway) {
            $arrIP = $objNIC.IPAddress
            for ($i=0; $i -lt $colNICs.Count; $i++) { 
            if ($arrIP[$i] -match $IPPattern) { $strIP = $arrIP[$i]; $strMAC = $objNIC.MACAddress }
            }
        }
    }
}

$objComp.Description = $strDateStamp + " - " + $strUsrLogin + " - " + $strIP
$objComp.extensionAttribute1 = $strUsrLogin
$objComp.extensionAttribute2 = $strIP
$objComp.extensionAttribute3 = $strMAC
$objComp.SetInfo()
2

The trick to knowing for certain where users last logged in aside from suggestions from Adam is log aggregation. If you have multiple domain controllers you either have to check them all, or centralize your logging and then check the single log.

Some, maybe even most, third party tools are smart enough to query all the domain controllers. But if you're thinking of writing a script to parse it out yourself I can't argue strongly enough for centralization of your logs.

1

Ideally, You would capture the following for your CSIRT Team to assist in invstigations.

userid logging in with workstation name MAC address IP address Date/Timestamp login type (rdp, interfactive etc)

Then dump that into a sql command into a database that they can query. Bits and pieces are logged all over the place, but recording this saves time pulling the data from DHCP/WINS servers etc...

1
  • 1
    I think this is a bit overkill for "Hey, what is Donny's computer name?" but maybe someday we'll be at that level :P
    – Garrett
    Jul 31, 2009 at 15:53
1

I was going to add this as a comment to marcusjv's answer above, but I dont have the reputation so a separate answer will have to do:

In that expression -AND "Source Network Address" will always evaluate to TRUE

I think what you need is: get-eventlog "Security" | where {$.Message -like "*username*" -AND $.Message.contains("Source Network Address")}

0

Only way to have very latest information is thru log foraging. Use a tool like Microsoft Operations Manager or free tool like snare to aggregate interesting event logs from server into central place (normal text files or SQL database) and then use tools like logparser or SQL queries to generate the report you want.

for finding different event IDs for different events go thru Event Log Encyclopedia

Let me know, if you want to follow this route, I can help you create the appropriate queries for logparser.

0

If your looking for a historical reference, you can try a 3rd party tool like Logon Central from Motivate Systems. It records all Active Directory user logons and provides a web interface for data mining. It also includes some pretty good graphs that translate logon statistics to percent usage.

0

ind Login in AD

Many times we require to know if particular login is a part of ad user group. Or sometimes we need to know a AD group and wanted to know who all logins are part of it.

There are many different ways to achieve this.

I follow this step to create a shortcut on my desktop where I can easily find the logins Please follow the process as

START-> RUN -> rundll32 dsquery, OpenQueryWindow

You can find all the AD you are part of, using this.

Start->Settings->Control Panel -> Administrator Tools -> Active Directory User and Computers Select the Domain you want to find login, right click that domain and choose “Find” option.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .