Jump to content

Having trouble converting AD date/time to readable Date/time


Recommended Posts

Hello all.. I am trying to convert Active Directory computer account last used date to a readable format. I have some functions that will do this, but they use the following command to perform the command:

w32tm /ntte <NT time epoch>
  Convert a NT system time, in (10^-7)s intervals from 0h 1-Jan 1601,
  into a readable format.

 

This is super slow when dealing with thousands of records. Here is what I have so far...

 

#include <array.au3>
#include <DateTimeConvert.au3>
#include <Date.au3>
$exampleADTimeStamp = "130793861794571914"
Msgbox(0,"MyResult", "Timestamp: " & $exampleADTimeStamp & @crlf & "Days since last Login: " & DateStringToDaysSinceLastLogin($exampleADTimeStamp))

Func DateStringToDaysSinceLastLogin($Timestamp)
    $ParseOutput = ParseLL($Timestamp)
    $ParseOutput = StringSplit($ParseOutput, " ", 2)
    $newFinal = _DateStandardToCalcDate($ParseOutput[0])
    Return Abs(CompareD($newFinal))
EndFunc   ;==>DateStringToDaysSinceLastLogin
Func ParseLL($oLastLogon)
    $sOutput = ""
    $iPID = Run(@ComSpec & " /c " & "w32tm.exe /ntte " & $oLastLogon, @TempDir, @SW_HIDE, 2)
    While 1
        $sOutput &= StdoutRead($iPID)
        If @error Then ExitLoop
    WEnd
    $sOutput = StringSplit($sOutput, " - ", 2 + 1)
    Return $sOutput[1]
EndFunc   ;==>ParseLL
Func CompareD($Datez)
    Return _DateDiff("D", @YEAR & "/" & @MON & "/" & @MDAY, $Datez)
EndFunc   ;==>CompareD

 

I'm sure there has got to be a better way to calculate this date format without having to use a command line tool, but after searching the forums, I haven't found anything..

Does anyone have any thoughts?

 

Thanks in advance!!!

C0d3 is P0etry( ͡° ͜ʖ ͡°)

Link to post
Share on other sites

Found my own answer.. I just need to write up this calculation...

 

 

Convert 18-digit LDAP timestamps to human readable date & epoch

The 18-digit Active Directory timestamps, also named 'Windows NT time format' and 'Win32 FILETIME or SYSTEMTIME'. These are used in Microsoft Active Directory for pwdLastSet, accountExpires, LastLogon, LastLogonTimestamp and LastPwdSet. The timestamp is the number of 100-nanoseconds intervals (1 nanosecond = one billionth of a second) since Jan 1, 1601 UTC.

 

 

Thanks anyways! 

 

(I notice i can never find an answer unless I post the Q here first, then I find the answer in minutes.)

C0d3 is P0etry( ͡° ͜ʖ ͡°)

Link to post
Share on other sites

Is this accurate enough?

#include <Date.au3>
$exampleADTimeStamp = "130793861794571914"

ConsoleWrite(_DateAdd("s", StringTrimRight($exampleADTimeStamp, 7), "1601/01/01 00:00:00")  & @CRLF)

 

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to post
Share on other sites

Its embarrassing how long I have been working to do this and how many methods I tried, and you knocked it out in one line.

I would give you a total man hug if you were here... Many thanks!!!

 

 

C0d3 is P0etry( ͡° ͜ʖ ͡°)

Link to post
Share on other sites

If you are talking about property "lastlogon" search function _AD_GetObjectProperties from my AD UDF for "lastlogon" and you will see how the date is translated into readable format.

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2022-02-19 - Version 1.6.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download
Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki
PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki
Task Scheduler (2019-12-03 - Version 1.5.1.0) - Download - General Help & Support - Wiki

Standard UDFs:
Excel - Example Scripts - Wiki
Word - Wiki

Tutorials:
ADO - Wiki
WebDriver - Wiki

 

Link to post
Share on other sites

If you are talking about property "lastlogon" search function _AD_GetObjectProperties from my AD UDF for "lastlogon" and you will see how the date is translated into readable format.

I tried this, but for some reason, in our environment, it always returned a blank value. Even a raw LDAP attribute query for a computer object returned a blank value which makes no sense.. Its not a UDF issue.. because I can pull any other attribute with no problem, but lastLogonTimeStamp is always blank.. Oddly enough, this works:

dsquery.exe * -limit 0 -filter "&(objectClass=Computer) (sAMAccountName=*)" -attr SamAccountName lastlogontimestamp

I think we just have a wonky AD environment. This is not the first time I saw something not work that very well should work.

 

C0d3 is P0etry( ͡° ͜ʖ ͡°)

Link to post
Share on other sites

lastlogon and lastlogontimestamp are two different properties. Did you try "lastlogon"?

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2022-02-19 - Version 1.6.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download
Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki
PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki
Task Scheduler (2019-12-03 - Version 1.5.1.0) - Download - General Help & Support - Wiki

Standard UDFs:
Excel - Example Scripts - Wiki
Word - Wiki

Tutorials:
ADO - Wiki
WebDriver - Wiki

 

Link to post
Share on other sites

lastlogon and lastlogontimestamp are two different properties. Did you try "lastlogon"?

I did, but from what I understand from Microsoft, lastlogon is specific to the domain controller, while LastLogonTimeStamp replicates. They suggest we pull from LastLogonTimeStamp when running reports. 

 

- LastLogon:
                  When a user logs on, this attribute is updated on the Domain Controller that provided the authentication ONLY.  Because it is only updated on one DC, that means this attribute is not replicated.  While that might seem inconvenient at first, this is actually a pretty useful function.  In those cases when you may want to figure out what sites a user has logged on (or not logged on), you would use this attribute.
                  
                  - LastLogonTimeStamp

                  To summarize this attribute, this is the replicated version of the LastLogon attribute.

 

C0d3 is P0etry( ͡° ͜ʖ ͡°)

Link to post
Share on other sites

Correct. Then function _AD_GetLastLoginDate is what you need. The function queries all DCs and returns the correct last login date/time.

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2022-02-19 - Version 1.6.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download
Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki
PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki
Task Scheduler (2019-12-03 - Version 1.5.1.0) - Download - General Help & Support - Wiki

Standard UDFs:
Excel - Example Scripts - Wiki
Word - Wiki

Tutorials:
ADO - Wiki
WebDriver - Wiki

 

Link to post
Share on other sites

Correct. Then function _AD_GetLastLoginDate is what you need. The function queries all DCs and returns the correct last login date/time.

It looks like that ended up working, but for some reason, that query takes much longer than a simple dsquery... 

 

This takes about 18 seconds to complete for me:

#include <ad.au3>
_AD_OPEN()
Msgbox(0,"_AD_GetLastLoginDate",_AD_GetLastLoginDate(@computername & "$"))
_AD_CLOSE()

While this takes less than 1 second

dsquery.exe * -limit 0 -filter "&(objectClass=Computer) (sAMAccountName=%computername%$)" -attr SamAccountName lastlogontimestamp

 

While I normally don't mind it taking a few more seconds, I have to query a little over 5000 computer accounts.

C0d3 is P0etry( ͡° ͜ʖ ͡°)

Link to post
Share on other sites
_AD_GetLastLoginDate queries ALL DCs to get the correct last logon because this property is - as you have noted - not replicated to other DCs. You can limit the DCs to query to a site or a list of DCs.
Edited by water

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2022-02-19 - Version 1.6.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download
Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki
PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki
Task Scheduler (2019-12-03 - Version 1.5.1.0) - Download - General Help & Support - Wiki

Standard UDFs:
Excel - Example Scripts - Wiki
Word - Wiki

Tutorials:
ADO - Wiki
WebDriver - Wiki

 

Link to post
Share on other sites
_AD_GetLastLoginDate queries ALL DCs to get the correct last logon because this property is - as you have noted - not replicated to other DCs.
You can limit the DCs to query to a site or a list of DCs.

Perfect, ill try that!

C0d3 is P0etry( ͡° ͜ʖ ͡°)

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By ahha
      Newbie to _GUICtrlListView_RegisterSortCallBack and can't get it to sort properly on date in format MM/DD/YYYY.
      Example code below.  Q - How do I get the date to sort properly?
      ;#AutoIt3Wrapper_run_debug_mode=Y #include <GUIConstantsEx.au3> #include <GuiListView.au3> Global $g_id_ListView Example() Exit Func Example() Local $idRow1, $idRow2, $idRow3 GUICreate("ListView Sort Question", 300, 200) $g_id_ListView = GUICtrlCreateListView("Row#|Name|Date", 10, 10, 280, 180) $id_Row1 = GUICtrlCreateListViewItem("#1|Alice|01/15/2022", $g_id_ListView) $id_Row2 = GUICtrlCreateListViewItem("#2|Bob|02/22/2021", $g_id_ListView) $id_Row3 = GUICtrlCreateListViewItem("#3|Carol|03/13/2021", $g_id_ListView) $id_Row10 = GUICtrlCreateListViewItem("#10|Dave|10/09/2021", $g_id_ListView) $id_Row11 = GUICtrlCreateListViewItem("#11|Eve|11/21/2021", $g_id_ListView) GUISetState(@SW_SHOW) ;$vCompareType = 0 ;not ok as Row# sort #1, #10, and want #1, #2, ;$vCompareType = 1 ;not ok as Row# sort #1, #10, and want #1, #2, $vCompareType = 2 ;Row# okay but Date messed up _GUICtrlListView_RegisterSortCallBack($g_id_ListView, $vCompareType) While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop Case $g_id_ListView ;MsgBox(0,"","col="&GUICtrlGetState($g_id_ListView)) _GUICtrlListView_SortItems($g_id_ListView, GUICtrlGetState($g_id_ListView)) EndSwitch WEnd _GUICtrlListView_UnRegisterSortCallBack($g_id_ListView) GUIDelete($g_id_ListView) EndFunc ;Func Example()  
    • By nacerbaaziz
      it recomended to use the builten function
      _DateDiff
       
       
       
      hello autoit team
      i made a simple function to help me get the difference between to date
      i liked to share it with you
      the paramatrs of this function
      is firstdate and lastedate
      the two params is as the following
      year/month/day hours:minuts:seconds
      here is the function
       
      #include <date.au3> func _dateBetween($s_firstDate, $s_lastDate = default) if not (StringRegExp($s_firstDate, "((\d{4})\/(\d{2})\/(\d{2})\s(\d{2})\:(\d{2})\:(\d{2}))", 0) = 1) then Return SetError(1, 0, 0) if $s_lastDate = default then $s_lastDate = @year & "/" & @mon & "/" & @mday & " " & @hour & ":" & @min & ":" & @sec if not (StringRegExp($s_lastDate, "((\d{4})\/(\d{2})\/(\d{2})\s(\d{2})\:(\d{2})\:(\d{2}))", 0) = 1) then Return SetError(2, 0, 0) local $a_FirstSplitDate = StringSplit(StringRegExpReplace($s_firstDate, "((.*)\s(.*))", "$2"), "/", 2) local $a_FirstSplitTime = StringSplit(StringRegExpReplace($s_firstDate, "((.*)\s(.*))", "$3"), ":", 2) local $a_lastSplitDate = StringSplit(StringRegExpReplace($s_lastDate, "((.*)\s(.*))", "$2"), "/", 2) local $a_LastSplitTime = StringSplit(StringRegExpReplace($s_lastDate, "((.*)\s(.*))", "$3"), ":", 2) local $i_firstDateValue = _DateToDayValue($a_FirstSplitDate[0], $a_FirstSplitDate[1], $a_FirstSplitDate[2]) local $i_LastDateValue = _DateToDayValue($a_LastSplitDate[0], $a_LastSplitDate[1], $a_LastSplitDate[2]) if $i_firstDateValue > $i_LastDateValue then Return SetError(3, 0, 0) local $i_totalDays = $i_LastDateValue-$i_firstDateValue if not ($i_totalDays = 0) then if $a_FirstSplitTime[0] <= $a_lastSplitTime[0] then $i_totalDays += 1 $a_lastSplitTime[0] -= $a_FirstSplitTime[0] elseIf $a_FirstSplitTime[0] > $a_lastSplitTime[0] then if $i_totalDays > 0 then $i_totalDays -= 1 $a_FirstSplitTime[0] -= $a_lastSplitTime[0] endIf endIf endIf local $i_totalYears = 0 if $i_totalDays >= 365 then While $i_totalDays >= 365 $i_totalYears += 1 $i_totalDays -= 365 Wend endIf local $i_TotalMonths = 0 if $i_totalDays >= 30 then While $i_totalDays >= 30 $i_totalMonths += 1 $i_totalDays -= 30 Wend endIf local $i_totalWeeks = 0 if $i_totalDays >= 7 then While $i_totalDays >= 7 $i_totalWeeks += 1 $i_totalDays -= 7 Wend endIf $i_totalSeconds = ((($a_FirstSplitTime[0]*60)*60)+($a_FirstSplitTime[1]*60)+($a_FirstSplitTime[2]))-((($a_lastSplitTime[0]*60)*60)+($a_lastSplitTime[1]*60)+($a_LastSplitTime[2])) local $minus = "" if $i_totalSeconds < 0 then $minus = "-" $i_totalSeconds = StringReplace($i_totalSeconds, "-", "") endIf local $i_totalHours = 0 if $i_totalSeconds >= 3600 then While $i_totalSeconds >= 3600 $i_totalHours += 1 $i_totalSeconds -= 3600 Wend endIf local $i_totalminuts = 0 if $i_totalSeconds >= 60 then While $i_totalSeconds >= 60 $i_totalminuts += 1 $i_totalSeconds -= 60 Wend endIf local $a_arrayReturn[7] $a_arrayReturn[0] = $i_totalYears $a_arrayReturn[1] = $i_totalMonths $a_arrayReturn[2] = $i_totalWeeks $a_arrayReturn[3] = $i_totalDays $a_arrayReturn[4] = $minus & $i_totalHours $a_arrayReturn[5] = $minus & $i_totalminuts $a_arrayReturn[6] = $minus & $i_totalSeconds return $a_arrayReturn endFunc  
      here is an example
       
       
      $a_calc = _dateBetween("2015/02/12 23:00:05", "2030/02/12 23:25:50") msgBox(64, "result", StringFormat("the difference is : %i years and %i months and %i weeks and %i days and %i hours and %i minuts and %i seconds", $a_calc[0], $a_calc[1], $a_calc[2], $a_calc[3], $a_calc[4], $a_calc[5], $a_calc[6]))  
      am waiting for your comments
      with my greetings
    • By Jahar
      Hi All,
      Please help me on how to fetch date/time of last windows 10 system restore point using autoit? Basically its about querying the last restore point.
    • By TheDcoder
      Hi everyone,
      I am bit stumped as to why I am not able to set the time in the Date control
      #include <DateTimeConstants.au3> #include <GUIConstantsEx.au3> #include <MsgBoxConstants.au3> Example() Func Example() GUICreate("My GUI get date", 200, 200, 800, 200) Local $idDate = GUICtrlCreateDate("1953/04/25", 10, 10, 185, 20, $DTS_TIMEFORMAT) ; to select a specific default format Local $sStyle = "HH:mm:ss" GUICtrlSendMsg($idDate, $DTM_SETFORMATW, 0, $sStyle) ; Set time Local $iRet = GUICtrlSetData($idDate, '13:33:37') ConsoleWrite('GUICtrlSetData returned ' & ($iRet = 1 ? 'success' : 'failure') & @CRLF) GUISetState(@SW_SHOW) ; Loop until the user exits. While GUIGetMsg() <> $GUI_EVENT_CLOSE WEnd MsgBox($MB_SYSTEMMODAL, "Time", GUICtrlRead($idDate)) EndFunc ;==>Example The documentation for GUICtrlSetData clearly mentions that it uses the same format as GUICtrlRead:
      But I get failure
      What gives?
      Thanks for the help in advance!
    • By Colduction
      Hi guys, i want to convert WebKit/Chrome timestamps that i've found in chrome cookie database to Human-Readable time (if possible, with UTC or GMT offset).
      Example of WebKit/Chrome timestamp: 13228999534132232 Output that i want: 2020-03-18 20:16:56 This site has a tool to do this work, but i wonder how to convert this time (this timestamp's time bases are 1600/01/01) to human-readable time:
      https://www.epochconverter.com/webkit
×
×
  • Create New...