Jump to content
Sign in to follow this  
dkwokgs

Active Directory - Pull All Users in OU "Last Logon" information and existence of a user

Recommended Posts

dkwokgs

Hi There,

Can someone advise me how to do pull all Users "Last Logon" information and existence of a user/computer account from an OU in Active Directory?

Thanks.

Edited by dkwokgs

Share this post


Link to post
Share on other sites
Airwolf

I would suggest doing some reading about LDAP lookups and COM objects. For an example, take a look at the ADUC Computers OU Cleanup script linked in my signature. COM objects in AutoIt are very similar to VBS. You can populate an array based on an LDAP query and then work with the LastLogon property of each object in the array.


Certifications: A+, Network+, Security+, Linux+, LPIC-1, MCSA | Languages: AutoIt, C, SQL, .NETBooks: AutoIt v3: Your Quick Guide - $7.99 - O'Reilly Media - September 2007-------->[u]AutoIt v3 Development - newbie to g33k[/u] - Coming Soon - Fate Publishing - Spring 2013UDF Libraries: SkypeCOM UDF Library | ADUC Computers OU Cleanup | Find PixelChecksumExamples: Skype COM Examples - Skype4COMLib Examples converted from VBS to AutoIt

Share this post


Link to post
Share on other sites
PsaltyDS

Hi There,

Can someone advise me how to do pull all Users "Last Logon" information and existence of a user/computer account from an OU in Active Directory?

Thanks.

Something like this, but I can't test the UINT64 conversion right now:
#include <Date.au3>

Global $oMyError = ObjEvent("AutoIt.Error", "MyErrFunc")

Global $sServer = "myserver.mydomain.com"
Global $sUserPath = "cn=User Name, ou=Users, dc=mydomain, dc=com"
Global $oUser, $oLastLogon, $iLastLogon

; Get user object
Local $oUser = ObjGet("LDAP://" & $sServer & "/" & $sUserPath)
If IsObj($oUser) Then
    $oLastLogon = $oUser.Get("lastLogon")
; Convert INT64 to float
    $iLastLogon = $oLastLogon.HighPart * (2^32)
    $iLastLogon += $oLastLogon.LowPart
; Convert 100ns count to seconds
    $iDays = Floor($iLastLogon / 10000000)
; Convert seconds since 12:00AM January 01, 1601
    $sLastLogon _DateAdd("S", $iLastLogon, "1601/01/01 00:00:00")
    MsgBox(64, "Last Logon", "User " & $oUser.Name & " last logged on at " & $sLastLogon)
Else
    MsgBox(16, "Error", "$oUser is not an object.")
EndIf

Func MyErrFunc()
    $HexNumber = Hex($oMyError.number, 8)
    MsgBox(0, "", "We intercepted a COM Error !" & @CRLF & _
            "Number is: " & $HexNumber & @CRLF & _
            "Windescription is: " & $oMyError.windescription)

    $g_eventerror = 1; something to check for when this function returns
EndFunc ;==>MyErrFunc

:mellow:


Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law

Share this post


Link to post
Share on other sites
water

Hi dkwokgs,

for AD access you could use the AD UDF which can be found at http://www.autoitscript.com/forum/index.php?showtopic=37378 or

http://www.autoitscript.com/forum/index.ph...st&id=22018

To check if a CN (User, Computer ...) exists in an OU I would use something like:

#include <adfunctions.au3>
$ou = "DC=microsoft,DC=com"                     ; Root of your AD
If Not _ADObjectExists(<SamAccountName>) ..

LASTLOGON:

Be careful with the lastlogon date. Because the lastLogon attribute is not replicated in Active Directory, a different value can be stored in the copy of Active Directory on each Domain Controller.

There are a lot of tools available from the internet to check the true last logon date/time. Search for "active directory true last logon".

See: http://msdn.microsoft.com/en-us/library/ms676823(VS.85).aspx and http://msdn.microsoft.com/en-us/library/ms676824.aspx

HTH

Thomas

Edited by water

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (2018-06-01 - Version 1.4.9.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2018-09-01 - Version 1.3.4.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
PowerPoint (2017-06-06 - Version 0.0.5.0) - Download - General Help & Support
Excel - Example Scripts - Wiki
Word - Wiki
 
Tutorials:

ADO - Wiki

 

Share this post


Link to post
Share on other sites
PsaltyDS

I'd like to make this work in AutoIt for myself, but I hit a glitch. This works for a user that has logged in authenticated by the DC being queried:

#include <Date.au3>

Global $oMyError = ObjEvent("AutoIt.Error", "MyErrFunc")

Global $sServer = "MyDC.MyDomain.com"
Global $sUserPath = "cn=My User, ou=Users,  dc=MyDomain, dc=com"
Global $oUser, $oLastLogon, $iLastLogon = 0

; Get user object
Local $oUser = ObjGet("LDAP://" & $sServer & "/" & $sUserPath)
If IsObj($oUser) Then
    $oLastLogon = $oUser.Get("lastLogon")
    If @error Then
        MsgBox(16, 'Debug', 'Error occured retreiving $oUser.Get("lasLogon").' & @CRLF & _
                'This attribute may not exist for this user (never logged in by this DC).')
    Else
        ; Convert IADsLargeInteger parts to 100ns count
        $iLastLogonHigh = $oLastLogon.HighPart
        $iLastLogonLow = $oLastLogon.LowPart
        If $iLastLogonLow < 0 Then $iLastLogonHigh += 1; Compensate for IADsLargeInteger interface error
        $iLastLogon = $iLastLogonHigh * 2 ^ 32
        $iLastLogon += $iLastLogonLow
        
        ; Convert 100ns count to integer seconds
        $iSeconds = Floor($iLastLogon / 10000000)
        
        ; Convert seconds since 12:00AM January 01, 1601 to date string
        $sLastLogon = _DateAdd("S", $iSeconds, "1601/01/01 00:00:00")
        
        ; Display result
        MsgBox(64, "Last Logon", "$sLastLogon = " & $sLastLogon & " Zulu (UTC)")
    EndIf
Else
    MsgBox(16, "Error", "$oUser is not an object, user may not exist.")
EndIf

Func MyErrFunc()
    MsgBox(16, "AutoIt COM Error", "AutoIt intercepted a COM Error:" & @CRLF & _
            "Number is: " & Hex($oMyError.number, 8) & @CRLF & _
            "Windescription is: " & $oMyError.windescription)
    SetError(1)
EndFunc;==>MyErrFunc

Note the conversion of the time code had to be updated, but looks good now.

The problem is the "lastLogon" attribute seems to not exist at all if the user has never logged on (via this DC at least). So I get COM errors on those users.

How would I check if "lastLogon" attribute exists for $oUser without triggering COM errors?

:mellow:

Edit1: Removed unnecessary conversion from seconds to days.

Edit2: Put back missing EndIf.

Edited by PsaltyDS

Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law

Share this post


Link to post
Share on other sites
water

Hi PsaltyDS,

How would I check if "lastLogon" attribute exists for $oUser without triggering COM errors?

Maybe the AD UDF would be a good place to start. See post #4 for the download links.

It installs a custom error handler and returns 0 if the object or attribute doesn't exist. Check _ADDoError() and _ADGetObjectAttribute()

HTH

Thomas

Edited by water

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (2018-06-01 - Version 1.4.9.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2018-09-01 - Version 1.3.4.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
PowerPoint (2017-06-06 - Version 0.0.5.0) - Download - General Help & Support
Excel - Example Scripts - Wiki
Word - Wiki
 
Tutorials:

ADO - Wiki

 

Share this post


Link to post
Share on other sites
PsaltyDS

Hi PsaltyDS,

Maybe the AD UDF would be a good place to start. See post #4 for the download links.

It installs a custom error handler and returns 0 if the object or attribute doesn't exist. Check _ADDoError() and _ADGetObjectAttribute()

HTH

Thomas

The _ADGetObjectAttribute() function will return the lastLogon attribute object, but you still need the conversion process to get a date out of it.

As for my problem above, that was just me being drifty... :mellow:

What I thought was my test user that had never logged on was in fact a Group for test users, which is why it didn't have a lastLogon attribute. Now that I am using a real account that has never logged on, it simply returns the IADsLargeInteger equivalent of 0. To avoid getting last logon date of "1601/01/01 00:00:00" I added a catch for that condition, and it all works now:

#include <Date.au3>

Global $oMyError = ObjEvent("AutoIt.Error", "MyErrFunc")

Global $sServer = "MyDC.MyDomain.com"
Global $sUserPath = "cn=My User, ou=Users,  dc=MyDomain, dc=com"
Global $oUser, $oLastLogon, $iLastLogon = 0

; Get user object
Local $oUser = ObjGet("LDAP://" & $sServer & "/" & $sUserPath)
If IsObj($oUser) Then
    $oLastLogon = $oUser.Get("lastLogon")
    If @error Then
        MsgBox(16, 'Debug', 'Error occured retreiving $oUser.Get("lastLogon").' & @CRLF & _
                'This attribute may not exist for this object.')
    Else
        ; Convert IADsLargeInteger parts to 100ns count
        $iLastLogonHigh = $oLastLogon.HighPart
        $iLastLogonLow = $oLastLogon.LowPart
        If $iLastLogonLow < 0 Then $iLastLogonHigh += 1; Compensate for IADsLargeInteger interface error
        $iLastLogon = $iLastLogonHigh * 2 ^ 32
        $iLastLogon += $iLastLogonLow
        
        ; Check if user ever logged in
        If $iLastLogon = 0 Then
            MsgBox(64, "Last Logon", "User has never logged on.")
        Else
            ; Convert 100ns count to integer seconds
            $iSeconds = Floor($iLastLogon / 10000000)

            ; Convert seconds since 12:00AM January 01, 1601 to date string
            $sLastLogon = _DateAdd("S", $iSeconds, "1601/01/01 00:00:00")

            ; Display result
            MsgBox(64, "Last Logon", "$sLastLogon = " & $sLastLogon & " Zulu (UTC)")
        EndIf
    EndIf
Else
    MsgBox(16, "Error", "$oUser is not an object, user may not exist.")
EndIf

Func MyErrFunc()
    MsgBox(16, "AutoIt COM Error", "AutoIt intercepted a COM Error:" & @CRLF & _
            "Number is: " & Hex($oMyError.number, 8) & @CRLF & _
            "Windescription is: " & $oMyError.windescription)
    SetError(1)
EndFunc;==>MyErrFunc

The trick way to do this would be check that $oUser was in fact a "User" type object first, but it's Friday and sunny outside and I'm losing the will to script!

:(

Edited by PsaltyDS

Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law

Share this post


Link to post
Share on other sites
supersonic

Hello!

Superb! That's what I was looking for so looong...

BUT: When try running this script, I get a COM

error (such an object is not availiable).

My PC: XP SP3.

Any ideas?

Greets,

-supersonic.

Share this post


Link to post
Share on other sites
PsaltyDS

Hello!

Superb! That's what I was looking for so looong...

BUT: When try running this script, I get a COM

error (such an object is not availiable).

My PC: XP SP3.

Any ideas?

Greets,

-supersonic.

The script is for an AD domain. Are you trying to run it on a workgroup or stand-alone PC?

:D


Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law

Share this post


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
Sign in to follow this  

×