Jump to content

Active Directory UDF - Help & Support (III)


water
 Share

Recommended Posts

You could try to connect to Global Catalogue as described here.
When you run

$aDCs = _AD_ListDomainControllers(False, True)
_ArrayDisplay($aDCs)

you get list of DCs including the GC (Global Catalogue). Then use this information in _AD_Open to connect to the GC as described by the link above.

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 (NEW 2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki

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

Tutorials:
ADO - Wiki
WebDriver - Wiki

 

Link to comment
Share on other sites

15 minutes ago, water said:

You could try to connect to Global Catalogue as described here.
When you run

$aDCs = _AD_ListDomainControllers(False, True)
_ArrayDisplay($aDCs)

you get list of DCs including the GC (Global Catalogue). Then use this information in _AD_Open to connect to the GC as described by the link above.

Nice I'll try! Right now I'm in home office and need to use a vpn! If it fails I'll try into one of the branches or something! Again thanks for you time and help! :D

 

Link to comment
Share on other sites

2 hours ago, edumanilha said:

Nice I'll try! Right now I'm in home office and need to use a vpn! If it fails I'll try into one of the branches or something! Again thanks for you time and help! :D

 

I got this error
 

image.png.925c1061e6bd6b2cdee650955d3373ba.png

when I try to run this:

#include<AD.au3>

Local $iResult = _AD_Open()
Local $aDCs = _AD_ListDomainControllers(False, True)
For $iIndex = 1 to $aDCs[0][0]
   If $aDCs[$iIndex][6] = True Then ConsoleWrite("DC " & $aDCs[$iIndex][0] & " is a Global Catalog")
Next

_ArrayDisplay($aDCs)
_AD_Close()

 

Link to comment
Share on other sites

Can you please insert

_AD_ErrorNotify(2)

after _AD_Open and run the script again?
You will get a MsgBox explaining what causes the error.

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 (NEW 2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki

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

Tutorials:
ADO - Wiki
WebDriver - Wiki

 

Link to comment
Share on other sites

7 minutes ago, water said:

Can you please insert

_AD_ErrorNotify(2)

after _AD_Open and run the script again?
You will get a MsgBox explaining what causes the error.

Windescription = Non operational server...

Edited by edumanilha
Link to comment
Share on other sites

Could you please add the following function to your script and call _AD_ListDomainControllersEX instead of _AD_ListDomainControllers? The error should be gone.

; #FUNCTION# ====================================================================================================================
; Name...........: _AD_ListDomainControllers
; Description ...: Enumerates all Domain Controllers (returns information about: Domain Controller, site, subnet and Global Catalog).
; Syntax.........: _AD_ListDomainControllers([$bListRO = False[, $bListGC = False]])
; Parameters ....: $bListRO - [optional] If set to True only returns RODC (read only domain controllers) (default = False)
;                  $bListGC - [optional] If set to True queries the DC for a Global Catalog. Disabled for performance reasons (default = False)
; Return values .: Success - One-based two dimensional array with the following information:
;                  |0 - Domain Controller: Name
;                  |1 - Domain Controller: Distinguished Name (FQDN)
;                  |2 - Domain Controller: DNS host name
;                  |3 - Site: Name
;                  |4 - Site: Distinguished Name (FQDN)
;                  |5 - Site: List of subnets that can connect to the site using this DC in the format x.x.x.x/mask - multiple subnets are separated by comma
;                  |6 - Global Catalog: If $bListGC = True you get one of the following values:
;                       True if the DC is a Global Catalog, False if it is no GC, "" if RootDSE of the DC could not be accessed
;                  Failure - "", sets @error to:
;                  |1 - No Domain Controllers found. @extended is set to the error returned by LDAP
; Author ........: water (based on VB functions by Richard L. Mueller)
; Modified.......:
; Remarks .......: This function only lists writeable DCs (default). To list RODC (read only DCs) use parameter $bListRO
; Related .......:
; Link ..........: http://www.rlmueller.net/Enumerate%20DCs.htm
; Example .......: Yes
; ===============================================================================================================================
Func _AD_ListDomainControllersEX($bListRO = False, $bListGC = False)

    If $bListRO = Default Then $bListRO = False
    If $bListGC = Default Then $bListGC = False
    Local $oDC, $oSite, $oResult
    Local Const $NTDSDSA_OPT_IS_GC = 1
    $__oAD_Command.CommandText = "<LDAP://" & $sAD_HostServer & "/" & $sAD_Configuration & ">;(objectClass=nTDSDSA);ADsPath;subtree"
    If $bListRO Then $__oAD_Command.CommandText = "<LDAP://" & $sAD_HostServer & "/" & $sAD_Configuration & ">;(objectClass=nTDSDSARO);ADsPath;subtree"
    Local $oRecordSet = $__oAD_Command.Execute
    If @error Or Not IsObj($oRecordSet) Or $oRecordSet.RecordCount = 0 Then Return SetError(1, @error, "")
    ; The parent object of each object with objectClass=nTDSDSA is a Domain
    ; Controller. The parent of each Domain Controller is a "Servers"
    ; container, and the parent of this container is the "Site" container.
    $oRecordSet.MoveFirst
    Local $aResult[1][7], $iCount1 = 1, $aSubNet, $aTemp, $sTemp
    Do
        ReDim $aResult[$iCount1 + 1][7]
        $oResult = __AD_ObjGet($oRecordSet.Fields("AdsPath").Value)
        $oDC = __AD_ObjGet($oResult.Parent)
        $aResult[$iCount1][0] = $oDC.Get("Name")
        $aResult[$iCount1][1] = $oDC.serverReference
        $aResult[$iCount1][2] = $oDC.DNSHostName
        $oResult = __AD_ObjGet($oDC.Parent)
        $oSite = __AD_ObjGet($oResult.Parent)
        $aResult[$iCount1][3] = StringMid($oSite.Name, 4)
        $aResult[$iCount1][4] = $oSite.distinguishedName
        $aSubNet = $oSite.GetEx("siteObjectBL")
        For $iCount2 = 0 To UBound($aSubNet) - 1
            $aTemp = StringSplit($aSubNet[$iCount2], ",")
            $sTemp = StringMid($aTemp[1], 4)
            If $iCount2 = 0 Then
                $aResult[$iCount1][5] = $sTemp
            Else
                $aResult[$iCount1][5] = $aResult[$iCount1][5] & "," & $sTemp
            EndIf
        Next
        If $bListGC Then
            ; Is the DC a GC? Taken from: http://www.activexperts.com/activmonitor/windowsmanagement/adminscripts/computermanagement/ad/
            Local $oDCRootDSE = __AD_ObjGet("LDAP://" & $oDC.DNSHostName & "/rootDSE")
            If @error = 0 Then
                Local $sDsServiceDN = $oDCRootDSE.Get("dsServiceName")
                Local $oDsRoot = __AD_ObjGet("LDAP://" & $oDC.DNSHostName & "/" & $sDsServiceDN)
                Local $iDCOptions = $oDsRoot.Get("options")
                If BitAND($iDCOptions, $NTDSDSA_OPT_IS_GC) = 1 Then
                    $aResult[$iCount1][6] = True
                Else
                    $aResult[$iCount1][6] = False
                EndIf
            EndIf
        EndIf
        $oRecordSet.MoveNext
        $iCount1 += 1
    Until $oRecordSet.EOF
    $oRecordSet.Close
    $aResult[0][0] = UBound($aResult, 1) - 1
    $aResult[0][1] = UBound($aResult, 2)
    Return $aResult

EndFunc   ;==>_AD_ListDomainControllers

 

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 (NEW 2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki

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

Tutorials:
ADO - Wiki
WebDriver - Wiki

 

Link to comment
Share on other sites

20 minutes ago, water said:

Could you please add the following function to your script and call _AD_ListDomainControllersEX instead of _AD_ListDomainControllers? The error should be gone.

; #FUNCTION# ====================================================================================================================
; Name...........: _AD_ListDomainControllers
; Description ...: Enumerates all Domain Controllers (returns information about: Domain Controller, site, subnet and Global Catalog).
; Syntax.........: _AD_ListDomainControllers([$bListRO = False[, $bListGC = False]])
; Parameters ....: $bListRO - [optional] If set to True only returns RODC (read only domain controllers) (default = False)
;                  $bListGC - [optional] If set to True queries the DC for a Global Catalog. Disabled for performance reasons (default = False)
; Return values .: Success - One-based two dimensional array with the following information:
;                  |0 - Domain Controller: Name
;                  |1 - Domain Controller: Distinguished Name (FQDN)
;                  |2 - Domain Controller: DNS host name
;                  |3 - Site: Name
;                  |4 - Site: Distinguished Name (FQDN)
;                  |5 - Site: List of subnets that can connect to the site using this DC in the format x.x.x.x/mask - multiple subnets are separated by comma
;                  |6 - Global Catalog: If $bListGC = True you get one of the following values:
;                       True if the DC is a Global Catalog, False if it is no GC, "" if RootDSE of the DC could not be accessed
;                  Failure - "", sets @error to:
;                  |1 - No Domain Controllers found. @extended is set to the error returned by LDAP
; Author ........: water (based on VB functions by Richard L. Mueller)
; Modified.......:
; Remarks .......: This function only lists writeable DCs (default). To list RODC (read only DCs) use parameter $bListRO
; Related .......:
; Link ..........: http://www.rlmueller.net/Enumerate%20DCs.htm
; Example .......: Yes
; ===============================================================================================================================
Func _AD_ListDomainControllersEX($bListRO = False, $bListGC = False)

    If $bListRO = Default Then $bListRO = False
    If $bListGC = Default Then $bListGC = False
    Local $oDC, $oSite, $oResult
    Local Const $NTDSDSA_OPT_IS_GC = 1
    $__oAD_Command.CommandText = "<LDAP://" & $sAD_HostServer & "/" & $sAD_Configuration & ">;(objectClass=nTDSDSA);ADsPath;subtree"
    If $bListRO Then $__oAD_Command.CommandText = "<LDAP://" & $sAD_HostServer & "/" & $sAD_Configuration & ">;(objectClass=nTDSDSARO);ADsPath;subtree"
    Local $oRecordSet = $__oAD_Command.Execute
    If @error Or Not IsObj($oRecordSet) Or $oRecordSet.RecordCount = 0 Then Return SetError(1, @error, "")
    ; The parent object of each object with objectClass=nTDSDSA is a Domain
    ; Controller. The parent of each Domain Controller is a "Servers"
    ; container, and the parent of this container is the "Site" container.
    $oRecordSet.MoveFirst
    Local $aResult[1][7], $iCount1 = 1, $aSubNet, $aTemp, $sTemp
    Do
        ReDim $aResult[$iCount1 + 1][7]
        $oResult = __AD_ObjGet($oRecordSet.Fields("AdsPath").Value)
        $oDC = __AD_ObjGet($oResult.Parent)
        $aResult[$iCount1][0] = $oDC.Get("Name")
        $aResult[$iCount1][1] = $oDC.serverReference
        $aResult[$iCount1][2] = $oDC.DNSHostName
        $oResult = __AD_ObjGet($oDC.Parent)
        $oSite = __AD_ObjGet($oResult.Parent)
        $aResult[$iCount1][3] = StringMid($oSite.Name, 4)
        $aResult[$iCount1][4] = $oSite.distinguishedName
        $aSubNet = $oSite.GetEx("siteObjectBL")
        For $iCount2 = 0 To UBound($aSubNet) - 1
            $aTemp = StringSplit($aSubNet[$iCount2], ",")
            $sTemp = StringMid($aTemp[1], 4)
            If $iCount2 = 0 Then
                $aResult[$iCount1][5] = $sTemp
            Else
                $aResult[$iCount1][5] = $aResult[$iCount1][5] & "," & $sTemp
            EndIf
        Next
        If $bListGC Then
            ; Is the DC a GC? Taken from: http://www.activexperts.com/activmonitor/windowsmanagement/adminscripts/computermanagement/ad/
            Local $oDCRootDSE = __AD_ObjGet("LDAP://" & $oDC.DNSHostName & "/rootDSE")
            If @error = 0 Then
                Local $sDsServiceDN = $oDCRootDSE.Get("dsServiceName")
                Local $oDsRoot = __AD_ObjGet("LDAP://" & $oDC.DNSHostName & "/" & $sDsServiceDN)
                Local $iDCOptions = $oDsRoot.Get("options")
                If BitAND($iDCOptions, $NTDSDSA_OPT_IS_GC) = 1 Then
                    $aResult[$iCount1][6] = True
                Else
                    $aResult[$iCount1][6] = False
                EndIf
            EndIf
        EndIf
        $oRecordSet.MoveNext
        $iCount1 += 1
    Until $oRecordSet.EOF
    $oRecordSet.Close
    $aResult[0][0] = UBound($aResult, 1) - 1
    $aResult[0][1] = UBound($aResult, 2)
    Return $aResult

EndFunc   ;==>_AD_ListDomainControllers

 

It worked! I can see the servers now...Thanks!

Link to comment
Share on other sites

Fixed in the 1.5.0.1 version of the UDF which I uploaded today.

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 (NEW 2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki

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

Tutorials:
ADO - Wiki
WebDriver - Wiki

 

Link to comment
Share on other sites

  • 4 weeks later...

If you check the checkbox "User must change password at next logon" property pwdlastset is set to 0.
Function _AD_GetPasswordInfo returns an array with "1601/01/01 00:00:00" in element 8 when the password has never been set = User must change password at next logon
Function _AD_IsPasswordExpired returns 1 if the password of the user or computer account has expired (means password has expired or has never been set).

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 (NEW 2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki

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

Tutorials:
ADO - Wiki
WebDriver - Wiki

 

Link to comment
Share on other sites

3 minutes ago, water said:

If you check the checkbox "User must change password at next logon" property pwdlastset is set to 0.
Function _AD_GetPasswordInfo returns an array with "1601/01/01 00:00:00" in element 8 when the password has never been set = User must change password at next logon
Function _AD_IsPasswordExpired returns 1 if the password of the user or computer account has expired (means password has expired or has never been set).

thanks :) that's just what i needed

Link to comment
Share on other sites

Glad to be of service :)
N.B.: Please test your scripts to
make sure that they work as expected and that everything I posted above is true - didn't have a look at this part of the UDF for months ;)

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 (NEW 2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki

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

Tutorials:
ADO - Wiki
WebDriver - Wiki

 

Link to comment
Share on other sites

2 hours ago, water said:

Glad to be of service :)
N.B.: Please test your scripts to
make sure that they work as expected and that everything I posted above is true - didn't have a look at this part of the UDF for months ;)

Global $result = _AD_IsPasswordExpired()
MsgBox("","",$result)

_AD_IsPasswordExpired seems to return 0 whenever the checkbox is enabled or not

Link to comment
Share on other sites

How long did you wait between checking the box and running your script? Maybe it is an AD sync problem?

Edit: What's the value of @error when $result = 0?

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 (NEW 2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki

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

Tutorials:
ADO - Wiki
WebDriver - Wiki

 

Link to comment
Share on other sites

19 hours ago, water said:

How long did you wait between checking the box and running your script? Maybe it is an AD sync problem?

Edit: What's the value of @error when $result = 0?

the value of @error is also 0, it doesen't seem likely it's a sync issue.
the password for the user is still reset, and hasn't been changed, and the checkbox is enabled, but it still returns 0

Link to comment
Share on other sites

You could run _AD_GetObjectProperties for the user with the checkbox enabled, save the result, disable the checkbox and do the previous steps again.
By comparing the saved results we could see which property holds the "needs to change password on next logon".

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 (NEW 2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki

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

Tutorials:
ADO - Wiki
WebDriver - Wiki

 

Link to comment
Share on other sites

That solved the problem :)

 

the Attribute: pwnLastSet gets updated to 1601/01/01 00:00:00 when you check : User must change password at next logon.
However, I can't seem to grab the information, it returns nothing from the attribute:

$pwdLastSet = _AD_GetObjectAttribute($input, "pwdLastSet")

$pwdLastSet = _AD_GetObjectAttribute($input, "pwdLastSet")

 

Edited by legend
Link to comment
Share on other sites

What's the value of property pwdlastset?

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 (NEW 2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki

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

Tutorials:
ADO - Wiki
WebDriver - Wiki

 

Link to comment
Share on other sites

26 minutes ago, water said:

What's the value of property pwdlastset?

the value of pwdLastSet is 1601/01/01 00:00:00

2020-07-15_115923.png

 

If i type a wrong username, it fails, but if i try with a correct username, it just returns nothing, but doesen't fail.

 

EDIT: i got it to work :)

$aListProp = _AD_GetObjectProperties(@UserName, "pwdLastSet")
msgbox(0,"", $aListProp[1][1])

 

Edited by legend
Link to comment
Share on other sites

"Unfortunately" _AD_GetObjectProperties translates values into a readable format.
Could you please run the following modified version of _AD_GetObjectproperties? It displays the pwdlastset bigint as high and low before translating it to a readable format.
Both values should be 0.

Spoiler
#include <AD.au3>

; Open Connection to the Active Directory
_AD_Open()
If @error Then Exit MsgBox(16, "Active Directory Example Skript", "Function _AD_Open encountered a problem. @error = " & @error & ", @extended = " & @extended)

Global $sUser = @UserName
Global $aProperties = _AD_GetObjectPropertiesEX($sUser, "pwdlastset")
_ArrayDisplay($aProperties, "Active Directory Functions - Properties for user '" & $sUser & "'")

; Close Connection to the Active Directory
_AD_Close()

Func _AD_GetObjectPropertiesEX($vObject = @UserName, $sProperties = "", $bSort = True)

    If $vObject = Default Then $vObject = @UserName
    If $sProperties = Default Then $sProperties = ""
    If $bSort = Default Then $bSort = True
    Local $aObjectProperties[10000][2], $oObject
    Local $oProperty, $oPropertyEntry, $sPropertyName, $oValue, $iPropertyRecord = 0, $xAD_Dummy
    Local $aSAMAccountType[12][2] = [["DOMAIN_OBJECT", 0x0], ["GROUP_OBJECT", 0x10000000], ["NON_SECURITY_GROUP_OBJECT", 0x10000001], _
            ["ALIAS_OBJECT", 0x20000000], ["NON_SECURITY_ALIAS_OBJECT", 0x20000001], ["USER_OBJECT", 0x30000000], ["NORMAL_USER_ACCOUNT", 0x30000000], _
            ["MACHINE_ACCOUNT", 0x30000001], ["TRUST_ACCOUNT", 0x30000002], ["APP_BASIC_GROUP", 0x40000000], ["APP_QUERY_GROUP", 0x40000001], _
            ["ACCOUNT_TYPE_MAX", 0x7fffffff]]
    Local $aUAC[21][2] = [[0x00000001, "SCRIPT"], [0x00000002, "ACCOUNTDISABLE"], [0x00000008, "HOMEDIR_REQUIRED"], [0x00000010, "LOCKOUT"], [0x00000020, "PASSWD_NOTREQD"], _
            [0x00000040, "PASSWD_CANT_CHANGE"], [0x00000080, "ENCRYPTED_TEXT_PASSWORD_ALLOWED"], [0x00000100, "TEMP_DUPLICATE_ACCOUNT"], [0x00000200, "NORMAL_ACCOUNT"], _
            [0x00000800, "INTERDOMAIN_TRUST_ACCOUNT"], [0x00001000, "WORKSTATION_TRUST_ACCOUNT"], [0x00002000, "SERVER_TRUST_ACCOUNT"], [0x00010000, "DONT_EXPIRE_PASSWD"], _
            [0x00020000, "MNS_LOGON_ACCOUNT"], [0x00040000, "SMARTCARD_REQUIRED"], [0x00080000, "TRUSTED_FOR_DELEGATION"], [0x00100000, "NOT_DELEGATED"], _
            [0x00200000, "USE_DES_KEY_ONLY"], [0x00400000, "DONT_REQUIRE_PREAUTH"], [0x00800000, "PASSWORD_EXPIRED"], [0x01000000, "TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION"]]
    If Not IsObj($vObject) Then
        If StringLeft($vObject, 7) <> "LDAP://" Then ; No ADsPath
            If _AD_ObjectExists($vObject) = 0 Then Return SetError(1, 0, "")
            Local $sProperty = "sAMAccountName"
            If StringMid($vObject, 3, 1) = "=" Then $sProperty = "distinguishedName" ; FQDN provided
            $__oAD_Command.CommandText = "<LDAP://" & $sAD_HostServer & "/" & $sAD_DNSDomain & ">;(" & $sProperty & "=" & $vObject & ");ADsPath;subtree"
            Local $oRecordSet = $__oAD_Command.Execute ; Retrieve the ADsPath for the object
            If @error Or Not IsObj($oRecordSet) Then Return SetError(3, @error, "")
            $vObject = $oRecordSet.fields(0).Value
        EndIf
        $oObject = __AD_ObjGet($vObject) ; Retrieve the COM Object
    Else
        $oObject = $vObject
    EndIf
    If $sProperties = "" Then
        $oObject.GetInfo() ; Refresh values of all properties in the property cache of the ADSI object
    Else
        Local $aProperties = StringSplit($sProperties, ",", $STR_NOCOUNT)
        $oObject.GetInfoEX($aProperties, 0) ; Refresh values of the selected properties in the property cache of the ADSI object
    EndIf
    Local $iPropertyCount = $oObject.PropertyCount()
    For $iCurrentProperty = 0 To $iPropertyCount - 1
        $oProperty = $oObject.Item($iCurrentProperty)
        $oPropertyEntry = $oObject.GetPropertyItem($oProperty.Name, $ADSTYPE_UNKNOWN)
        $sPropertyName = $oProperty.Name
        If Not IsObj($oPropertyEntry) Then Return SetError(2, 0, $sPropertyName)
        For $vPropertyValue In $oPropertyEntry.Values
            $iPropertyRecord = $iPropertyRecord + 1
            $aObjectProperties[$iPropertyRecord][0] = $sPropertyName
            Switch $oProperty.ADsType
                Case $ADSTYPE_DN_STRING
                    $aObjectProperties[$iPropertyRecord][1] = $vPropertyValue.DNString
                Case $ADSTYPE_CASE_IGNORE_STRING
                    $aObjectProperties[$iPropertyRecord][1] = $vPropertyValue.CaseIgnoreString
                Case $ADSTYPE_CASE_EXACT_STRING
                    $aObjectProperties[$iPropertyRecord][1] = $vPropertyValue.CaseExactString
                Case $ADSTYPE_NUMERIC_STRING
                    $aObjectProperties[$iPropertyRecord][1] = $vPropertyValue.NumericString
                Case $ADSTYPE_PRINTABLE_STRING
                    $aObjectProperties[$iPropertyRecord][1] = $vPropertyValue.PrintableString
                Case $ADSTYPE_INTEGER
                    If $sPropertyName = "sAMAccountType" Then
                        For $iCount4 = 0 To UBound($aSAMAccountType) - 1
                            If $vPropertyValue.Integer = $aSAMAccountType[$iCount4][1] Then
                                $aObjectProperties[$iPropertyRecord][1] = $aSAMAccountType[$iCount4][0]
                                ExitLoop
                            EndIf
                        Next
                    ElseIf $sPropertyName = "userAccountControl" Then
                        $aObjectProperties[$iPropertyRecord][1] = $vPropertyValue.Integer & " = "
                        For $iCount4 = 0 To UBound($aUAC) - 1
                            If BitAND($vPropertyValue.Integer, $aUAC[$iCount4][0]) = $aUAC[$iCount4][0] Then
                                $aObjectProperties[$iPropertyRecord][1] &= $aUAC[$iCount4][1] & " - "
                            EndIf
                        Next
                        If StringRight($aObjectProperties[$iPropertyRecord][1], 3) = " - " Then $aObjectProperties[$iPropertyRecord][1] = StringTrimRight($aObjectProperties[$iPropertyRecord][1], 3)
                    Else
                        $aObjectProperties[$iPropertyRecord][1] = $vPropertyValue.Integer
                    EndIf
                Case $ADSTYPE_LARGE_INTEGER
                    If $sPropertyName = "pwdLastSet" Then
                        MsgBox(0, "PwdLastSet", "Low: " & $vPropertyValue.LargeInteger.LowPart & ", High: " & $vPropertyValue.LargeInteger.HighPart)
                        $aObjectProperties[$iPropertyRecord][1] = __AD_LargeInt2DateString($vPropertyValue.LargeInteger.LowPart, $vPropertyValue.LargeInteger.HighPart)
                    ElseIf $sPropertyName = "accountExpires" Or $sPropertyName = "lastLogonTimestamp" Or $sPropertyName = "badPasswordTime" Or $sPropertyName = "lastLogon" Or _
                            $sPropertyName = "lockoutTime" Or $sPropertyName = "ms-Mcs-AdmPwdExpirationTime" Or $sPropertyName = "MSDS-UserPasswordExpiryTimeComputed" Then
                        $aObjectProperties[$iPropertyRecord][1] = __AD_LargeInt2DateString($vPropertyValue.LargeInteger.LowPart, $vPropertyValue.LargeInteger.HighPart)
                    Else
                        $aObjectProperties[$iPropertyRecord][1] = __AD_LargeInt2Double($vPropertyValue.LargeInteger.LowPart, $vPropertyValue.LargeInteger.HighPart)
                    EndIf
                Case $ADSTYPE_OCTET_STRING
                    $xAD_Dummy = DllStructCreate("byte[56]")
                    DllStructSetData($xAD_Dummy, 1, $vPropertyValue.OctetString)
                    ; objectSID etc. See: http://msdn.microsoft.com/en-us/library/aa379597(VS.85).aspx
                    ; objectGUID etc. See: http://www.autoitscript.com/forum/index.php?showtopic=106163&view=findpost&p=767558
                    If _Security__IsValidSid(DllStructGetPtr($xAD_Dummy)) Then
                        $aObjectProperties[$iPropertyRecord][1] = _Security__SidToStringSid(DllStructGetPtr($xAD_Dummy)) ; SID
                    Else
                        $aObjectProperties[$iPropertyRecord][1] = _WinAPI_StringFromGUID(DllStructGetPtr($xAD_Dummy)) ; GUID
                    EndIf
                Case $ADSTYPE_UTC_TIME
                    $aObjectProperties[$iPropertyRecord][1] = StringRegExpReplace($vPropertyValue.UTCTime, "(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})", "$1/$2/$3 $4:$5:$6") ; YYYY/MM/DD HH:MM:SS
                Case $ADSTYPE_BOOLEAN
                    If $vPropertyValue.Boolean = 0 Then
                        $aObjectProperties[$iPropertyRecord][1] = "False"
                    Else
                        $aObjectProperties[$iPropertyRecord][1] = "True"
                    EndIf
                Case $ADSTYPE_NT_SECURITY_DESCRIPTOR
                    $oValue = $vPropertyValue.SecurityDescriptor
                    $aObjectProperties[$iPropertyRecord][1] = "Control:" & $oValue.Control & ", " & _
                            "Group:" & $oValue.Group & ", " & _
                            "Owner:" & $oValue.Owner & ", " & _
                            "Revision:" & $oValue.Revision
                Case Else
                    $aObjectProperties[$iPropertyRecord][1] = "Has the unknown ADsType: " & $oProperty.ADsType
            EndSwitch
        Next
    Next
    ReDim $aObjectProperties[$iPropertyRecord + 1][2]
    $aObjectProperties[0][0] = $iPropertyRecord
    $aObjectProperties[0][1] = 2
    If $bSort And $iPropertyRecord > 1 Then _ArraySort($aObjectProperties, 0, 1) ; Only sort if flag is set and array contains > 1 records
    Return $aObjectProperties

EndFunc   ;==>_AD_GetObjectProperties

 

 

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 (NEW 2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki

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

Tutorials:
ADO - Wiki
WebDriver - Wiki

 

Link to comment
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
 Share

×
×
  • Create New...