Jump to content

Array values and Treeview


RogFleming
 Share

Recommended Posts

Hi I hope everyone having a good day. I been working on creating a AD Treeview so I can run specific commands against a specific OU. The issue I experiencing is how to keep track of the values of each tree items so can create a Context menu item of each Tree item.

So here is what I got so far, in the treeview GUI everything lines up great, but cannot get any on contextmenu items to be selcted correctly.

$tstou = _AD_GetAllOUs("OU=Test Workstation OU,OU=THR Workstations,DC=company,DC=com")
 here the part where I take the results from above to build the treeview, but not sure how to track each item.
;Test OU GRoup
$tstwks = GUICtrlCreateTreeViewItem("Test Groups", $wksname)
For $i = 1 To UBound($wstou,1) - 1
   $tstou[$i][0]=GUICtrlCreateTreeViewItem(StringTrimLeft($tstou[$i][0],37), $tstwks)
   $tstmenu = GUICtrlCreateContextMenu($tstou[$i][0])
   $tstmenuitem1 = GUICtrlCreateMenuItem("Workstation List",$tstmenu)
   $tstmenuitem2 = GUICtrlCreateMenuItem("Scan Workstations for McShield",$tstmenu)
   $tstmenuitem3 = GUICtrlCreateMenuItem("Scan Registry for invalid services",$tstmenu)

   GUICtrlSetColor(-1, 0x0000C0)
Next
;MsgBox(1,"tstmenuitem1 value",$tstmenuitem1)
GUICtrlSetState($wksname, BitOR($GUI_EXPAND, $GUI_DEFBUTTON))

GUISetState()

While 1
    ;Sleep(100)
    $nMsg = GUIGetMsg()

    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            Exit
        Case $nMsg > 0
                IF $nMsg > 0 Then
                $item = GUICtrlRead($nMsg)
                MsgBox(1,"Selected",$item)
                EndIf
    EndSwitch

WEnd

Or should it look more like this?

;Test OU GRoup
$tstwks = GUICtrlCreateTreeViewItem("Test Groups", $wksname)
For $i = 1 To UBound($wstou,1) - 1
   $tstou[$i][0]=GUICtrlCreateTreeViewItem(StringTrimLeft($tstou[$i][0],37), $tstwks)
   $tstmenu = GUICtrlCreateContextMenu($tstou[$i][0])
   $tstmenuitem1 = GUICtrlCreateMenuItem("Workstation List",$tstou[$i][0])
   $tstmenuitem2 = GUICtrlCreateMenuItem("Scan Workstations for McShield",$tstou[$i][0])
   $tstmenuitem3 = GUICtrlCreateMenuItem("Scan Registry for invalid services",$tstou[$i][0])

   GUICtrlSetColor(-1, 0x0000C0)
Next
;MsgBox(1,"tstmenuitem1 value",$tstmenuitem1)
GUICtrlSetState($wksname, BitOR($GUI_EXPAND, $GUI_DEFBUTTON))

GUISetState()

While 1
    ;Sleep(100)
    $nMsg = GUIGetMsg()

    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            Exit
        Case $nMsg > 0
                IF $nMsg = $tstmenu Then
                $item = GUICtrlRead($tstmenunMsg)
                MsgBox(1,"Selected",$item)
                EndIf
    EndSwitch

WEnd
_AD_Close()
Link to comment
Share on other sites

So after taking a smoke break (thinking about it) would it be advised to add the control values of each dynamically created control to the existing array and tehn once the GuiCtrlREad is checked query the array for the control and get the Ou assigned in the Array?

$tstou = _AD_GetAllOUs("OU=Test Workstation OU,OU=THR Workstations,DC=txhealth,DC=org")
becomes an Array

Then when I create the treeview and contextmenu add the following

$tstwks = GUICtrlCreateTreeViewItem("Test Groups", $wksname)
For $i = 2 To UBound($wstou,1) - 1
   $tstmainmenu=GUICtrlCreateTreeViewItem(StringTrimLeft($tstou[$i][0],37), $tstwks)
   $tstmenu = GUICtrlCreateContextMenu($tstou[$i][0])
   $tstmenuitem1 = GUICtrlCreateMenuItem("Workstation List",$tstou[$i][0])
   $tstmenuitem2 = GUICtrlCreateMenuItem("Scan Workstations for McShield",$tstou[$i][0])
   $tstmenuitem3 = GUICtrlCreateMenuItem("Scan Registry for invalid services",$tstou[$i][0])
_ArrayInsert(tstou,$tstou[$i][3],$tstmainmenu)??????
Link to comment
Share on other sites

Another question using AD.au3 how would I get a array of workstations from a specific OU?

I got it NVM

Global $aObjects = _AD_GetObjectsInOU("OU=Test Workstation OU,OU=Workstations,DC=company,DC=com", "(&(objectcategory=computer)(objectclass=computer))", 2, "name")
_ArrayDisplay($aObjects)
Edited by RogFleming
Link to comment
Share on other sites

seems I made it a little more effective

$aOUs = _AD_GetAllOUs("OU=THR Workstations,DC=txhealth,DC=org"); Pulls all the workstation OUs from the Main Workstation OU
;Test OU GRoup
Global $tstou = _ArrayFindAll($aOUs,"OU=Test Workstation",0,0,0,1,1); searches the $aOUs Array to find all values that match our targetted OU
For $i = 1 To UBound($tstou,1) - 1
    Global $getObject = $aOUs[$tstou[$i]][1]; Finds the child OU FQDN in the $aOUs Array from the index in $tstou Array
    Global $tstoumembers = _AD_GetObjectsInOU($getObject, "(&(objectcategory=computer)(objectclass=computer))", 2, "name"); searches the OU PCs
    _ArrayDisplay($tstoumembers);displays the workstation names
Next
Exit

So the remaining question is how to populate the parent OU and then have a Child OU Tree with and Contextmenu items on eachto display the PCs that belong to the child OU branch when selected from the menu.

Link to comment
Share on other sites

Well I made some good progress last night, but still having issues with the ContextMenu selection. Any help would be great. I have comment out the AD lookup just to speed up testing.

#include <Misc.au3>
#include <GUIConstants.au3>
#Include <GuiTreeView.au3>
#include <TreeviewConstants.au3>
#include <WindowsConstants.au3>
#Include <WinAPI.au3>
#include <AD.au3>
#include <StaticConstants.au3>
#Include <WinAPI.au3>

Opt ("GuiOnEventMode", 1)
$mainform = GUICreate("Organizational Tree", 600, 900)
GUISetOnEvent($GUI_EVENT_CLOSE, "_GUI_Event_Close")
$tviewPI = GUICtrlCreateTreeView(10, 10, 580, 880, BitOR($TVS_HASBUTTONS, $TVS_HASLINES, $TVS_LINESATROOT, $TVS_DISABLEDRAGDROP, $TVS_SHOWSELALWAYS), $WS_EX_CLIENTEDGE)
$tviewPICon = GUICtrlCreateContextMenu($tviewPI)
$tviewPIConGetWks = GUICtrlCreateMenuItem("Get workstations", $tviewPICon)
$tviewPIConCheckReg = GUICtrlCreateMenuItem("Check Registry", $tviewPICon)
$tviewPIConCheckfiles = GUICtrlCreateMenuItem("Check for Files", $tviewPICon)
$tviewPIConGetProcessList = GUICtrlCreateMenuItem("Process List", $tviewPICon)
$tviewPIConGetUserProfiles = GUICtrlCreateMenuItem("Get User Profiles Names", $tviewPICon)
$MainMenu = GUICtrlCreateTreeViewItem("Workstation Organizational Units", $tviewPI)

;_AD_Open()
;$aOUs = _AD_GetAllOUs("OU=THR Workstations,DC=txhealth,DC=org")
;_ArrayDisplay($aOUs)
;_AD_Close()

;Test OU GRoup
$TestParentOU=GUICtrlCreateTreeViewItem("Test OU Group",$MainMenu)
;$tstou = _ArrayFindAll($aOUs,"OU=Test Workstation",0,0,0,1,1)
;For $i = 1 To UBound($tstou,1) - 1
$TestChildOU1=GUICtrlCreateTreeViewItem("test1",$TestParentOU)
$TestChildwks1=GUICtrlCreateTreeViewItem("wks1",$TestChildOU1)
$TestChildOU2=GUICtrlCreateTreeViewItem("test2",$TestParentOU)
$TestChildwks1=GUICtrlCreateTreeViewItem("wks2",$TestChildOU2)
;Next

GUICtrlSetColor(-1, 0x0000C0)
GUICtrlSetState($MainMenu, BitOR($GUI_EXPAND, $GUI_DEFBUTTON))
GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")
GUIRegisterMsg($WM_CONTEXTMENU, "_WM_CONTEXTMENU") ;display context menu only when list is in focus and selected an item

GUISetState(@SW_SHOW)

While 1
    sleep(100)

WEnd

Func _GUI_EVENT_CLOSE()
    Exit
EndFunc

Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam) ; Barrowed this works great
;~  ConsoleWrite('@@ (' & @ScriptLineNumber & ') :(' & @MIN & ':' & @SEC & ') WM_NOTIFY()' & @CR) ;### Function Trace
    #forceref $hWnd, $iMsg, $iwParam
    Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR, $hWndTreeView, $tInfo
    ;$hWndTreeView = $tviewPI
    If Not IsHWnd($tviewPI) Then $hWndTreeView = GUICtrlGetHandle($tviewPI)

    $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_RCLICK
                    $tInfo = DllStructCreate($tagNMITEMACTIVATE, $ilParam)
                    Local $tPoint, $tTVHEx, $TVhItem, $mX, $mY
                    $tPoint = _WinAPI_GetMousePos(True, $tviewPI)
                    $mX = DllStructGetData($tPoint, "X")
                    $mY = DllStructGetData($tPoint, "Y")
                    $TVhItem = _GUICtrlTreeView_HitTestItem($tviewPI, $mX, $mY)

                    _GUICtrlTreeView_SetFocused($tviewPI, $TVhItem)

                    $var = 0

                    $A = _GUICtrlTreeView_GetItemHandle($tviewPI, $TVhItem)
                    $B = _GUICtrlTreeView_GetParentHandle($tviewPI, $TVhItem)
                    $C = _GUICtrlTreeView_GetParentHandle($tviewPI, _GUICtrlTreeView_GetParentHandle($tviewPI, $TVhItem))

                    If $C = 0 And $B = 0 Then
                        $vLvl1 = _GUICtrlTreeView_GetText($tviewPI, $A)
                        $vLvl2 = ""
                        $vLvl3 = ""

                    ElseIf $C = 0 And $B <> 0 Then
                        $vLvl1 = _GUICtrlTreeView_GetText($tviewPI, $B)
                        $vLvl2 = _GUICtrlTreeView_GetText($tviewPI, $A)
                        $vLvl3 = ""

                    ElseIf $C <> 0 And $B <> 0 Then
                        $vLvl1 = _GUICtrlTreeView_GetText($tviewPI, $C)
                        $vLvl2 = _GUICtrlTreeView_GetText($tviewPI, $B)
                        $vLvl3 = _GUICtrlTreeView_GetText($tviewPI, $A)
                    EndIf

                   ToolTip ("$A: " & $A & @CRLF & "$B: " & $B & @CRLF & "$C: " & $C & @CRLF & @CRLF & $vLvl1 & @CRLF & $vLvl2 & @CRLF & $vLvl3, 0, 0)

    EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY

Func GetWorkstations($getObject)
    Global $workstationnames = _AD_GetObjectsInOU($getObject, "(&(objectcategory=computer)(objectclass=computer))", 2, "name")
    _ArrayDisplay($workstationnames)
EndFunc

Func _WM_CONTEXTMENU($hwnd, $iMsg, $wParam, $lParam); Not sure how to get this right
    #forceref $hWnd, $iMsg, $wParam, $lParam
    If $wParam <> GUICtrlGetHandle($tviewPICon) Then Return $GUI_RUNDEFMSG
    Local $cursor = GUIGetCursorInfo($mainform)
    Return $GUI_RUNDEFMSG
EndFunc   ;==>_WM_CONTEXTMENU
Link to comment
Share on other sites

I use MessageLoop mode to handle the input and clicks to my GUI. So handling the context menu was quite easy.

So your script would look like:

#include <Misc.au3>
#include <GUIConstants.au3>
#Include <GuiTreeView.au3>
#include <TreeviewConstants.au3>
#include <WindowsConstants.au3>
#Include <WinAPI.au3>
#include <AD.au3>
#include <array.au3>
#include <StaticConstants.au3>
#Include <WinAPI.au3>

$mainform = GUICreate("Organizational Tree", 600, 900)
$tviewPI = GUICtrlCreateTreeView(10, 10, 580, 880, BitOR($TVS_HASBUTTONS, $TVS_HASLINES, $TVS_LINESATROOT, $TVS_DISABLEDRAGDROP, $TVS_SHOWSELALWAYS), $WS_EX_CLIENTEDGE)
$tviewPICon = GUICtrlCreateContextMenu($tviewPI)
$tviewPIConGetWks = GUICtrlCreateMenuItem("Get workstations", $tviewPICon)
$tviewPIConCheckReg = GUICtrlCreateMenuItem("Check Registry", $tviewPICon)
$tviewPIConCheckfiles = GUICtrlCreateMenuItem("Check for Files", $tviewPICon)
$tviewPIConGetProcessList = GUICtrlCreateMenuItem("Process List", $tviewPICon)
$tviewPIConGetUserProfiles = GUICtrlCreateMenuItem("Get User Profiles Names", $tviewPICon)
$MainMenu = GUICtrlCreateTreeViewItem("Workstation Organizational Units", $tviewPI)

;_AD_Open()
;$aOUs = _AD_GetAllOUs("OU=THR Workstations,DC=txhealth,DC=org")
;_ArrayDisplay($aOUs)
;_AD_Close()

;Test OU GRoup
$TestParentOU=GUICtrlCreateTreeViewItem("Test OU Group",$MainMenu)
;$tstou = _ArrayFindAll($aOUs,"OU=Test Workstation",0,0,0,1,1)
;For $i = 1 To UBound($tstou,1) - 1
$TestChildOU1=GUICtrlCreateTreeViewItem("test1",$TestParentOU)
$TestChildwks1=GUICtrlCreateTreeViewItem("wks1",$TestChildOU1)
$TestChildOU2=GUICtrlCreateTreeViewItem("test2",$TestParentOU)
$TestChildwks1=GUICtrlCreateTreeViewItem("wks2",$TestChildOU2)
;Next

GUICtrlSetColor(-1, 0x0000C0)
GUICtrlSetState($MainMenu, BitOR($GUI_EXPAND, $GUI_DEFBUTTON))
GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")
GUISetState(@SW_SHOW)
While 1
    $Msg = GUIGetMsg()
    Select
        Case $Msg = $GUI_EVENT_CLOSE
            Exit
        Case $Msg = $tviewPIConGetWks
            MsgBox(0,"","Get workstations")
        Case $Msg = $tviewPIConCheckReg
            MsgBox(0,"","Check Registry")
    EndSelect
WEnd

Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam) ; Barrowed this works great
;~ ConsoleWrite('@@ (' & @ScriptLineNumber & ') :(' & @MIN & ':' & @SEC & ') WM_NOTIFY()' & @CR) ;### Function Trace
    #forceref $hWnd, $iMsg, $iwParam
    Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR, $hWndTreeView, $tInfo
    ;$hWndTreeView = $tviewPI
    If Not IsHWnd($tviewPI) Then $hWndTreeView = GUICtrlGetHandle($tviewPI)

    $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_RCLICK
    $tInfo = DllStructCreate($tagNMITEMACTIVATE, $ilParam)
    Local $tPoint, $tTVHEx, $TVhItem, $mX, $mY
    $tPoint = _WinAPI_GetMousePos(True, $tviewPI)
    $mX = DllStructGetData($tPoint, "X")
    $mY = DllStructGetData($tPoint, "Y")
    $TVhItem = _GUICtrlTreeView_HitTestItem($tviewPI, $mX, $mY)

    _GUICtrlTreeView_SetFocused($tviewPI, $TVhItem)

    $var = 0

    $A = _GUICtrlTreeView_GetItemHandle($tviewPI, $TVhItem)
    $B = _GUICtrlTreeView_GetParentHandle($tviewPI, $TVhItem)
    $C = _GUICtrlTreeView_GetParentHandle($tviewPI, _GUICtrlTreeView_GetParentHandle($tviewPI, $TVhItem))

    If $C = 0 And $B = 0 Then
    $vLvl1 = _GUICtrlTreeView_GetText($tviewPI, $A)
    $vLvl2 = ""
    $vLvl3 = ""

    ElseIf $C = 0 And $B <> 0 Then
    $vLvl1 = _GUICtrlTreeView_GetText($tviewPI, $B)
    $vLvl2 = _GUICtrlTreeView_GetText($tviewPI, $A)
    $vLvl3 = ""

    ElseIf $C <> 0 And $B <> 0 Then
    $vLvl1 = _GUICtrlTreeView_GetText($tviewPI, $C)
    $vLvl2 = _GUICtrlTreeView_GetText($tviewPI, $B)
    $vLvl3 = _GUICtrlTreeView_GetText($tviewPI, $A)
    EndIf

    ToolTip ("$A: " & $A & @CRLF & "$B: " & $B & @CRLF & "$C: " & $C & @CRLF & @CRLF & $vLvl1 & @CRLF & $vLvl2 & @CRLF & $vLvl3, 0, 0)

    EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc ;==>WM_NOTIFY

Func GetWorkstations($getObject)
    Global $workstationnames = _AD_GetObjectsInOU($getObject, "(&(objectcategory=computer)(objectclass=computer))", 2, "name")
    _ArrayDisplay($workstationnames)
EndFunc

As an example the first two entries of your context menu create a message box.

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 Water!

I did notice a little issue, I need to be able to collect 2 items when I goto the switch, one the selected OU and the Selected ContextMenu item, together I can run the function.

Func GetWorkstations($getObject)

Global $workstationnames = _AD_GetObjectsInOU($getObject, "(&(objectcategory=computer)(objectclass=computer))", 2, "name")

_ArrayDisplay($workstationnames)

EndFunc

I hope you understand what I need. I notice the Workstation

If you run it you notice it seem to lag in the data between right clicking and selecting the function, I mean the right click displays the last OU selected not the current OU selected.

I was thinking maybe I needed an additional layer tell me if I made the changes correctly for adding a 4th layer

_GUICtrlTreeView_SetFocused($tviewPI, $TVhItem)

    $var = 0

    $A = _GUICtrlTreeView_GetItemHandle($tviewPI, $TVhItem)
    $B = _GUICtrlTreeView_GetParentHandle($tviewPI, $TVhItem)
    $C = _GUICtrlTreeView_GetParentHandle($tviewPI, _GUICtrlTreeView_GetParentHandle($tviewPI, $TVhItem))
    $D = _GUICtrlTreeView_GetParentHandle($tviewPI, _GUICtrlTreeView_GetParentHandle($tviewPI, _GUICtrlTreeView_GetParentHandle($tviewPI, $TVhItem)))
    If $D = 0 And $C = 0 And $B = 0 Then
    $vLvl1 = _GUICtrlTreeView_GetText($tviewPI, $A)
    $vLvl2 = ""
    $vLvl3 = ""
    $vLvl4 = ""

    ElseIf $D = 0 And $C = 0 And $B <> 0 And $A <> 0 Then
    $vLvl1 = _GUICtrlTreeView_GetText($tviewPI, $B)
    $vLvl2 = _GUICtrlTreeView_GetText($tviewPI, $A)
    $vLvl3 = ""
    $vLvl4 = ""

    ElseIf $D = 0 And $C <> 0 And $B <> 0 And $A <> 0 Then
    $vLvl1 = _GUICtrlTreeView_GetText($tviewPI, $C)
    $vLvl2 = _GUICtrlTreeView_GetText($tviewPI, $B)
    $vLvl3 = _GUICtrlTreeView_GetText($tviewPI, $A)
    $vLvl4 = ""

    ElseIf $D <> 0 And $C <> 0 And $B <> 0 And $A <> 0 Then
    $vLvl1 = _GUICtrlTreeView_GetText($tviewPI, $D)
    $vLvl2 = _GUICtrlTreeView_GetText($tviewPI, $C)
    $vLvl3 = _GUICtrlTreeView_GetText($tviewPI, $B)
    $vLvl4 = _GUICtrlTreeView_GetText($tviewPI, $A)
    EndIf

thanks in Advance

Edited by RogFleming
Link to comment
Share on other sites

... I mean the right click displays the last OU selected not the current OU selected ...

I noticed the same problem in one of my applications. I searched the forum but couldn't find a solution.

I think opening a new thread and ask something like "How to get the item I right clicked in a TreeView" should return some helpful information.

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

  • Recently Browsing   0 members

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