Sign in to follow this  
Followers 0
uruloke

Active Directory Treeview [SOLVED]

23 posts in this topic

#1 ·  Posted (edited)

Hello,

i'm a new user of AutoIt, but i decided to use it because it seems really great to get awesome GUI for my vbscripts :)

Anyway, I want to make an Active Directory Treeview (look like ADUC console) to run customs scripts to performs creations, search, etc..

Reading the help file of AutoIt, I found a way to create a treeview, and i'm pretty sure i can use my brain to find a way to dynamicaly create nodes from my AD.

But there something i have not found (I promise I made a search on the forum before posting) : I need a way to get the full path (to have the Distinguished Name in AD) of the selected node. The only thing I found is how to get the name of the node with GUICtrlRead($menu1, 1)

So, my questions are:

- how can i have the name of the parent node ? With this info, i could recursively build the full path

- Is it possible to set a hidden value on a node? In this case I could set the Distinguished Name in the value, and the treeview will only show the name (i'm not sure to be clear muttley )

Anyway, if someone as already made an AD treeview / browser, I would be happy to get it :(

Thank you very much

-----------------------------------

EDIT : SCRIPT SOLUTION

-----------------------------------

Hi!

Here I give you my GenerateADTreeview v1

It makes queries in Active Directory to build the treeview

For now, you have to specify a root Organizationnal Unit (in the MAIN part, modify $strRootContainer) to make it work! You won't see User or Computers container for exemple

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <TreeViewConstants.au3>
#include <StaticConstants.au3>
#Include <GuiTreeView.au3>

Opt('MustDeclareVars', 1)

#region ; Define AD Constants

Global Const $ADS_GROUP_TYPE_GLOBAL_GROUP = 0x2
Global Const $ADS_GROUP_TYPE_DOMAIN_LOCAL_GROUP = 0x4
Global Const $ADS_GROUP_TYPE_UNIVERSAL_GROUP = 0x8
Global Const $ADS_GROUP_TYPE_SECURITY_ENABLED = 0x80000000
Global Const $ADS_GROUP_TYPE_GLOBAL_SECURITY = BitOR($ADS_GROUP_TYPE_GLOBAL_GROUP, $ADS_GROUP_TYPE_SECURITY_ENABLED)
Global Const $ADS_GROUP_TYPE_UNIVERSAL_SECURITY = BitOR($ADS_GROUP_TYPE_UNIVERSAL_GROUP, $ADS_GROUP_TYPE_SECURITY_ENABLED)
Global Const $ADS_GROUP_TYPE_DOMAIN_LOCAL_SECURITY = BitOR($ADS_GROUP_TYPE_DOMAIN_LOCAL_GROUP, $ADS_GROUP_TYPE_SECURITY_ENABLED)

Global Const $ADS_UF_PASSWD_NOTREQD = 0x0020
Global Const $ADS_UF_WORKSTATION_TRUST_ACCOUNT = 0x1000
Global Const $ADS_ACETYPE_ACCESS_ALLOWED = 0x0
Global Const $ADS_ACETYPE_ACCESS_ALLOWED_OBJECT = 0x5
Global Const $ADS_FLAG_OBJECT_TYPE_PRESENT = 0x1
Global Const $ADS_RIGHT_GENERIC_READ = 0x80000000
Global Const $ADS_RIGHT_DS_SELF = 0x8
Global Const $ADS_RIGHT_DS_WRITE_PROP = 0x20
Global Const $ADS_RIGHT_DS_CONTROL_ACCESS = 0x100
Global Const $ADS_UF_ACCOUNTDISABLE = 2
Global Const $ADS_OPTION_SECURITY_MASK = 3
Global Const $ADS_SECURITY_INFO_DACL = 4
Global Const $ADS_PROPERTY_CLEAR = 1
Global Const $ADS_PROPERTY_APPEND = 3
Global Const $ADS_SCOPE_ONELEVEL = 1
Global Const $ADS_SCOPE_SUBTREE = 2

Global Const $ALLOWED_TO_AUTHENTICATE = "{68B1D179-0D15-4d4f-AB71-46152E79A7BC}"
Global Const $RECEIVE_AS = "{AB721A56-1E2f-11D0-9819-00AA0040529B}"
Global Const $SEND_AS = "{AB721A54-1E2f-11D0-9819-00AA0040529B}"
Global Const $USER_CHANGE_PASSWORD = "{AB721A53-1E2f-11D0-9819-00AA0040529b}"
Global Const $USER_FORCE_CHANGE_PASSWORD = "{00299570-246D-11D0-A768-00AA006E0529}"
Global Const $USER_ACCOUNT_RESTRICTIONS = "{4C164200-20C0-11D0-A768-00AA006E0529}"
Global Const $VALIDATED_DNS_HOST_NAME = "{72E39547-7B18-11D1-ADEF-00C04FD8D5CD}"
Global Const $VALIDATED_SPN = "{F3A64788-5306-11D1-A9C5-0000F80367C1}"
Const $Member_SchemaIDGuid = "{BF9679C0-0DE6-11D0-A285-00AA003049E2}"

Global $objConnection = ObjCreate("ADODB.Connection") ; Create COM object to AD
$objConnection.ConnectionString = "Provider=ADsDSOObject"
$objConnection.Open ("Active Directory Provider") ; Open connection to AD

Global $objRootDSE = ObjGet("LDAP://RootDSE")
Global $strAdsDomainPath = $objRootDSE.Get ("defaultNamingContext") ; Retrieve the current AD domain name
Global $strHostServer = $objRootDSE.Get ("dnsHostName"); Retrieve the name of the connected DC
Global $strConfiguration = $objRootDSE.Get ("ConfigurationNamingContext"); Retrieve the Configuration naming context

#endregion


#region ; Define Script Constants

Global Const $ADS_SCOPE_DEPTH = 1

#endregion

;**********************************************************************
;               MAIN
;**********************************************************************
Global $hTreeView
Global $strRootContainer = "OU=TESTS" &","& $strAdsDomainPath
 
Local $infobutton, $cancelbutton, $msg, $Text

GUICreate("AD TreeView", 400, 400)


$hTreeView     = CreateADTree ($strRootContainer, 25, 25, 300, 300, BitOr($TVS_HASBUTTONS, $TVS_HASLINES, $TVS_LINESATROOT, $TVS_DISABLEDRAGDROP, $TVS_SHOWSELALWAYS), $WS_EX_CLIENTEDGE)
$infobutton     = GUICtrlCreateButton("Info", 25, 350, 70, 20, 0)
$cancelbutton   = GUICtrlCreateButton("Cancel", 125, 350, 70, 20, 0)


GUISetState ()

GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")


While 1
    $msg = GUIGetMsg()
    Select
        Case $msg = $cancelbutton Or $msg = $GUI_EVENT_CLOSE
            ExitLoop
 
        Case $msg = $infobutton
            $Text = GetItemAdsPath ($hTreeView)
            MsgBox(64, "Information", $Text)
            
      EndSelect
WEnd

GUIDelete()
Exit


#region 
;**********************************************************************
;               FONCTIONS
;**********************************************************************


#region ; TreeView Functions


; ---------------------------------------------------------------------
;   Create Treeview  of OrganizationalUnits by queries in Active Directory
; ---------------------------------------------------------------------
Func CreateADTree ($strRootAdsPath, $intLeft, $intTop, $intWidth, $intHeight, $intStyle, $intExStyle )
    Local $LocalTreeview, $RootNode, $strRootName
    Global $hImage, $hFolderImage
    
    $LocalTreeview  = GUICtrlCreateTreeView($intLeft, $intTop, $intWidth, $intHeight, $intStyle, $intExStyle)
    
    $hImage = _GUIImageList_Create(16, 16, 5, 3)
    $hFolderImage = _GUIImageList_AddIcon($hImage, "shell32.dll", 4);Folder Image
    _GUICtrlTreeView_SetNormalImageList($LocalTreeview, $hImage)    
    
    _GUICtrlTreeView_BeginUpdate($LocalTreeview)
    $strRootName = GetObjectInfo ($strRootAdsPath, "Name")
    $RootNode = _GUICtrlTreeView_Add($LocalTreeview, 0, $strRootName, $hFolderImage, $hFolderImage)
    BuildADtreeView ($LocalTreeview, $RootNode, $strRootAdsPath,$ADS_SCOPE_DEPTH)
    _GUICtrlTreeView_EndUpdate($LocalTreeview)
    
    Return $LocalTreeview
EndFunc


; ---------------------------------------------------------------------
; Fonction récursive à N niveaux créant des noeuds à partir de requetes AD
;   $intDepth = number of recursive calls
; ---------------------------------------------------------------------
Func BuildADtreeView ($hTreeView, $hItem, $strAdsContainer,$intDepth)
Local $strOrganizationalUnitsDN, $arrOUsList, $intSizeArray
    Local $strObjectDN, $strObjectName
    Local $ThisItem, $i 

    If $intDepth < 1 Then
        Return 
    EndIf 
    
    $strOrganizationalUnitsDN = QueryAD ($strAdsContainer, $ADS_SCOPE_ONELEVEL,"OrganizationalUnit", "DistinguishedName", "name", "=", "*", "name")
    
    $arrOUsList = StringSplit($strOrganizationalUnitsDN,";")
    $intSizeArray = $arrOUsList[0]
    
    If $strOrganizationalUnitsDN = "" Then
    ;ConsoleWrite("LISTOU > EXIT FUNC "&@LF)
        
    Else 
        For $i = 1 To $intSizeArray
            $strObjectDN = $arrOUsList[$i]
            $strObjectName = GetObjectInfo($strObjectDN, "name")
            
        ; Add Item on Treeview
            $ThisItem = _GUICtrlTreeView_AddChild($hTreeView, $hItem, $strObjectName, $hFolderImage, $hFolderImage)
            
        ; Build Sub Containers 
            If ($intDepth-1) > 0 Then
                BuildADtreeView ($hTreeView, $ThisItem, $strObjectDN,$intDepth-1)
            EndIf 
        Next    
    
    EndIf

EndFunc 


; ---------------------------------------------------------------------
; Control clicks on Treeview
; ---------------------------------------------------------------------
Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
    #forceref $hWnd, $iMsg, $iwParam
    Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR, $hWndTreeview
    $hWndTreeview = $hTreeView
    If Not IsHWnd($hTreeView) Then $hWndTreeview = GUICtrlGetHandle($hTreeView)

    $tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    $iIDFrom = DllStructGetData($tNMHDR, "IDFrom")
    $iCode = DllStructGetData($tNMHDR, "Code")
    Switch $hWndFrom
        Case $hWndTreeview
            Switch $iCode
                Case $NM_CLICK; The user has clicked the left mouse button within the control
                    Local $tPoint, $tTVHEx, $TVhItem, $mX, $mY
                    $tPoint = _WinAPI_GetMousePos(True, $hWndTreeview)
                    $mX = DllStructGetData($tPoint, "X")
                    $mY = DllStructGetData($tPoint, "Y")
                    $tTVHEx = _GUICtrlTreeView_HitTestEx($hWndTreeview, $mX, $mY)
                    $TVhItem = DllStructGetData($tTVHEx, "Item")
                    Switch DllStructGetData($tTVHEx, "Flags")
                        Case $TVHT_ONITEM
                            ConsoleWrite("$NM_CLICK" & @LF & "--> $TVHT_ONITEM Item Handle:" & @TAB & $TVhItem)           

                        Case $TVHT_ONITEMLABEL or $TVHT_ONITEMICON
                            TreeView_RefreshItem ($hTreeView, $TVhItem)

                    EndSwitch     
;~    Return 1; nonzero to not allow the default processing
                    Return 0; zero to allow the default processing
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc  ;==>WM_NOTIFY


; ---------------------------------------------------------------------
; Refresh : Load Sub Containers (query AD)
; ---------------------------------------------------------------------
Func TreeView_RefreshItem ($hTreeView, $hItem)
    Local $strItemAdsPath, $intNbChildren
    Local $strAdsContainer
    
    $strItemAdsPath = GetItemRecursiveAdsPath ($hTreeView, $hItem)
    $intNbChildren = _GUICtrlTreeView_GetChildCount($hTreeView, $hItem)
    
    If $intNbChildren < 0 Then
        $strAdsContainer = $strItemAdsPath & "," &$strAdsDomainPath
        BuildADtreeView ($hTreeView, $hItem, $strAdsContainer,$ADS_SCOPE_DEPTH)
        
    EndIf 
    
EndFunc 

; ---------------------------------------------------------------------
; TreeView Function : Get Selected Item's Label
; ---------------------------------------------------------------------
Func GetItemText ($hTreeView)
    Local $hItem, $Text
    
    $hItem = _GUICtrlTreeView_GetSelection ($hTreeView)
;MsgBox(64, "Information", $hItem)
    If $hItem = 0 Then
        $Text = "No item currently selected"
    Else
        $Text = _GUICtrlTreeView_GetText ($hTreeView, $hItem)
    EndIf
    
    Return $Text
EndFunc

; ---------------------------------------------------------------------
; TreeView Function : Get Parent's Label of the Selected Item
; ---------------------------------------------------------------------
Func GetParentItemText ($hTreeView)
    Local $hItem, $Text
    Local $hParentItem
    
    $hItem = _GUICtrlTreeView_GetSelection ($hTreeView)
    
    If $hItem = 0 Then
        $Text = "No item currently selected"
    Else
        $hParentItem = _GUICtrlTreeView_GetParentHandle($hTreeView, $hItem)
    ;MsgBox(64, "Parent", $hParentItem)
        If $hParentItem=0 Then
            $Text = ""
        Else    
            $Text = _GUICtrlTreeView_GetText ($hTreeView, $hParentItem) 
        EndIf
    EndIf
    
    Return $Text    
EndFunc


; ---------------------------------------------------------------------
; TreeView Function : Get Selected Item's ADS Path
;       syntax like  OU=Temp,OU=SALES,OU=Company
; ---------------------------------------------------------------------
Func GetItemAdsPath ($hTreeView)
    Local $Text, $hItem, $hParentItem
    
; Get Item ID
    $hItem = _GUICtrlTreeView_GetSelection ($hTreeView)
    If $hItem <> 0 Then
        $Text = GetItemRecursiveAdsPath ($hTreeView, $hItem)
    EndIf 
    
    Return $Text
EndFunc

; ---------------------------------------------------------------------
;; TreeView Function : Get Specified Item's ADS Path
;       syntax like  OU=Temp,OU=SALES,OU=Company
; ---------------------------------------------------------------------
Func GetItemRecursiveAdsPath ($hTreeView, $hItem)
    Local $Text, $hParentItem
    
; Get Parent Item ID
    $hParentItem = _GUICtrlTreeView_GetParentHandle($hTreeView, $hItem)
    If $hParentItem=0 Then
        $Text = "OU="&_GUICtrlTreeView_GetText ($hTreeView, $hItem)
    Else    
        $Text = "OU="&_GUICtrlTreeView_GetText ($hTreeView, $hItem) & "," & GetItemRecursiveAdsPath ($hTreeView, $hParentItem)
    EndIf

    Return $Text
EndFunc

#endregion

#region ; AD Functions
; ---------------------------------------------------------------------
; Requete AD
;   $intScope = ADS_SCOPE_ONELEVEL or ADS_SCOPE_SUBTREE
;   $strTypeFilter = USER, CONTACT, GROUP, COMPUTER
;   $strAttributeQueried : Attribut retourné (ex: DistinguishedName, Name, CN, etc.)
;   $strAttributeRequested : Critere de recherche (ex: SamAccountName, Name, DisplayName, GivenName, etc.)
;   $strOperator: operation à effectuer (ex: "=", ">", "<>")
;   $strAttributeValue : requete de valeur (ex: "toto" pour le Name)
;           > Recherche possible avec le wildchar (ex: Test*)
;   $strSort : Critère de tri alphabétique (ex: "Name" pour un tri sur le nom)
;           > Mettre à "" pour ne faire aucun tri

; SORTIE: Si plusieurs réponses, séparation par ';' (ex: DN1;DN2;DN3)
; ---------------------------------------------------------------------
Func QueryAD ($strLdapRootPath, $intScope, $strTypeFilter, $strAttributeQueried, $strAttributeRequested, $strOperator, $strAttributeValue, $strSort)
    Local $objCommand, $objRecordSet
    Local $strResultQuery, $strResultQueryMultiValued
    Local $arrTemp, $strValue, $CleanAdsPath

    $strResultQuery = ""

    $objCommand = ObjCreate("ADODB.Command")
    $objCommand.ActiveConnection = $objConnection
    
;Escape Special Characters for SQL Query
    $CleanAdsPath = StringReplace($strLdapRootPath,"'","''")
    $CleanAdsPath = StringReplace($CleanAdsPath,"+","\+")

    If StringCompare($strTypeFilter,"COMPUTER")=0 Then
        $objCommand.CommandText = _
            "Select "& $strAttributeQueried &","&$strSort&" from 'LDAP://" & $CleanAdsPath & _
            "' where objectClass='COMPUTER' and "&$strAttributeRequested&"='"&$strAttributeValue&"'" 
    Else
        $objCommand.CommandText = _
            "Select "& $strAttributeQueried &" from 'LDAP://" & $CleanAdsPath & _
            "' where objectClass='"&$strTypeFilter&"' AND objectClass<>'computer' and "&$strAttributeRequested& $strOperator &"'"&$strAttributeValue&"'"
    EndIf 

    $objCommand.Properties("Page Size") = 1000; Recherche par paquet de 1000 objets
    $objCommand.Properties("Timeout") = 30 
    $objCommand.Properties("Searchscope") = $intScope 
    $objCommand.Properties("Cache Results") = False 
    If $strSort<>"" Then
        $objCommand.Properties("Sort on") = $strSort
    EndIf 
    
    $objRecordSet = $objCommand.Execute

    If $objRecordSet.EOF <> true Then 
        $objRecordSet.MoveFirst
    EndIf 

    If NOT $objRecordSet.EOF Then
        If IsArray($objRecordSet.Fields($strAttributeQueried)) Then
            $arrTemp = $objRecordSet.Fields($strAttributeQueried)
            $strResultQueryMultiValued = ""
            For $strValue In $arrTemp
                If $strResultQueryMultiValued="" Then 
                    $strResultQueryMultiValued = $strValue
                Else
                    $strResultQueryMultiValued = $strResultQueryMultiValued &"§"& $strValue
                EndIf
            Next
            $strResultQuery = $strResultQueryMultiValued
        Else
            $strResultQuery  = $objRecordSet.Fields($strAttributeQueried).Value
        EndIf 
        
        $objRecordSet.MoveNext
        
    EndIf

;MsgBox (1,"Query AD","$strResultQuery : "&$strResultQuery) 
    
    While NOT $objRecordSet.EOF
        If IsArray($objRecordSet.Fields($strAttributeQueried)) Then
            $arrTemp = $objRecordSet.Fields($strAttributeQueried)
            $strResultQueryMultiValued = ""
            For $strValue In $arrTemp
                If $strResultQueryMultiValued="" Then 
                    $strResultQueryMultiValued = $strValue
                Else
                    $strResultQueryMultiValued = $strResultQueryMultiValued &"§"& $strValue
                EndIf
            Next
            $strResultQuery  = $strResultQuery &";" &$strResultQueryMultiValued
        
        Else
            $strResultQuery  = $strResultQuery &";" &$objRecordSet.Fields($strAttributeQueried).Value 
        EndIf 
        
        $objRecordSet.MoveNext
    Wend 

    $objCommand = 0
    $objRecordSet = 0
    
    Return $strResultQuery

EndFunc



; ---------------------------------------------------------------------
; Récupère la valeur d'un attribut d'un objet AD
;   - StrObjectDN = Object DistinguishedName
;   - StrAttribute = Attribut choisi
; ---------------------------------------------------------------------
Func GetObjectInfo ($strObjectDN, $strAttribute)
    Local $objADObject, $strResult 

    $objADObject = ObjGet ("LDAP://"&$strObjectDN)
    $objADObject.GetInfo
 
    $strResult = $objADObject.Get($strAttribute)
    
    Return $strResult
EndFunc



#endregion

#endregion
Edited by uruloke

Share this post


Link to post
Share on other sites



So your wanting something that looks like this? http://www.bristol.ac.uk/is/computing/advi...ff/winxp/ou.gif or similar?

Yes, exactly, the tree part (on the left pane)

If I keep your exemple: suppose I wanna create a computer in the OU "student pc lab #1".

1/ I have a script/function who takes the OU path in parameter (to know where i will create the computer object)

2/ I want to keep the "AD tree" looklike: I click on "student pc lab #1" to specify the target OU.

3/ I need to get the OU path from the selected node to use it with my function createComputerObject

Share this post


Link to post
Share on other sites

Yes, exactly, the tree part (on the left pane)

If I keep your exemple: suppose I wanna create a computer in the OU "student pc lab #1".

1/ I have a script/function who takes the OU path in parameter (to know where i will create the computer object)

2/ I want to keep the "AD tree" looklike: I click on "student pc lab #1" to specify the target OU.

3/ I need to get the OU path from the selected node to use it with my function createComputerObject

For AD stuff, have a look here:

http://www.autoitscript.com/forum/index.ph...tory&st=105

I am unable to test AD stuff ATM, but I'll just use arrays, to show you how to populate the treeview, and also how to get an event such as a click. Give me an hour, as I've got to reject my friend to do this.... Wave to him now! muttley

Share this post


Link to post
Share on other sites

#5 ·  Posted (edited)

For AD stuff, have a look here:

http://www.autoitscript.com/forum/index.ph...tory&st=105

I am unable to test AD stuff ATM, but I'll just use arrays, to show you how to populate the treeview, and also how to get an event such as a click. Give me an hour, as I've got to reject my friend to do this.... Wave to him now! muttley

Hi, thx Bert for your help.

I'm thinking i maybe wrote a bad title for my topic, because my main problem is treeview, not Active Directory :)

(maybe some moderator can change it for "Treeview : Advances Features?? / use for AD browsing" ?)

Anyway, if i take 2 minutes to think about it, i think i can solve my problem if someone can give me a solution/exemple for the following issue:

I want to obtain the following treeview:

-------------------------------

[MyTree]

+NodeA

+ nA_Sub1

- nASubSub1

- nA_Sub2

+NodeB

- nB_Sub1

+NodeC

-------------------------------

And a way / a function to obtain one (or both I you can) of the following information, when I Click and select the node "nASubSub1":

1/ result = "nASubSub1 / nA_Sub1 / NodeA" (or NodeA / nA_Sub1 / nASubSub1)

2/ result = "My Hidden Value for nASubSub1"

Edited by uruloke

Share this post


Link to post
Share on other sites

I actually was just looking for a similar thing (I just want to get the item and its parents), and if you use the user defined treeview controls I think it's possible.

I haven't tried it out yet, but if you use

_GUICtrlTreeView_Create(...) to make the control, and use _GUICtrlTreeView_AddChild(...) to create children, you should be able to recursively get all of the parents and create a string with something like this:

; assuming you have already generated the treeview, and $selectedItem is handle to the item you're getting info

Dim $parentArray(100); 100 is arbitrary, pick a number well above the most parents you expect
$i = 0
$parentArray[0] = $selectedItem
While _GUICtrlTreeView_GetParentHandle($parentArray[$i]) <> $treeviewControl ; don't mess with things that are children of the root

        $parentArray[$i] = _GUICtrlTreeView_GetParentHandle($parentArray[$i - 1])  ; handle to the parent... read the handle to get the text
       $i = $i + 1

Wend

Then you will have an array to all of the parent handles, and the number of parents, $i

Dunno if its what you're looking for or if it will work but I figured I'd throw it out there


Regards,Josh

Share this post


Link to post
Share on other sites

I actually was just looking for a similar thing (I just want to get the item and its parents), and if you use the user defined treeview controls I think it's possible.

I haven't tried it out yet, but if you use

_GUICtrlTreeView_Create(...) to make the control, and use _GUICtrlTreeView_AddChild(...) to create children, you should be able to recursively get all of the parents and create a string with something like this:

; assuming you have already generated the treeview, and $selectedItem is handle to the item you're getting info

Dim $parentArray(100); 100 is arbitrary, pick a number well above the most parents you expect
$i = 0
$parentArray[0] = $selectedItem
While _GUICtrlTreeView_GetParentHandle($parentArray[$i]) <> $treeviewControl; don't mess with things that are children of the root

        $parentArray[$i] = _GUICtrlTreeView_GetParentHandle($parentArray[$i - 1]) ; handle to the parent... read the handle to get the text
       $i = $i + 1

Wend

Then you will have an array to all of the parent handles, and the number of parents, $i

Dunno if its what you're looking for or if it will work but I figured I'd throw it out there

Hi!

Thx for your answer, i looked for these user defined functions, and it seems i can use it for what i'm looking for!

I will test it next week, and post here my solution if it works muttley

Share this post


Link to post
Share on other sites

No problem. It worked for me, but I only wanted to get the first parent. I messed around with recursively getting all of the parents, but I gave up muttley

Good luck!


Regards,Josh

Share this post


Link to post
Share on other sites

No problem. It worked for me, but I only wanted to get the first parent. I messed around with recursively getting all of the parents, but I gave up :)

Good luck!

Hi!

Here is the function I wrote for getting recursively all the parents! muttley

You only have to call GetItemAdsPath

Func GetItemAdsPath ($hTreeView)
    Local $Text, $hItem, $hParentItem
    
; Get Item ID
    $hItem = _GUICtrlTreeView_GetSelection ($hTreeView)
    If $hItem <> 0 Then
        $Text = GetItemRecursiveAdsPath ($hTreeView, $hItem)
    EndIf 
    
    Return $Text
EndFunc


Func GetItemRecursiveAdsPath ($hTreeView, $hItem)
    Local $Text, $hParentItem
    
; Get Parent Item ID
    $hParentItem = _GUICtrlTreeView_GetParentHandle($hTreeView, $hItem)
    If $hParentItem=0 Then
        $Text = "OU="&_GUICtrlTreeView_GetText ($hTreeView, $hItem)
    Else    
        $Text = "OU="&_GUICtrlTreeView_GetText ($hTreeView, $hItem) & "," & GetItemRecursiveAdsPath ($hTreeView, $hParentItem)
    EndIf

    Return $Text
EndFunc

Share this post


Link to post
Share on other sites

I did an edit and post my solution on the first post muttley

Share this post


Link to post
Share on other sites

Seems very nice. I'm just working on such script. But I found some errors in your script. If the search is from the base of a AD, it will report wrong DN name.

I'll work on it tomorrow.

BTW: I have a stupid question. If the OU name has "/" in the name the script will complain. Maybe we need modify it in GetObjectInfo to replace those chars. But I don't know replace to what.

Sorry for my ignorance.

I'll try it myself first tomorrow.

Share this post


Link to post
Share on other sites

After research the script, I change below points:

1. To get accurate DN name, in GetItemRecursiveAdsPath Function

Change

$Text = "OU="&_GUICtrlTreeView_GetText ($hTreeView, $hItem)

To:

$Text = $strRootContainer;

2. To translate "/" character, in QueryAD Function

Remove

$CleanAdsPath = StringReplace($CleanAdsPath,"+","\+")

Add

$CleanAdsPath = StringReplace($CleanAdsPath,"/","\/")

3. To translate "/" character, in GetObjectInfo Function

Add

$strObjectDN = StringRegExpReplace ($strObjectDN, "/", "\\/")

Maybe it's also useful for you.

Share this post


Link to post
Share on other sites

Sorry to revive a dead thread. This script is 'almost' exactly what I need. I work in an organization that has many sites, all with their own unique network information. This allows me to query the network info from the adapter and identify which OU they are in.

I would like to change the $strRootContainer to the user's specific OU.

I notice that if I leave it as an OU in the root of the domain, Ex. "OU=North America,DC=Contoso,DC=Com", it works great.

If I want to dive deeper and get the location's OU as the root container, Ex. "OU=California,OU=West Coast,OU=North America,DC=Contoso,DC=com", it shows the top item with the plus, then hitting the plus shows the child OUs in that OU...but then selecting a child OU crashes the app.

The error is on this command:

$objRecordSet = $objCommand.Execute

within the QueryAD function.

Any ideas?

Share this post


Link to post
Share on other sites

Sorry to revive a dead thread. This script is 'almost' exactly what I need. I work in an organization that has many sites, all with their own unique network information. This allows me to query the network info from the adapter and identify which OU they are in.

I would like to change the $strRootContainer to the user's specific OU.

I notice that if I leave it as an OU in the root of the domain, Ex. "OU=North America,DC=Contoso,DC=Com", it works great.

If I want to dive deeper and get the location's OU as the root container, Ex. "OU=California,OU=West Coast,OU=North America,DC=Contoso,DC=com", it shows the top item with the plus, then hitting the plus shows the child OUs in that OU...but then selecting a child OU crashes the app.

The error is on this command:

$objRecordSet = $objCommand.Execute

within the QueryAD function.

Any ideas?

Alright, I think I have it working. It's a hack, but it works. What I saw was the objCommand.commandtext (ldap search) was putting the dc info twice...so, instead of the query being on "LDAP://OU=California,OU=West Coast,OU=North America,DC=Contoso,DC=com", it was doing "LDAP://OU=California,OU=West Coast,OU=North America,DC=Contoso,DC=com,DC=Contoso,DC=com"...so what I did was do a string replace to remove the extra domain name. I changed it here:

Func GetItemRecursiveAdsPath ($hTreeView, $hItem)
    Local $Text, $hParentItem
    
; Get Parent Item ID
    $hParentItem = _GUICtrlTreeView_GetParentHandle($hTreeView, $hItem)
    If $hParentItem=0 Then
        $Text = $strRootContainer
    Else    
        $Text = "OU="&_GUICtrlTreeView_GetText ($hTreeView, $hItem) & "," & stringReplace(GetItemRecursiveAdsPath ($hTreeView, $hParentItem),",DC=Contoso,DC=com","")
    EndIf

    Return $Text
EndFunc

If anyone knows a better way, please let me know.

Thanks.

Share this post


Link to post
Share on other sites

There is a successor to adfunctions.au3 available - AD.au3.

For download please see my signature. This extended AD UDF has more functions, better error handling, help file, examples, a wiki ...

Please have a look at function _AD_GetAllOUs. You can specify a OU where to start.


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

There is a successor to adfunctions.au3 available - AD.au3.

For download please see my signature. This extended AD UDF has more functions, better error handling, help file, examples, a wiki ...

Please have a look at function _AD_GetAllOUs. You can specify a OU where to start.

How would I use that to replace the functions in this script? Do you think it would require a full rewrite? All I really need is a form to pop up with the treeview. Is there an easy way of doing this without rewriting a bunch of code.

Share this post


Link to post
Share on other sites

#17 ·  Posted (edited)

Check this example script. It lists all OUs in a TreeView.

If you want to start in a sub OU set $sOU to the FQDN of this OU.

#include <ad.au3>
#include <TreeviewConstants.au3>
#include <WindowsConstants.au3>
#include <GUIConstants.au3>
#Include <GuiTreeView.au3>

_AD_Open()
Global $sOU = ""
Global $sSep = "\"
Global $aResult = _AD_GetAllOUs($sOU, $sSep)
Global $aTV[$aResult[0][0] + 1] = [$aResult[0][0]]
For $i = 1 To $aResult[0][0]
    $aTemp = StringSplit($aResult[$i][0], $sSep)
    $aTV[$i] = StringFormat("%" & $aTemp[0] - 1 & "s", "") & "#" & $aTemp[$aTemp[0]]
Next
_AD_Close()

$hMain = GUICreate("Treeview", 742, 683, -1, -1, -1798701056, 256)
$hTree = GUICtrlCreateTreeView(6, 6, 600, 650, BitOR($TVS_HASBUTTONS, $TVS_HASLINES, $TVS_LINESATROOT, $TVS_DISABLEDRAGDROP, $TVS_SHOWSELALWAYS), $WS_EX_CLIENTEDGE)
TV_Display($aTV)
GUISetState()

While 1
    $Msg = GUIGetMsg()
    Switch $Msg
        Case $GUI_EVENT_CLOSE
            Exit
    EndSwitch
WEnd

Func TV_Display($aTree)
    Dim $hNode[50] ;Keep Parent on Level
    For $i = 1 To $aTree[0]
        $line = StringSplit(StringStripCR($aTree[$i]), @TAB)
        $level = StringInStr($line[1], "#")
        If $level = 0 Then ExitLoop
        If $level = 1 Then
            $hNode[$level] = _GUICtrlTreeView_Add($hTree, 0, StringMid($line[1], $level + 1))
        Else
            $hNode[$level] = _GUICtrlTreeView_AddChild($hTree, $hNode[$level - 1], StringMid($line[1], $level + 1))
        EndIf
    Next
EndFunc   ;==>TV_Display
Edited by water

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

#18 ·  Posted (edited)

Check this example script. It lists all OUs in a TreeView.

Wow..Water, this is great! I should preface this with a little background info. I am not running this in a full Windows OS...This is run during an imaging process within WinPE. I need the ability to select the OU that the computer will be joined into so I can modify my unattend file. I manipulated the code a little bit because I needed to pass alternate credentials to AD since the workstations are not in the domain. While on my dev unit, the credentials appear to work, however, when I run it from the PE environment, it fails. It appears to be failing in the _AD_OPEN function, around line 389 which is $oAD_RootDSE = ObjGet("LDAP://" & $sAD_HostServerParam & "/RootDSE")

Is there something that I am missing? Do these functions rely on some other Windows dlls or something that I need to have in the PE environment?

I also noticed that the _AD_Open function's parameters are set to ""($sAD_UserIdParam = "")...Maybe I just don't understand it, but wouldn't that make all parameters sent to that function set to "" or is that just the way to define the default parameter if nothing is sent?

Thanks for all your help!

Rich.

Edited by RichMinichiello

Share this post


Link to post
Share on other sites

Please check this It descibes what needs to be installed on Windows PE to access the Active Directory.


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

water...Thank you! I have my work cut out for me. I will get the PE env. setup and get back to you.

Thanks again for your help!

Rich.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0