Thursday, April 19, 2012

Autoit - Moving Computers in Active Directory

We've just had a new building built, with lots of nice new rooms for members of staff to live in. Naturally current staff have already staked their claims to rooms, and as such its up to IT Services to move the computer equipment over to the new offices.

Obviously we've done this a few times before and we usually forget to change where the computers are in Active Directory. If you've got a structure based on room layout, then when a computer moves rooms or even to a different building then it needs moving in Active Directory as well. Like I said, we usually forget to move them, as we're normally very busy.

So I've been going round the net trying to find some free software that will pop up when one of IT log on to ask if we want to move the computer. Personally I didn't like any of them, so I decided to write my own in AutoIt.

This little program is based on the examples given in AD.au3 pack that I've talked about before. The program will start when a member of IT services logs on, and will initially ask if the computer they have logged on to has been moved. 'No' will exit the program, but 'yes' will taken them to a GUI with their Active Directory tree structure. If you then browse to the OU that you want the computer to be moved to and click 'Move Computer' it will move it for you. If you click Exit instead, the program will end. It will pop up with 2 confirmation boxes, the first checking that it is correct and the second will tell you either if its successful, or if it failed. Here's the code


#AutoIt3Wrapper_AU3Check_Parameters= -d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6
#AutoIt3Wrapper_AU3Check_Stop_OnWarning=Y

#include <AD.au3>
#include <TreeviewConstants.au3>
#include <WindowsConstants.au3>
#include <GUIConstants.au3>
#include <GuiTreeView.au3>
#include <ButtonConstants.au3>
#include <GUIConstantsEx.au3>

_AD_Open()
Global $Reply = MsgBox(4,"Moved computer", "Have you moved this computer?")
If $Reply <> 6 Then Exit
  
Global $newOU = ""
Global $sTitle = "Move that stupid Computer v1.3"
Global $hMain = GUICreate($sTitle, 743, 683, -1, -1)
Global $IObject = GUICtrlCreateInput(_AD_SamAccountNameToFQDN(@ComputerName& "$"), 8, 30, 559, 21)

Global $hTree = GUICtrlCreateTreeView(6, 100, 600, 400, -1, $WS_EX_CLIENTEDGE)
Global $bExit = GUICtrlCreateButton("Exit", 624, 8, 97, 33)
Global $BOK = GUICtrlCreateButton("Move Computer", 624, 200, 97, 33)
Global $aTreeView = _AD_GetOUTreeView($newOU, $hTree)

GUICtrlCreateLabel("Object to move (FQDN or sAMAccountName):", 8, 10, 231, 17)
GUISetState(@SW_SHOW)

While 1
    Global $nMsg = GUIGetMsg()
    Switch $nMsg
        Case $GUI_EVENT_CLOSE, $BExit
            Exit
        Case $BOK
            Global $sObject = GUICtrlRead($IObject)
           
            $hSelection = _GUICtrlTreeView_GetSelection($hTree)
            $sSelection = _GUICtrlTreeView_GetText($hTree, $hSelection)
            For $i = 1 To $aTreeView[0][0]
                If $hSelection = $aTreeView[$i][2] Then ExitLoop
            Next
            $sOU = $aTreeView[$i][1]
            msgbox(1,"","Currently - "&$sObject&" target - "&$sOU)
            ExitLoop
    EndSwitch
WEnd

; Move object
Global $iValue = _AD_MoveObject($sOU, $sObject)
If $iValue = 1 Then
    MsgBox(64, "Active Directory Functions - Example 1", "Object '" & $sObject & "' successfully moved to '" & $sOU & "'")
ElseIf @error = 1 Then
    MsgBox(64, "Active Directory Functions - Example 1", "Target OU '" & $sOU & "' does not exist")
ElseIf @error = 2 Then
    MsgBox(64, "Active Directory Functions - Example 1", "Object '" & $sObject & "' does not exist")
Else
    MsgBox(64, "Active Directory Functions - Example 1", "Return code '" & @error & "' from Active Directory")
EndIf
_AD_Close()


Func _AD_GetOUTreeView($sAD_OU, $hAD_TreeView, $bAD_IsADOpen = True)

    If $bAD_IsADOpen = False Then
        _AD_Open()
        If @error Then Return SetError(@error, @extended, 0)
    EndIf
    $sSeparator = "\"
    Local $aAD_OUs = _AD_GetAllOUs($sAD_OU, $sSeparator)
    If @error <> 0 Then Return SetError(@error, @extended, 0)
    Local $aAD_TreeView[$aAD_OUs[0][0] + 1][3] = [[$aAD_OUs[0][0], 3]]
    For $i = 1 To $aAD_OUs[0][0]
        $aAD_Temp = StringSplit($aAD_OUs[$i][0], $sSeparator)
        $aAD_TreeView[$i][0] = StringFormat("%" & $aAD_Temp[0] - 1 & "s", "") & "#" & $aAD_Temp[$aAD_Temp[0]]
        $aAD_TreeView[$i][1] = $aAD_OUs[$i][1]
    Next
    If $bAD_IsADOpen = False Then _AD_Close()

    _GUICtrlTreeView_BeginUpdate($hAD_TreeView)
    Local $ahAD_Node[50]
    For $iAD_Index = 1 To $aAD_TreeView[0][0]
        $sAD_Line = StringSplit(StringStripCR($aAD_TreeView[$iAD_Index][0]), @TAB)
        $iAD_Level = StringInStr($sAD_Line[1], "#")
        If $iAD_Level = 0 Then ExitLoop
        If $iAD_Level = 1 Then
            $ahAD_Node[$iAD_Level] = _GUICtrlTreeView_Add($hAD_TreeView, 0, StringMid($sAD_Line[1], $iAD_Level + 1))
            $aAD_TreeView[$iAD_Index][2] = $ahAD_Node[$iAD_Level]
        Else
            $ahAD_Node[$iAD_Level] = _GUICtrlTreeView_AddChild($hAD_TreeView, $ahAD_Node[$iAD_Level - 1], StringMid($sAD_Line[1], $iAD_Level + 1))
            $aAD_TreeView[$iAD_Index][2] = $ahAD_Node[$iAD_Level]
        EndIf
    Next
    _GUICtrlTreeView_EndUpdate($hAD_TreeView)
    Return $aAD_TreeView

EndFunc

It should work for you, I see no reason why not, but please remember that this will change your Active Directory. Please make sure you test it first. I'm not being held responsible for messing up your AD.

No comments: