Using CLR for adsi lastlogontime

Started by stanl, December 03, 2023, 04:56:25 AM

Previous topic - Next topic

stanl

As Active Directory last logon timestamps return a huge number [something like nanoseconds since 1/1/1601] I was reminded how I tried to tackle converting to a datetime in 2002.... very ugly code using Binary Math. Implementing the CLR in WB made the process easier, and I sent example code to a friend who inherited wb scripts for adsi.
Code (WINBATCH) Select


Logon = "132635534097464000"  ;as returned from adsi query
Logon = ObjectType("i8",Logon)
Date1 = ObjectClrNew("System.DateTime")
strDate1 = TimeFormat(Date1.FromFileTime(Logon),"MM/dd/yyyy hh:mm:ss t")
Message(Logon,strDate1)


;will give incorrect year as 0421 not 2021
;Date1 = ObjectClrNew("System.DateTime",Logon)
;strDate1 = TimeFormat(Date1.ToLocalTime(),"MM/dd/yyyy hh:mm:ss t")
;strDate2 = TimeFormat(Date1.ToUniversalTime(),"MM/dd/yyyy hh:mm:ss t")
;Message(Logon,strDate1:@LF:strDate2)



He wrote back questioning why the commented portion would give erroneous data and could it be fixed. Not sure if I or someone else brought that up here years ago. Anyway, he was happy with what I did send... gratis :)

td

I suspect that ADSI's logon time is in file time which starts on  January 1, 1601UTC so the conversion works when you use FromFileTime. However, ToLocalTime and ToUniversalTime expect 100-nanosecond intervals that start on year 1 January 1 at 00:00:00.000 UTC. If you notice, the date returned from the latter two functions is about 1601 1599 years off.

As an FYI, you do not need the Logon = ObjectType("i8",Logon) in your script since the advent of native 64-bit integer support in WIL. The conversion is handled automagically by the interpreter.
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

td

Should have mentioned that the quotes around the 132635534097464000 also need to be removed, if you want to rid yourself of the ObjectType line.
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

stanl

Just glad it worked. Have no idea about the version of WB being used. Just trying to help out for a friend. Also I found that in PS I could




$logon = "132635534097464000"
$logon =[datetime]::FromFileTime($logon).ToLocalTime().ToString("MM/dd/yyyy hh:mm:ss")



or ToUniversalTime() with no issues, so assume could be done similar in CL.

stanl

Oh, and I appreciated your comments and should have written to that effect in the start.

td

DateTime is a structure in C# that is implemented on the process stack. WIL cannot implement a .Net structure datatype internally, so the FromFileTime returns a string date but not another DateTime structure. The PS code works because you are calling a method on a structure that was returned by a call to a method on another structure. You can call the FromFileTimeUtc method using WinBatch CLR hosting if you want the file time returned as UTC. Also, File Time can itself be either UTC or local time. It depends on the application and system originating the file time.


"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

stanl

Quote from: td on December 05, 2023, 04:53:47 AM
D You can call the FromFileTimeUtc method using WinBatch CLR hosting if you want the file time returned as UTC. Also, File Time can itself be either UTC or local time. It depends on the application and system originating the file time.


Nice to know.