Jump to content

Active Directory UDF (II)


water
 Share

Recommended Posts

:)

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

  • 9 months later...

Hello,

To begin with I have been using the UDF for several years, it is great.

However, I have two problems:

1- See the screenshot above, it seems that there is a bad recognition when the names include a -

Everything that is in the OU "Et_2" is found by mistake in the OU "Et_-2".


2- I also have names with spaces. I saw the remark on this subject "If an OU contains spaces the sorting is wrong and might lead to problems in further processing.
Please have a look at http://www.autoitscript.com/forum/topic/106163-active-directory-udf/page__view__findpost__p__943892 "

But I admit that I did not quite understand the solution that must be put in place to correct this, can you give me more specific information?

Thank you in advance for your help.

Bug AD et GAIA.png

Edited by mprudhomme
Link to comment
Share on other sites

I have taken and added the modifications made by trancexx (they are quite old and I'm sure the Array-functions have evolved over time).
You get the array and then the function displays the empty GUI. If the content of the array is correct, you can remove the lines makred with ("; <== Remove if the Treeview should be generated") in function _AD_GetOUTreeView.

Spoiler

 

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_UseX64=n
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
#include <AD.au3>
#include <Excel.au3>
#include <TreeviewConstants.au3>
#include <WindowsConstants.au3>
#include <GUIConstants.au3>
#include <GuiTreeView.au3>

Global $sTitle = "Active Direcory OU Treeview"
#Region ### START Koda GUI section ### Form=
Global $hMain = GUICreate($sTitle, 743, 683, -1, -1)
Global $idTree = GUICtrlCreateTreeView(6, 6, 600, 666, -1, $WS_EX_CLIENTEDGE)
Global $idExit = GUICtrlCreateButton("Exit", 624, 8, 97, 33)
Global $idExpand = GUICtrlCreateButton("Expand all", 624, 56, 97, 33)
Global $idCollapse = GUICtrlCreateButton("Collapse all", 624, 104, 97, 33)
Global $idSelect = GUICtrlCreateButton("Select OU", 624, 152, 97, 33)
Global $idExport = GUICtrlCreateButton("Export -> Excel", 624, 200, 97, 33)
Global $idProgress = GUICtrlCreateProgress(624, 248, 97, 20)
GUISetState(@SW_SHOW)
#EndRegion ### END Koda GUI section ###
Global $__aTreeView
;------------------------------
; Make your changes below
;------------------------------
Global $sOU = "" ; FQDN of the OU where to start
Global $sCategory = "computer" ; Category to select when counts should be displayed or full LDAP query
Global $sText = " (Computer: %)" ; Text to use for the counts to display. % is replaced with the count
Global $iScope = 1 ; Scope for the LDAP search to calculate the count. 1 = Only the OU, 2 = OU + sub-OUs
Global $bCount = True ; True = Display the object count right to the OU
Global $bDisplay = True ; True = Display objects in the OU as well (selection = $sCategory)
Global $iTimerTotal, $iTimerOU, $iTimerGroups, $iTimerTV, $iTimerPerm = 0, $iTimerLoop = 0
Global $iCountSamFQDN = 0, $iCountLoop = 0
Global $oDict = ObjCreate("Scripting.Dictionary")
;------------------------------
; Make your changes above
;------------------------------
$iTimerTotal = TimerInit()
Global $aTreeView = _AD_GetOUTreeView($sOU, $idTree, False, $bCount, $bDisplay, $sCategory, $sText, $iScope, $idProgress)
If @error <> 0 Then MsgBox(16, "Active Direcory OU Treeview", "Error creating list of OUs starting with '" & $sOU & "'." & @CRLF & _
        "Error returned by function _AD_GetALLOUs: @error = " & @error & ", @extended =  " & @extended)
Global $sResult = StringFormat("Total: " & "%.2f" & "sec" & @CRLF & _
        "Get OUs: " & "%.2f sec" & @CRLF & _
        "Get Groups: " & "%.2f sec" & @CRLF & _
        "Check Permissions: " & "%.2f sec" & @CRLF & _
        "  SamToFQDN called: " & "%.0i times" & @CRLF & _
        "  Time in Loop: " & "%.2f sec" & @CRLF & _
        "  Count Loop: " & "%.0i times" & @CRLF & _
        "Display TreeView: " & "%.2f sec", _
        TimerDiff($iTimerTotal) / 1000, $iTimerOU / 1000, $iTimerGroups / 1000, $iTimerPerm / 1000, $iCountSamFQDN, $iTimerLoop / 1000, $iCountLoop, $iTimerTV / 1000)
MsgBox(0, "Timers and Counters", $sResult)
; Sleep(1000)
GUICtrlDelete($idProgress)
While 1
    $Msg = GUIGetMsg()
    Switch $Msg
        Case $GUI_EVENT_CLOSE, $idExit
            Exit
        Case $idExpand
            _GUICtrlTreeView_Expand($idTree)
        Case $idCollapse
            _GUICtrlTreeView_Expand($idTree, 0, False)
        Case $idSelect
            $hSelection = _GUICtrlTreeView_GetSelection($idTree)
            $sSelection = _GUICtrlTreeView_GetText($idTree, $hSelection)
            For $i = 1 To $aTreeView[0][0]
                If $hSelection = $aTreeView[$i][2] Then ExitLoop
            Next
            $sOU = $aTreeView[$i][1]
            MsgBox(64, $sTitle & " - Selected OU", "Name: " & $sSelection & @CRLF & "FQDN: " & $sOU)
        Case $idExport
            If IsArray($__aTreeView) Then
                Global $aExcelData[$__aTreeView[0][0]][99]
                For $i = 1 To $__aTreeView[0][0]
                    $iPos = StringInStr($__aTreeView[$i][0], "#")
                    $aExcelData[$i - 1][$iPos - 1] = StringMid($__aTreeView[$i][0], $iPos + 1)
                Next
                $oExcel = _Excel_Open()
                $oWorkbook = _Excel_BookNew($oExcel)
                _Excel_RangeWrite($oWorkbook, Default, $aExcelData)
                _Excel_Close($oExcel)
            EndIf
    EndSwitch
WEnd

; #FUNCTION# ====================================================================================================================
; Name...........: _AD_GetOUTreeView
; Description ...: Fills a given TreeView control with all OUs starting with a given OU.
; Syntax.........: _AD_GetOUTreeView($sOU, $idTreeView[, $bIsADOpen = False[, $bCount = False[, $bDisplay = False[, $sCategory = ""[, $sText = " (%)"[, $iSearchScope = 1[, $idProgress = Default]]]]]]])
; Parameters ....: $sOU          - FQDN of the OU where to start. "" displays all OUs
;                  $idTreeView   - Handle of the TreeView where the OUs will be displayed. Has to be created in advance
;                  $bIsADOpen    - Optional: Pass as True if the connection to the AD has already been made by the calling script (default = False)
;                  $bCount       - Optional: True will display the count of objects in the OU right to the OU name (default = False)
;                                  The LDAP query to determine the count is built from $sCategory
;                  $bDisplay     - Optional: True will display the objects in the OU below the OU itself (default = False)
;                  $sCategory    - Optional: Category to search for or the complete LDAP search string e.g. "computer" and "(objectcategory=computer)" are equivalent
;                                  The number of found objects is added to the OUs name (default = "" = don't count objects)
;                  $sText        - Optional: Text to display the count. Must contain a % which will be replaced by the actual number (default = " (%)")
;                  $iSearchScope - Optional: Search scope for function _AD_GetObjectsInOU: 0 = base, 1 = one-level, 2 = sub-tree (default = 1)
;                  $idProgress   - Optional: ControlID of a progress bar to show during creation of the TreeView (default = Default)
; Return values .: Success - 1
;                  Failure - Returns 0 and sets @error:
;                  |x - Function _AD_Open or _AD_GetAllOUs failed. @error and @extended are set by _AD_Open or _AD_GetAllOUs
; Author ........: water based on code by ReFran - http://www.autoitscript.com/forum/topic/84119-treeview-read-to-from-file
; Modified.......: water including ideas by HaeMHuK
; Remarks .......: Use $iSearchScope = 1 to get the number of objects of a single OU.
;                  Use $iSearchScope = 2 to get the number of objects in the OU plus all sub-OUs.
; Related .......:
; Link ..........:
; Example .......:
; ===============================================================================================================================
Func _AD_GetOUTreeView($sOU, $idTreeView, $bIsADOpen = False, $bCount = False, $bDisplay = False, $sCategory = "", $sText = " (%)", $iSearchScope = 1, $idProgress = Default)

    Local $iCount, $aObjects
    If $bIsADOpen = False Then
        _AD_Open()
        If @error Then Return SetError(@error, @extended, 0)
    EndIf
    $sSeparator = "\"
    $iTimerOU = TimerInit()
    Local $aOUs = _AD_GetAllOUs($sOU, $sSeparator)
    If @error <> 0 Then Return SetError(@error, @extended, 0)
    _ArrayDisplay($aOUs) ; <== Remove if the Treeview should be generated
    Return            ; <== Remove if the Treeview should be generated
    $iTimerOU = TimerDiff($iTimerOU)
    Global $__aTreeView[$aOUs[0][0] + 1][3] = [[$aOUs[0][0], 3]]
    Local $aResult = $__aTreeView
    Local $iIndexTV = 0, $sIgnoreOU = ""
    $iTimerGroups = TimerInit()
    Local $aMemberOf = _AD_GetUserGroups(@UserName) ; Dummy can be removed
    $iTimerGroups = TimerDiff($iTimerGroups)
    For $i = 1 To $aOUs[0][0]
        If $idProgress <> Default Then GUICtrlSetData($idProgress, $i * 100 / $aOUs[0][0] / 2) ; 50 of the progress by processing the OUs
        If $sIgnoreOU = "" Or ($sIgnoreOU <> "" And StringInStr($aOUs[$i][1], $sIgnoreOU, -1) = 0) Then ; OU to ignore if not set or OU to ignore is set and entry to check isn't a sub-OU of the ignored OU then check permissions
            If _AD_HasRequiredRights__GivenMembers($aOUs[$i][1], 0, @UserName, $aMemberOf) = 0 Then ; User doesn't have needed permissions. Ignore this OU and all sub-OUs
                $sIgnoreOU = $aOUs[$i][1]
            Else
                $sIgnoreOU = ""
            EndIf
        EndIf
        If $sIgnoreOU = "" Then
            $iIndexTV = $iIndexTV + 1
            $aTemp = StringSplit($aOUs[$i][0], $sSeparator)
            $__aTreeView[$iIndexTV][0] = StringFormat("%" & $aTemp[0] - 1 & "s", "") & "#" & $aTemp[$aTemp[0]]
            $__aTreeView[$iIndexTV][1] = $aOUs[$i][1]
        EndIf
    Next
    ReDim $__aTreeView[$iIndexTV + 1][3]
    $__aTreeView[0][0] = $iIndexTV
    $iTimerTV = TimerInit()
    _GUICtrlTreeView_BeginUpdate($idTreeView)
    Local $ah[50], $sLDAPString
    If $sCategory <> "" And StringIsAlNum($sCategory) Then
        $sLDAPString = "(objectcategory=" & $sCategory & ")"
    Else
        $sLDAPString = $sCategory
    EndIf
    $iOutIndex = 0
    For $iIndex = 1 To $__aTreeView[0][0]
        If $idProgress <> Default Then GUICtrlSetData($idProgress, 50 + $iIndex * 100 / $__aTreeView[0][0] / 2) ; 50 of the progress by processing the result
        $iOutIndex += 1
        $aObjects = ""
        $sLine = StringSplit(StringStripCR($__aTreeView[$iIndex][0]), @TAB)
        $iLevel = StringInStr($sLine[1], "#")
        If $iLevel = 0 Then ExitLoop
        If ($bCount Or $bDisplay) And $sLDAPString <> "" Then
            If $bDisplay Then
                $aObjects = _AD_GetObjectsInOU($__aTreeView[$iIndex][1], $sLDAPString, 1, "samaccountname,distinguishedname", "", False)
                If @error Then
                    $iCount = 0
                Else
                    $iCount = $aObjects[0][0]
                EndIf
            Else
                $iCount = _AD_GetObjectsInOU($__aTreeView[$iIndex][1], $sLDAPString, $iSearchScope, "samaccountname,distinguishedname", "", True)
            EndIf
        EndIf
        $sTemp = ""
        If $bCount And $sLDAPString <> "" Then $sTemp = StringReplace($sText, "%", $iCount)
        If $iLevel = 1 Then
            $ah[$iLevel] = _GUICtrlTreeView_Add($idTreeView, 0, StringMid($sLine[1], $iLevel + 1) & $sTemp)
        Else
            $ah[$iLevel] = _GUICtrlTreeView_AddChild($idTreeView, $ah[$iLevel - 1], StringMid($sLine[1], $iLevel + 1) & $sTemp)
        EndIf
        $aResult[$iOutIndex][0] = $__aTreeView[$iIndex][0]
        $aResult[$iOutIndex][1] = $__aTreeView[$iIndex][1]
        $aResult[$iOutIndex][2] = $ah[$iLevel]
        ; Add the objects of the OU to the TreeView
        If IsArray($aObjects) Then
            ReDim $aResult[UBound($aResult, 1) + $aObjects[0][0]][UBound($aResult, 2)]
            For $iIndex2 = 1 To $aObjects[0][0]
                $iOutIndex += 1
                If StringRight($aObjects[$iIndex2][0], 1) = "$" Then $aObjects[$iIndex2][0] = StringLeft($aObjects[$iIndex2][0], StringLen($aObjects[$iIndex2][0]) - 1)
                $aResult[$iOutIndex][0] = $aObjects[$iIndex2][0]
                $aResult[$iOutIndex][1] = $aObjects[$iIndex2][1]
                $aResult[$iOutIndex][2] = _GUICtrlTreeView_AddChild($idTreeView, $ah[$iLevel], $aObjects[$iIndex2][0])
            Next
        EndIf
    Next
    If $bIsADOpen = False Then _AD_Close()
    _GUICtrlTreeView_EndUpdate($idTreeView)
    $aResult[0][0] = UBound($aResult, 1) - 1
    $aResult[0][1] = UBound($aResult, 2)
    $iTimerTV = TimerDiff($iTimerTV)
    Return $aResult

EndFunc   ;==>_AD_GetOUTreeView

Func _AD_HasRequiredRights__GivenMembers($sAD_Object, $iAD_Right = 983551, $sAD_User = @UserName, $aAD_MemberOf = "")
    Local $iPerm = TimerInit()
    Local $iLoop = TimerInit()
    If StringMid($sAD_Object, 3, 1) <> "=" Then $sAD_Object = _AD_SamAccountNameToFQDN($sAD_Object) ; sAMAccountName provided
    Local $aAD_TrusteeArray, $sAD_TrusteeGroup, $sAD_TrusteeArrayFQDN
    Local $oAD_Object = __AD_ObjGet("LDAP://" & $sAD_HostServer & "/" & $sAD_Object)
    If IsObj($oAD_Object) Then
        Local $oAD_Security = $oAD_Object.Get("ntSecurityDescriptor")
        Local $oAD_DACL = $oAD_Security.DiscretionaryAcl
        For $oAD_ACE In $oAD_DACL
            If BitAND($oAD_ACE.AccessMask, $iAD_Right) <> $iAD_Right Then ContinueLoop
            $aAD_TrusteeArray = StringSplit($oAD_ACE.Trustee, "\")
            $sAD_TrusteeGroup = "CN=" & $aAD_TrusteeArray[$aAD_TrusteeArray[0]] & ","
            If $aAD_TrusteeArray[0] = 2 Then
                If $aAD_TrusteeArray[2] = $sAD_User And BitAND($oAD_ACE.AccessMask, $iAD_Right) = $iAD_Right Then Return 1
                ; Check if the entry exists in the Dictionary
                If $oDict.Exists($aAD_TrusteeArray[2]) Then
                    $sAD_TrusteeArrayFQDN = $oDict.Item($aAD_TrusteeArray[2])
                Else
                    $iCountSamFQDN = $iCountSamFQDN + 1
                    $sAD_TrusteeArrayFQDN = _AD_SamAccountNameToFQDN($aAD_TrusteeArray[2])
                    $oDict.Add($aAD_TrusteeArray[2], $sAD_TrusteeArrayFQDN)
                EndIf
            EndIf
            $iLoop = TimerInit()
            For $iCount1 = 0 To UBound($aAD_MemberOf) - 1
                $iCountLoop = $iCountLoop + 1
                If StringInStr($aAD_MemberOf[$iCount1], $sAD_TrusteeArrayFQDN) Then
                    $iTimerPerm = $iTimerPerm + TimerDiff($iPerm)
                    Return 1
                ElseIf StringInStr($aAD_MemberOf[$iCount1], $sAD_TrusteeGroup) Then
                    $iTimerPerm = $iTimerPerm + TimerDiff($iPerm)
                    Return 1
                EndIf
            Next
            $iTimerLoop = $iTimerLoop + TimerDiff($iLoop)
        Next
    EndIf
    $iTimerPerm = $iTimerPerm + TimerDiff($iPerm)
    Return 1 ; 1: Test. Change to 0 for production
EndFunc   ;==>_AD_HasRequiredRights__GivenMembers

; #FUNCTION# ====================================================================================================================
; Name...........: _AD_GetAllOUs
; Description ...: Retrieves an array of OUs. The paths are separated by the '\' character.
; Syntax.........: _AD_GetAllOUs([$sRoot = ""[, $sSeparator = "\"[, $iSelect = 0[, $iSearchScope = 2]]]])
; Parameters ....: $sRoot      - [optional] OU (FQDN) where to start in the AD tree (default = "", equals "start at the AD root")
;                  $sSeparator - [optional] Single character to separate the OU names (default = "\")
;                  $iSelect    - [optional] Which objects should be returned in the result (default = 0)
;                  |0 - Return OUs (Organizational Units) (default)
;                  |1 - Return CNs (Containers)
;                  |2 - Return OUs + CNs
;                  $iSearchScope - [optional] 0 = base, 1 = one-level, 2 = sub-tree (default)
; Return values .: Success - One-based two dimensional array of OUs starting with the given OU. The paths are separated by "\"
;                  |0 - ... \name of grandfather OU\name of father OU\name of son OU
;                  |1 - Distinguished Name (FQDN) of the son OU
;                  Failure - "", sets @error to:
;                  |1 - No OUs found
;                  |2 - Specified $sRoot does not exist
;                  |3 - $iSelect is not an integer or < 0 or > 2
; Author ........: Jonathan Clelland
; Modified.......: water
; Remarks .......: If an OU contains spaces the sorting is wrong and might lead to problems in further processing.
;                  Please have a look at http://www.autoitscript.com/forum/topic/106163-active-directory-udf/page__view__findpost__p__943892
; Related .......: _AD_GetObjectsInOU
; Link ..........:
; Example .......: Yes
; ===============================================================================================================================
Func _AD_GetAllOUsEX($sRoot = "", $sSeparator = "\", $iSelect = 0, $iSearchScope = 2)

    If $sRoot = Default Then $sRoot = ""
    If $sSeparator = Default Then $sSeparator = "\"
    If $iSelect = Default Then $iSelect = 0
    If $iSearchScope = Default Then $iSearchScope = 2
    If $sRoot = "" Then
        $sRoot = $sAD_DNSDomain
    Else
        If _AD_ObjectExists($sRoot, "distinguishedName") = 0 Then Return SetError(2, 0, "")
    EndIf
    If Not IsInt($iSelect) Or $iSelect < 0 Or $iSelect > 2 Then Return SetError(3, 0, "")
    If $sSeparator <= " " Or StringLen($sSeparator) > 1 Then $sSeparator = "\"
    $__oAD_Command.Properties("Searchscope") = $iSearchScope
    $__oAD_Command.CommandText = "<LDAP://" & $sAD_HostServer & "/" & $sRoot & ">;"
    Switch $iSelect
        Case 0
            $__oAD_Command.CommandText = $__oAD_Command.CommandText & "(objectCategory=organizationalUnit);distinguishedName"
        Case 1
            $__oAD_Command.CommandText = $__oAD_Command.CommandText & "(objectCategory=container);distinguishedName"
        Case 2
            $__oAD_Command.CommandText = $__oAD_Command.CommandText & "(|(objectCategory=organizationalUnit)(objectCategory=container));distinguishedName"
    EndSwitch
    Local $oRecordSet = $__oAD_Command.Execute
    Local $iCount1 = $oRecordSet.RecordCount
    If $iCount1 = 0 Then Return SetError(1, 0, "")
    Local $aOUs[$iCount1 + 1][2]
    Local $iCount2 = 1, $aTempOU
    $oRecordSet.MoveFirst
    Do
        $aOUs[$iCount2][1] = $oRecordSet.Fields("distinguishedName").Value
        $aOUs[$iCount2][0] = "," & StringTrimRight($aOUs[$iCount2][1], StringLen($sAD_DNSDomain) + 1)
        $aTempOU = StringSplit($aOUs[$iCount2][0], "," & StringLeft($aOUs[$iCount2][1], 3), 1) ; Split at ",OU=" or ",CN="
        _ArrayReverseEX($aTempOU)
        $aOUs[$iCount2][0] = StringTrimRight(_ArrayToString($aTempOU, $sSeparator), 3)
        $iCount2 += 1
        $oRecordSet.MoveNext
    Until $oRecordSet.EOF
    _ArraySortEX($aOUs)
    $aOUs[0][0] = UBound($aOUs, 1) - 1
    $aOUs[0][1] = 2
    Return $aOUs

EndFunc   ;==>_AD_GetAllOUsEX

; #FUNCTION# ====================================================================================================================
; Name...........: _ArraySortEX
; Description ...: Sort a 1D or 2D array on a specific index using the quicksort/insertionsort algorithms.
; Syntax.........: _ArraySortEX(ByRef $avArray[, $iDescending = 0[, $iStart = 0[, $iEnd = 0[, $iSubItem = 0]]]])
; Parameters ....: $avArray     - Array to sort
;                  $iDescending - [optional] If set to 1, sort descendingly
;                  $iStart      - [optional] Index of array to start sorting at
;                  $iEnd        - [optional] Index of array to stop sorting at
;                  $iSubItem    - [optional] Sub-index to sort on in 2D arrays
; Return values .: Success - 1
;                  Failure - 0, sets @error:
;                  |1 - $avArray is not an array
;                  |2 - $iStart is greater than $iEnd
;                  |3 - $iSubItem is greater than subitem count
;                  |4 - $avArray has too many dimensions
; Author ........: Jos van der Zande <jdeb at autoitscript dot com>
; Modified.......: LazyCoder - added $iSubItem option, Tylo - implemented stable QuickSort algo, Jos van der Zande - changed logic to correctly Sort arrays with mixed Values and Strings, Ultima - major optimization, code cleanup, removed $i_Dim parameter
; Remarks .......:
; Related .......:
; Link ..........:
; Example .......: Yes
; ===============================================================================================================================
Func _ArraySortEX(ByRef $avArray, $iDescending = 0, $iStart = 0, $iEnd = 0, $iSubItem = 0)
    If Not IsArray($avArray) Then Return SetError(1, 0, 0)

    Local $iUBound = UBound($avArray) - 1

    ; Bounds checking
    If $iEnd < 1 Or $iEnd > $iUBound Then $iEnd = $iUBound
    If $iStart < 0 Then $iStart = 0
    If $iStart > $iEnd Then Return SetError(2, 0, 0)

    ; Sort
    Switch UBound($avArray, 0)
        Case 1
            __ArrayQuickSort1DEX($avArray, $iStart, $iEnd)
            If $iDescending Then _ArrayReverseEX($avArray, $iStart, $iEnd)
        Case 2
            Local $iSubMax = UBound($avArray, 2) - 1
            If $iSubItem > $iSubMax Then Return SetError(3, 0, 0)

            If $iDescending Then
                $iDescending = -1
            Else
                $iDescending = 1
            EndIf

            __ArrayQuickSort2DEX($avArray, $iDescending, $iStart, $iEnd, $iSubItem, $iSubMax)
        Case Else
            Return SetError(4, 0, 0)
    EndSwitch

    Return 1
EndFunc   ;==>_ArraySortEX

; #INTERNAL_USE_ONLY# ===========================================================================================================
; Name...........: __ArrayQuickSort1DEX
; Description ...: Helper function for sorting 1D arrays
; Syntax.........: __ArrayQuickSort1DEX(ByRef $avArray, ByRef $iStart, ByRef $iEnd)
; Parameters ....: $avArray - Array to sort
;                  $iStart  - Index of array to start sorting at
;                  $iEnd    - Index of array to stop sorting at
; Return values .: None
; Author ........: Jos van der Zande, LazyCoder, Tylo, Ultima
; Modified.......:
; Remarks .......: For Internal Use Only
; Related .......:
; Link ..........:
; Example .......:
; ===============================================================================================================================
Func __ArrayQuickSort1DEX(ByRef $avArray, ByRef $iStart, ByRef $iEnd)
    If $iEnd <= $iStart Then Return

    Local $vTmp

    ; InsertionSort (faster for smaller segments)
    If ($iEnd - $iStart) < 15 Then
        Local $vCur
        For $i = $iStart + 1 To $iEnd
            $vTmp = $avArray[$i]

            If IsNumber($vTmp) Then
                For $j = $i - 1 To $iStart Step -1
                    $vCur = $avArray[$j]
                    ; If $vTmp >= $vCur Then ExitLoop
                    If ($vTmp >= $vCur And IsNumber($vCur)) Or (Not IsNumber($vCur) And StringCompare($vTmp, $vCur) >= 0) Then ExitLoop
                    $avArray[$j + 1] = $vCur
                Next
            Else
                For $j = $i - 1 To $iStart Step -1
                    If (StringCompare($vTmp, $avArray[$j], 2) >= 0) Then ExitLoop ;<- !Here!
                    $avArray[$j + 1] = $avArray[$j]
                Next
            EndIf

            $avArray[$j + 1] = $vTmp
        Next
        Return
    EndIf

    ; QuickSort
    Local $L = $iStart, $R = $iEnd, $vPivot = $avArray[Int(($iStart + $iEnd) / 2)], $fNum = IsNumber($vPivot)
    Do
        If $fNum Then
            ; While $avArray[$L] < $vPivot
            While ($avArray[$L] < $vPivot And IsNumber($avArray[$L])) Or (Not IsNumber($avArray[$L]) And StringCompare($avArray[$L], $vPivot) < 0)
                $L += 1
            WEnd
            ; While $avArray[$R] > $vPivot
            While ($avArray[$R] > $vPivot And IsNumber($avArray[$R])) Or (Not IsNumber($avArray[$R]) And StringCompare($avArray[$R], $vPivot) > 0)
                $R -= 1
            WEnd
        Else
            While (StringCompare($avArray[$L], $vPivot) < 0)
                $L += 1
            WEnd
            While (StringCompare($avArray[$R], $vPivot) > 0)
                $R -= 1
            WEnd
        EndIf

        ; Swap
        If $L <= $R Then
            $vTmp = $avArray[$L]
            $avArray[$L] = $avArray[$R]
            $avArray[$R] = $vTmp
            $L += 1
            $R -= 1
        EndIf
    Until $L > $R

    __ArrayQuickSort1DEX($avArray, $iStart, $R)
    __ArrayQuickSort1DEX($avArray, $L, $iEnd)
EndFunc   ;==>__ArrayQuickSort1DEX

; #INTERNAL_USE_ONLY# ===========================================================================================================
; Name...........: __ArrayQuickSort2DEX
; Description ...: Helper function for sorting 2D arrays
; Syntax.........: __ArrayQuickSort2DEX(ByRef $avArray, ByRef $iStep, ByRef $iStart, ByRef $iEnd, ByRef $iSubItem, ByRef $iSubMax)
; Parameters ....: $avArray  - Array to sort
;                  $iStep    - Step size (should be 1 to sort ascending, -1 to sort descending!)
;                  $iStart   - Index of array to start sorting at
;                  $iEnd     - Index of array to stop sorting at
;                  $iSubItem - Sub-index to sort on in 2D arrays
;                  $iSubMax  - Maximum sub-index that array has
; Return values .: None
; Author ........: Jos van der Zande, LazyCoder, Tylo, Ultima
; Modified.......:
; Remarks .......: For Internal Use Only
; Related .......:
; Link ..........:
; Example .......:
; ===============================================================================================================================
Func __ArrayQuickSort2DEX(ByRef $avArray, ByRef $iStep, ByRef $iStart, ByRef $iEnd, ByRef $iSubItem, ByRef $iSubMax)
    If $iEnd <= $iStart Then Return

    ; QuickSort
    Local $vTmp, $L = $iStart, $R = $iEnd, $vPivot = $avArray[Int(($iStart + $iEnd) / 2)][$iSubItem], $fNum = IsNumber($vPivot)
    Do
        If $fNum Then
            ; While $avArray[$L][$iSubItem] < $vPivot
            While ($iStep * ($avArray[$L][$iSubItem] - $vPivot) < 0 And IsNumber($avArray[$L][$iSubItem])) Or (Not IsNumber($avArray[$L][$iSubItem]) And $iStep * StringCompare($avArray[$L][$iSubItem], $vPivot) < 0)
                $L += 1
            WEnd
            ; While $avArray[$R][$iSubItem] > $vPivot
            While ($iStep * ($avArray[$R][$iSubItem] - $vPivot) > 0 And IsNumber($avArray[$R][$iSubItem])) Or (Not IsNumber($avArray[$R][$iSubItem]) And $iStep * StringCompare($avArray[$R][$iSubItem], $vPivot) > 0)
                $R -= 1
            WEnd
        Else
            While ($iStep * StringCompare($avArray[$L][$iSubItem], $vPivot) < 0)
                $L += 1
            WEnd
            While ($iStep * StringCompare($avArray[$R][$iSubItem], $vPivot) > 0)
                $R -= 1
            WEnd
        EndIf

        ; Swap
        If $L <= $R Then
            For $i = 0 To $iSubMax
                $vTmp = $avArray[$L][$i]
                $avArray[$L][$i] = $avArray[$R][$i]
                $avArray[$R][$i] = $vTmp
            Next
            $L += 1
            $R -= 1
        EndIf
    Until $L > $R

    __ArrayQuickSort2DEX($avArray, $iStep, $iStart, $R, $iSubItem, $iSubMax)
    __ArrayQuickSort2DEX($avArray, $iStep, $L, $iEnd, $iSubItem, $iSubMax)
EndFunc   ;==>__ArrayQuickSort2DEX

; #FUNCTION# ====================================================================================================================
; Name...........: _ArrayReverseEX
; Description ...: Takes the given array and reverses the order in which the elements appear in the array.
; Syntax.........: _ArrayReverseEX(ByRef $avArray[, $iStart = 0[, $iEnd = 0]])
; Parameters ....: $avArray - Array to modify
;                  $iStart  - [optional] Index of array to start modifying at
;                  $iEnd    - [optional] Index of array to stop modifying at
; Return values .: Success - 1
;                  Failure - 0, sets @error:
;                  |1 - $avArray is not an array
;                  |2 - $iStart is greater than $iEnd
;                  |3 - $avArray is not a 1 dimensional array
; Author ........: Brian Keene
; Modified.......: Jos van der Zande <jdeb at autoitscript dot com> -  added $iStart parameter and logic, Tylo - added $iEnd parameter and rewrote it for speed, Ultima - code cleanup, minor optimization
; Remarks .......:
; Related .......: _ArraySwap
; Link ..........:
; Example .......: Yes
; ===============================================================================================================================
Func _ArrayReverseEX(ByRef $avArray, $iStart = 0, $iEnd = 0)
    If Not IsArray($avArray) Then Return SetError(1, 0, 0)
    If UBound($avArray, 0) <> 1 Then Return SetError(3, 0, 0)

    Local $vTmp, $iUBound = UBound($avArray) - 1

    ; Bounds checking
    If $iEnd < 1 Or $iEnd > $iUBound Then $iEnd = $iUBound
    If $iStart < 0 Then $iStart = 0
    If $iStart > $iEnd Then Return SetError(2, 0, 0)

    ; Reverse
    For $i = $iStart To Int(($iStart + $iEnd - 1) / 2)
        $vTmp = $avArray[$i]
        $avArray[$i] = $avArray[$iEnd]
        $avArray[$iEnd] = $vTmp
        $iEnd -= 1
    Next

    Return 1
EndFunc   ;==>_ArrayReverseEX

 

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

Thank you for your reply, but unfortunately I cannot solve my problem :-(.
I admit that I have trouble understanding the modifications that must be made and in particular the use of "_AD_Example_GetOUTreeView" and "_AD_GetOUTreeView" which lose me because I do not use them in my program.

However, I copied your modifications so as not to use "_ArraySort" but rather "_ArraySortEX" and I have the same result.

My problem is indeed with the _ArraySort in the _AD_GetAllOUs function of the AD.au3 file.

In my code I run the command below to recreate a Treeview from my AD.
_AD_GetAllOUs ('OU = Computers, OU = distinguishedName ..., "\")

Below are different captures. The one without the _ArraySort is correct except that it is not sorted alphabetically like in the AD tree.

 

Do you have any additional solution to help me or it is a problem on my end that I cannot understand the use of your changes?

Thanks again for your help

TreeView AD.png

Link to comment
Share on other sites

I will need to do some testing. As I do not have OUs with dashes or spaces in our AD (and as I'm just an ordinary user which can't modify our AD) I need to create the array by hand. Then I will try to find out what I did wrong when implementing the solution by trancexx or which change in the Array UDF since then makes her solution work no longer 🤔

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

I had a look at the function and did some tests. I then realized that the whole sorting thing isn't working.
I need to rewrite the function so it uses a multicolumn sort algorithm.
Please stay tuned but don't hold your breath ;)

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

:D

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 weeks later...

The following (first version) of a function pads the subitems of a cell to a specified length so sorting returns the correct order.
Could you please run the example script (if you like you can add more of your data entries) and check if you get the desired result?

#include <Array.au3>
#include <debug.au3>

;----- Test Data
Local $aOUs[14][2]
$aOUs[1][0] = "01300_TEST\Ordinateurs"
$aOUs[1][1] = "OU=01300_TEST,OU=Ordinateurs,DC=company,DC=COM"
$aOUs[2][0] = "01300_TEST\Ordinateurs\Administratif"
$aOUs[2][1] = "OU=01300_TEST,OU=Ordinateurs,OU=Administratif,DC=company,DC=COM"
$aOUs[3][0] = "01300_TEST\Ordinateurs\Pedagogique"
$aOUs[3][1] = "OU=01300_TEST,OU=Ordinateurs,OU=Pedagogique,DC=company,DC=COM"
$aOUs[4][0] = "01300_TEST\Ordinateurs\Pedagogique\Bat_A"
$aOUs[4][1] = "OU=01300_TEST,OU=Ordinateurs,OU=Pedagogique,DC=Bat_A,DC=company,DC=COM"
$aOUs[5][0] = "01300_TEST\Ordinateurs\Pedagogique\Bat_A\ET_-2"
$aOUs[5][1] = "OU=01300_TEST,OU=Ordinateurs,OU=Pedagogique,DC=Bat_A,DC=ET_-2,DC=company,DC=COM"
$aOUs[6][0] = "01300_TEST\Ordinateurs\Pedagogique\Bat_A\ET_-2\Salle_02moins"
$aOUs[6][1] = "OU=01300_TEST,OU=Ordinateurs,OU=Pedagogique,DC=Bat_A,DC=ET_-2,DC=Salle_02moins,DC=company,DC=COM"
$aOUs[7][0] = "01300_TEST\Ordinateurs\Pedagogique\Bat_A\ET_1"
$aOUs[7][1] = "OU=01300_TEST,OU=Ordinateurs,OU=Pedagogique,DC=Bat_A,DC=ET_1,DC=company,DC=COM"
$aOUs[8][0] = "01300_TEST\Ordinateurs\Pedagogique\Bat_A\ET_1\Salle_01"
$aOUs[8][1] = "OU=01300_TEST,OU=Ordinateurs,OU=Pedagogique,DC=Bat_A,DC=ET_1,DC=Salle_01,DC=company,DC=COM"
$aOUs[9][0] = "01300_TEST\Ordinateurs\Pedagogique\Bat_A\ET_1\Salle_02"
$aOUs[9][1] = "OU=01300_TEST,OU=Ordinateurs,OU=Pedagogique,DC=Bat_A,DC=ET_1,DC=Salle_02,DC=company,DC=COM"
$aOUs[10][0] = "01300_TEST\Ordinateurs\Pedagogique 2019"
$aOUs[10][1] = "OU=01300_TEST,OU=Ordinateurs,OU=Pedagogique 2019,DC=company,DC=COM"
$aOUs[11][0] = "01300_TEST\Ordinateurs\Pedagogique 2019\Bat_B"
$aOUs[11][1] = "OU=01300_TEST,OU=Ordinateurs,OU=Pedagogique 2019,DC=Bat_B,DC=company,DC=COM"
$aOUs[12][0] = "01300_TEST\Ordinateurs\Pedagogique 2019\Bat_B\ET_2"
$aOUs[12][1] = "OU=01300_TEST,OU=Ordinateurs,OU=Pedagogique 2019,DC=Bat_B,DC=ET_2,DC=company,DC=COM"
$aOUs[13][0] = "01300_TEST\Ordinateurs\Pedagogique 2019\Bat_B\ET_2\Salle_20"
$aOUs[13][1] = "OU=01300_TEST,OU=Ordinateurs,OU=Pedagogique 2019,DC=Bat_B,DC=ET_2,DC=Salle_20,DC=company,DC=COM"
;-----

_ExtendCells($aOUs)
_ArraySort($aOUs, 0, 0, 0, 0)
_DebugArrayDisplay($aOUs)
Exit

Func _ExtendCells(ByRef $aArray, $iStartRow = 0, $iColumn = 0, $sSeparator = "\", $iLength = 50)

    Local $aTemp, $sTemp, $iSubtract = 0, $sPadString = StringFormat("%" & $iLength & "s", " ")

    ; Pad the substrings of the cells of the specified column to the specified length
    If UBound($aArray, 0) = 1 Then ; 1D array
        ; Insert code for a 1D array here
    Else
        If $iStartRow = 0 Then $iSubtract = 1
        For $i = $iStartRow To UBound($aArray, 1) - $iSubtract
            $aTemp = StringSplit($aArray[$i][$iColumn], $sSeparator)
            If @error = 0 Then
                For $j = 1 To UBound($aTemp, 1) - 1
                    $sTemp = StringLeft($aTemp[$j] & $sPadString, $iLength)
                    $aArray[$i][$iColumn] = ($j > 1) ? ($aArray[$i][$iColumn] & $sSeparator & $sTemp) : ($sTemp)
                Next
            EndIf
        Next
    EndIf

    ; Sort the array on the padded column
    _ArraySort($aArray, 0, $iStartRow, 0, $iColumn)

    ; Remove the padding characters
    If UBound($aArray, 0) = 1 Then ; 1D array
        ; Insert code for a 1D array here
    Else
        If $iStartRow = 0 Then $iSubtract = 1
        For $i = $iStartRow To UBound($aArray, 1) - $iSubtract
            While 1
                $aArray[$i][$iColumn] = StringReplace($aArray[$i][$iColumn], " " & $sSeparator, $sSeparator)
                If @extended = 0 Then ExitLoop
            WEnd
        Next
    EndIf

EndFunc   ;==>_ExtendCells

 

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

Second version (fixing some problems with first version):

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_AU3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7 -w 8
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
#include <Array.au3>
#include <debug.au3>

;----- Test Data
Global $aOUs[16][2] = [[15, 2]]
$aOUs[01][0] = "01300_TEST\Ordinateurs"
$aOUs[02][0] = "01300_TEST\Ordinateurs\Administratif"
$aOUs[03][0] = "01300_TEST\Ordinateurs\Pedagogique"
$aOUs[04][0] = "01300_TEST\Ordinateurs\Pedagogique\Bat A"
$aOUs[05][0] = "01300_TEST\Ordinateurs\Pedagogique\Bat A\ET_-2"
$aOUs[06][0] = "01300_TEST\Ordinateurs\Pedagogique\Bat A\ET_-2\Salle_02moins"
$aOUs[07][0] = "01300_TEST\Ordinateurs\Pedagogique\Bat A\ET_1"
$aOUs[08][0] = "01300_TEST\Ordinateurs\Pedagogique\Bat A\ET_1\Salle_01"
$aOUs[09][0] = "01300_TEST\Ordinateurs\Pedagogique\Bat A\ET_1\Salle_02"
$aOUs[10][0] = "01300_TEST\Ordinateurs\Pedagogique 2019"
$aOUs[11][0] = "01300_TEST\Ordinateurs\Pedagogique 2019\Bat_B"
$aOUs[12][0] = "01300_TEST\Ordinateurs\Pedagogique 2019\Bat_B\ET_2"
$aOUs[13][0] = "01300_TEST\Ordinateurs\Pedagogique 2019\Bat_B\ET_2\Salle_20"
$aOUs[14][0] = "01300_TEST\Ordinateurs\Pedagogique\Bat A\ET_-1"
$aOUs[15][0] = "01300_TEST\Ordinateurs\Pedagogique\Bat A\ET_-1\Salle_10"
;-----

_ExtendCells($aOUs, 1)
Exit

Func _ExtendCells(ByRef $aArray, $iStartRow = 0, $iColumn = 0, $sUsedSeparator = "\", $sSortSeparator = "|", $sPaddingCharacter = " ", $iLength = 50)

    Local $aTemp, $sTemp, $sPadString = StringFormat("%" & $iLength & "s", $sPaddingCharacter)

    ; Pad the substrings of the cells of the specified column to the specified length
    If UBound($aArray, 0) = 1 Then ; 1D array
        ; Insert code for a 1D array here
    Else
        For $i = $iStartRow To UBound($aArray, 1) - 1
            $aArray[$i][$iColumn] = Stringreplace($aArray[$i][$iColumn], $sUsedSeparator, $sSortSeparator)
            $aTemp = StringSplit($aArray[$i][$iColumn], $sSortSeparator, $STR_NOCOUNT)
            If @error = 0 Then
                For $j = 0 To UBound($aTemp, 1) - 1
                    $sTemp = StringLeft($aTemp[$j] & $sPadString, $iLength - 1)
                    $aArray[$i][$iColumn] = ($j = 0) ? ($sTemp & $sSortSeparator) : ($aArray[$i][$iColumn] & $sTemp & $sSortSeparator)
                Next
            EndIf
        Next
    EndIf

    ; Sort the array on the padded column
    _DebugArrayDisplay($aOUs, "Before sorting")
    _ArraySort($aArray, 0, $iStartRow, 0, $iColumn)
    _DebugArrayDisplay($aOUs, "After sorting")

    ; Remove the padding characters
    If UBound($aArray, 0) = 1 Then ; 1D array
        ; Insert code for a 1D array here
    Else
        For $i = $iStartRow To UBound($aArray, 1) - 1
            If StringRight($aArray[$i][$iColumn], 1) = $sSortSeparator Then $aArray[$i][$iColumn] = StringTrimRight($aArray[$i][$iColumn], 1) ; Remove rightmost separator character
            $aArray[$i][$iColumn] = StringReplace($aArray[$i][$iColumn], $sPaddingCharacter & $sSortSeparator, $sUsedSeparator)
            While 1
                $aArray[$i][$iColumn] = StringReplace($aArray[$i][$iColumn], $sPaddingCharacter & $sUsedSeparator, $sUsedSeparator)
                If @extended = 0 Then ExitLoop
            WEnd
        Next
    EndIf
    _DebugArrayDisplay($aOUs, "After sorting and removing padding characters")
EndFunc   ;==>_ExtendCells

What do you think? Does it work for you?

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

Hi,

First of all thank you for researching this problem and sorry for the delay in responding.

I encountered problems with the first version but the second seems to work perfectly!

To make sure I didn't make any mistakes, here's what I did to integrate the changes into my project:
- In my au3 file I added <Degug.au3>
- In the AD.au3 file
          - In the "Func _AD_GetAllOUs" function I replaced "ArraySort ($aOUs)" by "_ExtendCells ($aOUs, 1)"
          - In this same file I copied the function "_ExtendCells"
          - In this same file I had to declare the variable $aOUs (global $aOUs) otherwise I have a use message before declaration

Are the changes I made correct or do I have to do it differently?

 

Really a HUGE thank you for fixing this problem.

Marcel

Link to comment
Share on other sites

Looks good!

I will add the modification to the AD UDF and hope to release a new version (1.5.2.1) quite soon.

Edit:
- In my au3 file I added <Degug.au3> No longer needed with the latest version of the UDF
- In the AD.au3 file
    - In the "Func _AD_GetAllOUs" function I replaced "ArraySort ($aOUs)" by "_ExtendCells ($aOUs, 1)" No longer needed with the latest version of the UDF
    - In this same file I copied the function "_ExtendCells" No longer needed with the latest version of the UDF
    - In this same file I had to declare the variable $aOUs (global $aOUs) otherwise I have a use message before declaration. No longer needed with the latest version of the UDF

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

Thanks a lot for your feedback :) 
Glad you like the UDF and the support :D 

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 months later...

Hello,

great library and work very well !

With the function _AD_GetAllOUs I have strange backslash at the end of line on some OU :

ULilleRessources\DSI\DSISHS\Pont_de_Bois\Pedagogie\TICE\DEDIEES\Angellier
OU=Angellier,OU=DEDIEES,OU=TICE,OU=Pedagogie,OU=Pont_de_Bois,OU=DSISHS,OU=DSI,OU=ULilleRessources,DC=ad,DC=univ-lille,DC=fr
ULilleRessources\DSI\DSISHS\Pont_de_Bois\Pedagogie\TICE\DEDIEES\Angellier\B1619(tbi)\
OU=B1619(tbi),OU=Angellier,OU=DEDIEES,OU=TICE,OU=Pedagogie,OU=Pont_de_Bois,OU=DSISHS,OU=DSI,OU=ULilleRessources,DC=ad,DC=univ-lille,DC=fr
ULilleRessources\DSI\DSISHS\Pont_de_Bois\Pedagogie\TICE\DEDIEES\ArtsCulture
OU=ArtsCulture,OU=DEDIEES,OU=TICE,OU=Pedagogie,OU=Pont_de_Bois,OU=DSISHS,OU=DSI,OU=ULilleRessources,DC=ad,DC=univ-lille,DC=fr
ULilleRessources\DSI\DSISHS\Pont_de_Bois\Pedagogie\TICE\DEDIEES\ArtsCulture\B2451\
OU=B2451,OU=ArtsCulture,OU=DEDIEES,OU=TICE,OU=Pedagogie,OU=Pont_de_Bois,OU=DSISHS,OU=DSI,OU=ULilleRessources,DC=ad,DC=univ-lille,DC=fr
ULilleRessources\DSI\DSISHS\Pont_de_Bois\Pedagogie\TICE\DEDIEES\CIREL
OU=CIREL,OU=DEDIEES,OU=TICE,OU=Pedagogie,OU=Pont_de_Bois,OU=DSISHS,OU=DSI,OU=ULilleRessources,DC=ad,DC=univ-lille,DC=fr
ULilleRessources\DSI\DSISHS\Pont_de_Bois\Pedagogie\TICE\DEDIEES\CIREL\B3328\
OU=B3328,OU=CIREL,OU=DEDIEES,OU=TICE,OU=Pedagogie,OU=Pont_de_Bois,OU=DSISHS,OU=DSI,OU=ULilleRessources,DC=ad,DC=univ-lille,DC=fr
ULilleRessources\DSI\DSISHS\Pont_de_Bois\Pedagogie\TICE\DEDIEES\CIREL\B3332\
OU=B3332,OU=CIREL,OU=DEDIEES,OU=TICE,OU=Pedagogie,OU=Pont_de_Bois,OU=DSISHS,OU=DSI,OU=ULilleRessources,DC=ad,DC=univ-lille,DC=fr

I remove them in my code but it's normal ?

Link to comment
Share on other sites

How do you call _AD_GetAllOUs (which parameters do you pass)?

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

Hello,

I call it with
 

Local $root_ou = ""

 _AD_GetAllOUs($root_ou)

or

Local $root_ou = "OU=Pedagogie,OU=Pont_de_Bois,OU=DSISHS,OU=DSI,OU=ULilleRessources,DC=ad,DC=univ-lille,DC=fr"

 _AD_GetAllOUs($root_ou)

I have the same result with backslash on certain OU

Maybe is the start of parenthesis ?

OU=B1619(tbi),OU=Angellier,OU=DEDIEES,OU=TICE,OU=Pedagogie,OU=Pont_de_Bois,OU=DSISHS,OU=DSI,OU=ULilleRessources,DC=ad,DC=univ-lille,DC=fr
Link to comment
Share on other sites

Good point!

I will do some checks and come back later :)

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

I have notice other strange thing with version 1.5.2.1 (before I use the 1.4.14.0) for the first column of array :

- I have to remove extra space otherwise Stringlen function return incorrect number of character

- when I use _ArraySearch function I must set the $iCompare parameter to 1 otherwise the function found nothing

That's all for the moment. 😅

Thank you again and good luck.

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

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...