DavidLago

Trying to dev a script to calculate Active Directory Authentication Time

13 posts in this topic

#1 ·  Posted (edited)

Hello. 

I have 5 DCs, and I need to create a scheduled task to run a script that will test the authentication time for each one of them, once every minute. (Then I'll use it within a log analyser to create graphics).

I came up with a script using the great AD UDF (by water). First I tried using "for" and an array, but something was messing up the results, then I went for the dumb old fashioned way:

#Include <ad.au3>
#include <MsgBoxConstants.au3>

Global $AdTestTime = ""
Global $Timer1, $Timer2, $Timer3, $Timer4, $Timer5 = ""
Global $sAD1 = "MYSERVER109"
Global $sAD2 = "MYSERVER110"
Global $sAD3 = "MYSERVER111"
Global $sAD4 = "MYSERVER112"
Global $sAD5 = "MYSERVER113"

$Timer1 = Timerinit()
_AD_Open("", "", $sAD1)
_AD_Close()
Local $fDiff1 = TimerDiff($Timer1)

$Timer2 = Timerinit()
_AD_Open("", "", $sAD2)
_AD_Close()
Local $fDiff2 = TimerDiff($Timer2)

$Timer3 = Timerinit()
_AD_Open("", "", $sAD3)
_AD_Close()
Local $fDiff3 = TimerDiff($Timer3)

$Timer4 = Timerinit()
_AD_Open("", "", $sAD4)
_AD_Close()
Local $fDiff4 = TimerDiff($Timer4)

$Timer5 = Timerinit()
_AD_Open("", "", $sAD5)
_AD_Close()
Local $fDiff5 = TimerDiff($Timer5)

MsgBox(0,"", "MYSERVER109=" & $fDiff1)
MsgBox(0,"", "MYSERVER110=" & $fDiff2)
MsgBox(0,"", "MYSERVER111=" & $fDiff3)
MsgBox(0,"", "MYSERVER112=" & $fDiff4)
MsgBox(0,"", "MYSERVER113=" & $fDiff5)

Still, something is off here. 

The first AD to be tested is always the slowest one, by far, like 20 times slower. Then I started to suspect that the first one starts the "negotiation", and the following ones ride the gravy train.

If I repeat the first code twice, All servers seem to have a similar result.

$Timer1 = Timerinit()
_AD_Open("", "", $sAD1)
_AD_Close()
Local $fDiff1 = TimerDiff($Timer1)

$Timer1 = Timerinit()
_AD_Open("", "", $sAD1)
_AD_Close()
Local $fDiff1 = TimerDiff($Timer1)

$Timer2....

Am I right?

Also, is there a better way to test the authentication time?

Thanks for the help.

- Dave

Edited by DavidLago

Just a server analyst that has never been into programming that much. So, small fish here :)

Share this post


Link to post
Share on other sites



I'm not sure about a "better" way, but this is how I would do it. I do have a lot of DCs so listing them out would be hassle for me.

#include <AD.au3>

Global $iResult, $aDCs, $time, $timediff

$iResult = _AD_Open("", "", "", "", "", 1)
$aDCs = _AD_ListDomainControllers()
_AD_Close()
;_ArrayDisplay($aDCs, "", "|0:2") ; Display All DC's in Array
For $iIndex = 1 to $aDCs[0][0]
    $time = Timerinit()
    _AD_Open("", "", "", $aDCs[$iIndex][2])
    _AD_Close()
    $timediff = TimerDiff($time)
    ConsoleWrite($iIndex & " DC = " & $aDCs[$iIndex][2] & " | Time = " & $timediff & @CRLF)
Next

 

Share this post


Link to post
Share on other sites

Thanks, Surf. 

Actually I have more than 40 DCs, but I just want to test 5 of them, specifically. This "_AD_ListDomainControllers" function won't work with any parameters of filters, so, all of them will come to the array.

Also, The first one still comes with a higher latency. 

I think it's not because of the token thing, probably, calling up the include...


Just a server analyst that has never been into programming that much. So, small fish here :)

Share this post


Link to post
Share on other sites
1 hour ago, DavidLago said:

Actually I have more than 40 DCs, but I just want to test 5 of them, specifically. This "_AD_ListDomainControllers" function won't work with any parameters of filters, so, all of them will come to the array.

And why not deleting the 35 from array, where you know their is no need to control?

Share this post


Link to post
Share on other sites
Just now, AutoBert said:

And why not deleting the 35 from array, where you know their is no need to control?

Thought about doing this:

Dim $aArray = ["DC1", "DC2", "DC3", "DC4", "DC5"]

 


Just a server analyst that has never been into programming that much. So, small fish here :)

Share this post


Link to post
Share on other sites
1 minute ago, DavidLago said:

Thought about doing this:

Dim $aArray = ["DC1", "DC2", "DC3", "DC4", "DC5"]

 

seems this is the shorter way.

Share this post


Link to post
Share on other sites

Each time you call _Ad_Open, the function creates a "ADODB.Connection" object.

Maybe it's slow the first time, then faster next

Can you check for this ?

Local $hTimer1 = TimerInit()
ObjCreate("ADODB.Connection")
ConsoleWrite(TimerDiff($hTimer1) & @CRLF)

Local $hTimer2 = TimerInit()
ObjCreate("ADODB.Connection")
ConsoleWrite(TimerDiff($hTimer2) & @CRLF)

I cannot check it for now...

Share this post


Link to post
Share on other sites
On 09/09/2016 at 5:09 PM, jguinch said:

Each time you call _Ad_Open, the function creates a "ADODB.Connection" object.

Maybe it's slow the first time, then faster next

Can you check for this ?

Local $hTimer1 = TimerInit()
ObjCreate("ADODB.Connection")
ConsoleWrite(TimerDiff($hTimer1) & @CRLF)

Local $hTimer2 = TimerInit()
ObjCreate("ADODB.Connection")
ConsoleWrite(TimerDiff($hTimer2) & @CRLF)

I cannot check it for now...

Thanks jguinch. It's exactly what happens here.

The first one always gets a lot of delay.

I increased the number of tests to 5, and ran a lot of them. It also seems to keep getting faster every execution. Look at the console outputs:

EXEC1:

--> Press Ctrl+Alt+Break to Restart or Ctrl+Break to Stop
2.93141843646089
0.0276548909100084
0.0210975456426868
0.0196720358019648
0.00627224329917717

EXEC2:

--> Press Ctrl+Alt+Break to Restart or Ctrl+Break to Stop
2.26912656446141
0.0159657102160873
0.00912326298062133
0.00912326298062133
0.00570203936288833

EXEC3:

--> Press Ctrl+Alt+Break to Restart or Ctrl+Break to Stop
3.12699838660796
0.0290804007507305
0.0188167298975315
0.0153955062797985
0.0131146905346432

 

Maybe it's not a trustable test?

I'd like to see water's opinion on this too, since he was the one who came up with the UDF.


Just a server analyst that has never been into programming that much. So, small fish here :)

Share this post


Link to post
Share on other sites

We discussed a similar "problem" on the German forum.
It seems that on the first run it takes some time for Windows to load the needed modules.


My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2017-04-18 - Version 1.4.8.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2017-02-27 - Version 1.3.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites

I inserted the line "ObjCreate("ADODB.Connection")" before the script, and it didn't change the situation. The first one comes with a lot of delay.

So far, the only way I could come up with decent results was creating a _AD_OPEN line to "open the path" before the 'for' statement:

 

Global $time, $timediff
Dim $aArray = ["5", "MYSERVER109", "MYSERVER110", "MYSERVER111", "MYSERVER112", "MYSERVER113"]

; Function to "load up" the include
_AD_Open("", "", "MYSERVER109")
_AD_Close()

ObjCreate("ADODB.Connection")

For $i = 1 to 5 step 1
    Global $time = ""
    $time = Timerinit()
    _AD_Open("", "", $aArray[$i])
    _AD_Close()
    $timediff = TimerDiff($time)
    ConsoleWrite($aArray[$i] & "=" & $timediff & @CRLF)
Next

@water Do you think that _AD_OPEN could "simulate" some kind of authentication response?


Just a server analyst that has never been into programming that much. So, small fish here :)

Share this post


Link to post
Share on other sites

Maybe if you directly measure in function _AD_Open before and after

; ADO Open Method: http://msdn.microsoft.com/en-us/library/ms676505.aspx
    $__oAD_Connection.Open() ; Open connection to AD

 


My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2017-04-18 - Version 1.4.8.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2017-02-27 - Version 1.3.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites

Suggestion/workaround - test 6 DCs, with the first being one you DON'T want to measure.

 

Ie: DC75, DC1, DC2,DC3,DC4,DC5

That way the delay only affects a DC you don't care about.

Another option is to run the script 5 times, with a different DC in the first position each time, thus they all get affected by the slow connection equally (which could be important if the latency is what you're trying to measure).

 

1 person likes this

Share this post


Link to post
Share on other sites
3 hours ago, nikink said:

Suggestion/workaround - test 6 DCs, with the first being one you DON'T want to measure.

 

Ie: DC75, DC1, DC2,DC3,DC4,DC5

That way the delay only affects a DC you don't care about.

Another option is to run the script 5 times, with a different DC in the first position each time, thus they all get affected by the slow connection equally (which could be important if the latency is what you're trying to measure).

 

That's exactly what I'm doing, @nikink, though, you outta agree this is a great jury-rig :P

I got the script running and getting me results already. I would like to find a solution, though. Or at least understand that behavior.

1 person likes this

Just a server analyst that has never been into programming that much. So, small fish here :)

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

  • Similar Content

    • Realm
      By Realm
      After Several Minutes searching the forums for a simple solution to calculating for the Unix Time, as required for another project I am working on, I was astonished to not find one clean and universal solution. After looking over the helpfile, I noticed one simple solution given in the example with _DateDiff(). However it did not account for my current timezone or daylight savings time.
      Without further ado... This is my example of Calculating for a current Unix Time stamp or  seconds since Jan, 1st, 1970 00:00:00 GMT.
      This function will account for your timezone as well as for daylight savings time.
      Update: v0.3
      -Added Function to revert a Unix Time stamp into Date form.
      -Added parameter to original _GetUnixTime() allowing for a custom date since Jan 1st 1970 to be passed and converted to Unix Time.
      #include <Date.au3> #include <Array.au3> #include <Constants.au3> Local $iUnixTime1 = _GetUnixTime() MsgBox($MB_SYSTEMMODAL, "Unix Timestamp", "Seconds Since Jan, 1st, 1970 00:00:00 GMT" & @CRLF & $iUnixTime1) Local $sUnixDate1 = _GetDate_fromUnixTime($iUnixTime1) MsgBox($MB_SYSTEMMODAL, "Unix Timestamp", "Get Date from Unix Timestamp in Local Time" & @CRLF & $sUnixDate1) $sUnixDate1 = _GetDate_fromUnixTime($iUnixTime1, False) MsgBox($MB_SYSTEMMODAL, "Unix Timestamp", "Get Date from Unix Timestamp with $iReturnLocal = False which returns UTC Time" & @CRLF & $sUnixDate1) Local $iUnixTime2 = _GetUnixTime('2013/01/01 00:00:00') MsgBox($MB_SYSTEMMODAL, "Unix Timestamp", "Seconds since 2013/01/01 00:00:00" & @CRLF & $iUnixTime2) ; Get timestamp for input datetime (or current datetime). Func _GetUnixTime($sDate = 0);Date Format: 2013/01/01 00:00:00 ~ Year/Mo/Da Hr:Mi:Se Local $aSysTimeInfo = _Date_Time_GetTimeZoneInformation() Local $utcTime = "" If Not $sDate Then $sDate = _NowCalc() If Int(StringLeft($sDate, 4)) < 1970 Then Return "" If $aSysTimeInfo[0] = 2 Then ; if daylight saving time is active $utcTime = _DateAdd('n', $aSysTimeInfo[1] + $aSysTimeInfo[7], $sDate) ; account for time zone and daylight saving time Else $utcTime = _DateAdd('n', $aSysTimeInfo[1], $sDate) ; account for time zone EndIf Return _DateDiff('s', "1970/01/01 00:00:00", $utcTime) EndFunc ;==>_GetUnixTime ;$blTrim: Year in short format and no seconds. Func _GetDate_fromUnixTime($iUnixTime, $iReturnLocal = True) Local $aRet = 0, $aDate = 0 Local $aMonthNumberAbbrev[13] = ["", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] Local $timeAdj = 0 If Not $iReturnLocal Then Local $aSysTimeInfo = _Date_Time_GetTimeZoneInformation() Local $timeAdj = $aSysTimeInfo[1] * 60 If $aSysTimeInfo[0] = 2 Then $timeAdj += $aSysTimeInfo[7] * 60 EndIf $aRet = DllCall("msvcrt.dll", "str:cdecl", "ctime", "int*", $iUnixTime + $timeAdj ) If @error Or Not $aRet[0] Then Return "" $aDate = StringSplit(StringTrimRight($aRet[0], 1), " ", 2) Return $aDate[4] & "/" & StringFormat("%.2d", _ArraySearch($aMonthNumberAbbrev, $aDate[1])) & "/" & $aDate[2] & " " & $aDate[3] EndFunc ;==>_GetUnixDate Enjoy!
      Realm
      Update: >Added some functionality and a suggestion from FireFox
    • squirrelc0de
      By squirrelc0de
      Hi there, 

      I have a question about persistent drives and AD. 
      I am playing around with a script but I'm missing something. What i want to do is if a user is part of an OU, it will map a network drive and be persistent. However if a user is moved out of that OU, they will need to have the persistent drive removed. 

      I'm using the ad plugin script, and i can map the drives if a user is in a specific ou, but i cannot seem to delete the drive if the user is out of the OU. 

      Here's an example of code I'm using: 

       
      #Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_Compression=4 #AutoIt3Wrapper_Res_Fileversion=1.0.0 #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** #include <AD\AD.au3> func MapDrives() _AD_Open() if _AD_RecursiveIsMemberOf(OU) Then Mapdrive1() Elseif _AD_RecursiveIsMemberOf(different ou) drivemapdel EndIf _AD_Close() EndFunc Func MapDrive1() Drivemapdel ("Z:") DriveMapAdd ("Z:"."\\server\share",$DMA_PERSISTENT,0) EndFunc  
    • Simpel
      By Simpel
      Hi, I created a gui with date field but formatted as time in HH:mm. It always shows "now-time". Even if I try to set it with GUICtrlSetData.
      #include <DateTimeConstants.au3> #include <GUIConstantsEx.au3> #include <MsgBoxConstants.au3> Example() Func Example() GUICreate("My GUI get date", 200, 200, 800, 200) Local $idDate = GUICtrlCreateDate("", 20, 20, 100, 20, $DTS_TIMEFORMAT) ; to select a specific default format Local $sStyle = "HH:mm" ; Just display hours and minutes <<<<<<<<<<<<<<<<<<<<<<<<<<<< GUICtrlSendMsg($idDate, $DTM_SETFORMATW, 0, $sStyle) ConsoleWrite(GUICtrlRead($idDate) & @CRLF) GUICtrlSetData($idDate, "00:00") ConsoleWrite(GUICtrlRead($idDate) & @CRLF) GUISetState(@SW_SHOW) ; Loop until the user exits. While GUIGetMsg() <> $GUI_EVENT_CLOSE WEnd MsgBox($MB_SYSTEMMODAL, "Time", GUICtrlRead($idDate)) EndFunc ;==>Example How can I set the time field with another time and how can this field be set blank?
      Regards, Conrad
    • 31290
      By 31290
      Hi guys, 
      I'd like to write a piece of tool that would allow me to update a certain field in our Active Directory from a comma separated csv file composed like this:

      This file, automatically generated, can hold more than 10k lines.
      Thus, I need column A to be in one variable, column B in a second one and column C in a third one.
      I'm really missing this part as updating the AD is fairly easy once the 3 variable are populated. 
      I see things like this:
      Here's my attempts at the moment:
      #include <File.au3> #include <Array.au3> Global $csv_file = @DesktopDir & "\Book1.csv" Global $aRecords If Not _FileReadToArray($csv_file,$aRecords) Then MsgBox(4096,"Error", " Error reading log to Array error:" & @error) Exit EndIf For $x = 1 to $aRecords[0] Msgbox(0,'Record:' & $x, $aRecords[$x]) ; Shows the line that was read from file $csv_line_values = StringSplit($aRecords[$x], ",",1) ; Splits the line into 2 or more variables and puts them in an array ; _ArrayDisplay($csv_line_values) ; Shows what's in the array you just created. ; $csv_line_values[0] holds the number of elements in array ; $csv_line_values[1] holds the value ; $csv_line_values[2] holds the value ; etc Msgbox(0, 0, $csv_line_values[1]) Next Any help on this please? 
      Thanks in advance
      -31290-
    • MyEarth
      By MyEarth
      Hi guys
      I need to get time of different city, London, Jerusalem, Mosca and many others. My starting script:
      #include <Date.au3> Local $iUTC, $iHour, $iMinute, $iSecond $iUTC = _Date_Time_GetSystemTime() $iHour = DllStructGetData($iUTC, "Hour") $iMinute = DllStructGetData($iUTC, "Minute") $iSecond = DllStructGetData($iUTC, "Second") ConsoleWrite("+UTC: " & $iHour & ":" & $iMinute & ":" & $iSecond & @CRLF) My idea was start from UTC time and then add-remove hours. But what about the DST, Daylight Savings Time? How i can know if in a country is active or not? There is an API? Example with _Date_Time_GetTimeZoneInformation it will give the current time zone settings and not for other time zone. I don't have understand if is possible or not 
      On the help i have found SystemTimeToTzSpecificLocalTime but i don't have understand how to use for other time zone...
      Thanks