Jump to content

Active Directory UDF (II)


water
 Share

Recommended Posts

There does not seem to be a function in the UDF to delete objects that have children (leaf nodes).  We have a security product in our organization that inserts child objects into computer containers, which makes it impossible to delete the computers from Active Directory using the _AD_DeleteObject function in this UDF, which calls the "Delete" method.  To make this work, you have to call the "DeleteObject" method, which seems to use different semantics.  I implemented it here:

 

; #FUNCTION# ====================================================================================================================
; Name...........: _AD_DeleteObjectWithChildren
; Description ...: Deletes the specified object.  Works on objects with children (leaf nodes) and without children.
; Syntax.........: _AD_DeleteObject($sObject)
; Parameters ....: $sObject - Object (user, group, computer etc.) to delete (FQDN or sAMAccountName)
; Return values .: Success - 1
;                  Failure - 0, sets @error to:
;                  |1 - $sObject does not exist
;                  |x - Error returned by Delete function (Missing permission etc.)
; Author ........: toasterking (partially based on _AD_DeleteObject() by Jonathan Clelland; modified by water)
; Modified.......:
; Remarks .......:
; Related .......: _AD_DeleteObject, _AD_RenameObject, _AD_MoveObject
; Link ..........: https://msdn.microsoft.com/en-us/library/aa705994(v=vs.85).aspx
; Example .......: No
; ===============================================================================================================================
Func _AD_DeleteObjectWithChildren($sObject)
    If Not _AD_ObjectExists($sObject) Then Return SetError(1, 0, 0)
    If StringMid($sObject, 3, 1) <> "=" Then $sObject = _AD_SamAccountNameToFQDN($sObject) ; sAMAccountName provided
    Local $oAdBind = $__oAD_OpenDS.OpenDSObject("LDAP://" & $sObject, $sADAdminUser, $sADAdminPassword, $__bAD_BindFlags)
    If @error Or Not IsObj($__oAD_Bind) Then ; login error occurred - get extended information
        Local $iError = @error
        Local $sHive = "HKLM"
        If @OSArch = "IA64" Or @OSArch = "X64" Then $sHive = "HKLM64"
        Local $sOSVersion = RegRead($sHive & "\SOFTWARE\Microsoft\Windows NT\CurrentVersion", "CurrentVersion")
        $sOSVersion = StringSplit($sOSVersion, ".")
        If Int($sOSVersion[1]) >= 6 Then ; Delivers detailed error information for Windows Vista and later if debugging is activated
            Local $aErrors = _AD_GetLastADSIError()
            If $aErrors[4] <> 0 Then
                If $__iAD_Debug = 1 Then ConsoleWrite("_AD_Open: " & _ArrayToString($aErrors, @CRLF, 1) & @CRLF)
                If $__iAD_Debug = 2 Then MsgBox(64, "Active Directory Functions - Debug Info - _AD_Open", _ArrayToString($aErrors, @CRLF, 1))
                If $__iAD_Debug = 3 Then FileWrite($__sAD_DebugFile, @YEAR & "." & @MON & "." & @MDAY & " " & @HOUR & ":" & @MIN & ":" & @SEC & " " & @CRLF & _
                        "-------------------" & @CRLF & "_AD_Open: " & _ArrayToString($aErrors, @CRLF, 1) & @CRLF & _
                        "========================================================" & @CRLF)
                Return SetError(Dec($aErrors[4]), 0, 0)
            EndIf
            Return SetError(8, $iError, 0)
        Else
            Return SetError(8, $iError, 0)
        EndIf
    EndIf

    Local $vResult = $oAdBind.DeleteObject(0) ;This actually does the magic of deleting an object that has children. Method takes a single parameter and only 0 is valid.
    If @error Then Return SetError(@error,666,0)
    Return 1
EndFunc

 

Edit:  And by "implemented", I mean I found code that Jonathan Clelland and water wrote and monkeyed it until it worked for me, as I'm standing on the shoulders of giants here.

Edited by toasterking
Clarifying my unworthiness
Link to comment
Share on other sites

Thanks for this function :)

I'm thinking about to extend the UDF with a function to delete objects plus leaf nodes and OUs including all contained objects/leafs/subOUs.
This function will be based upon your function plus the ideas I found here: http://www.selfadsi.org/delete.htm

What do you (and others) think? Is such a function needed?
If yes, is anyone willing to test on a test system? I'm an ordinary user so only have read access to our AD :( 

Please click the "Like this" button in the lower right corner of this post. So I know how many of you would like to see this function implemented. 

Edited by water

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2024-07-28 - Version 1.6.3.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 (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

Personally, the function I posted is all I have needed beyond the many already included with your UDF.  But what you suggested might be useful to others.  Unfortunately, the only Active Directory installation I have access to at the moment is my employer's production system, which I cannot use for testing.

I first started down the path of enumerating every child object and deleting it, then deleting the parent, but found that some objects are more difficult to enumerate and reference, and I probably just didn't know enough about what I was doing.  I couldn't get the DeleteObject method working at first, but it got a lot easier once I figured out how to bind directly to the object I wanted to delete using the right credentials.

Thank you for continuing to maintain this UDF.  It has really helped us out!  :)

Link to comment
Share on other sites

:) 

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2024-07-28 - Version 1.6.3.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 (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

_AD_DeleteSubtree: Allows to

  • delete an object and all children of the object as described in post #101
  • delete an OU including all objects and child OUs.
  • delete all objects in an OU and all child OUs but leave the OUs intact. Means the tree remains unchanged but all contained objects get deleted (clears the tree)

The example does not delete any objects.
It just writes a tree of processed objects to the SciTE console and adds a prefix whether the object will be deleted or remains unchanged.
To make it run modify line #9 marked with "<=== MODIFY".
What do you think?

Is anyone able to test the function on a test system? So that a bug does not cause any harm?

Spoiler

 

#include <AD.au3>
Global $sBlank = "                                "

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

; Delete Subtree
Global $sReturn = _AD_DeleteSubtree("OU=XX,DC=XX,DC=XX") ; <=== MODIFY
If @error Then Exit MsgBox(16, "Active Directory Example Skript", "Function _AD_DeleteSubtree encountered a problem. @error = " & @error & ", @extended = " & @extended & ", return value = " & $sReturn)

; Close Connection to the Active Directory
_AD_Close()

Exit

; #FUNCTION# ====================================================================================================================
; Name...........: _AD_DeleteSubtree
; Description ...: Deletes the specified object including all leafs of this object.
; Syntax.........: _AD_DeleteSubtree($sObject[, $iFlag = 0])
; Parameters ....: $sObject - Object (user, group, computer, OU etc.) to delete (FQDN or sAMAccountName)
;                  $iFlag   - [optional] Specifies how to process leaf objects. Can be:
;                  | 0 - Delete the object, all containedOUs and objects
;                  | 1 - Only delete contained objects. The object and all contained OUs remain active. Means: The subtree will be cleared.
; Return values .: Success - 1
;                  Failure - The distinguishedName of the object raising the error, sets @error to:
;                  |1 - $sObject does not exist
;                  |2 - Error returned by DeleteObject method for an object (Missing permission etc.). @extended holds the COM error code.
;                  |3 - Error returned by DeleteObject method for an OU (Missing permission etc.). @extended holds the COM error code.
; Author ........: water
; Modified.......:
; Remarks .......:
; Related .......: _AD_RenameObject, _AD_MoveObject, _AD_DeleteObject
; Link ..........:
; Example .......: Yes
; ===============================================================================================================================
Func _AD_DeleteSubtree($sObject, $iFlag = 0, $iRecursion = 0)

    ; Only check the object provided by the user (performance reasons). Values: 0 = first call by user, 1 = recursive call
    If $iRecursion = 0 Then
        If Not _AD_ObjectExists($sObject) Then Return SetError(1, 0, $sObject)
        If StringMid($sObject, 3, 1) <> "=" Then $sObject = _AD_SamAccountNameToFQDN($sObject) ; sAMAccountName provided
    EndIf
    Local $oObject = __AD_ObjGet("LDAP://" & $sAD_HostServer & "/" & $sObject)
    Local $sClass = $oObject.Class
    If $sClass = "organizationalUnit" Then
        If $iFlag = 1 Then
            ConsoleWrite("REMAINS: " & StringLeft($sBlank, $iRecursion * 2) & $sObject & @CRLF)
        Else
            ConsoleWrite("DELETED: " & StringLeft($sBlank, $iRecursion * 2) & $sObject & @CRLF)
        EndIf
        For $oChild In $oObject
            _AD_DeleteSubtree($oChild.distinguishedName, $iFlag, $iRecursion + 1)
            If @error Then Return SetError(@error, @extended, $sObject)
        Next
        If $iFlag <> 1 Then
            ; OUs will not get deleted when $iFlag = 1 (clear subtree)
;~ TESTING: $oObject.DeleteObject(0)
            If @error Then Return SetError(3, @error, $sObject)
        EndIf
    Else
        ConsoleWrite("DELETED: " & StringLeft($sBlank, $iRecursion * 2) & $sObject & @CRLF)
        ; Objects will always be deleted
;~ TESTING: $oObject.DeleteObject(0)
        If @error Then Return SetError(2, @error, $sObject)
    EndIf
    Return 1

EndFunc   ;==>_AD_DeleteSubtree

 

Edited by water

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2024-07-28 - Version 1.6.3.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 (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 months later...

Hi, im just wondering why this will not work?
If it has a mail it returns the mail adress, but if its empty, it just writes ERROR in console:
 

$oObject.Get($sAttribute)
$oObject^ ERROR

Here is the code:
 

#include <AD.au3>
_AD_Open()
$ADmail = _AD_GetObjectAttribute(@username, "mail")
ConsoleWrite($ADmail)
_AD_Close()
If $ADmail == "" Then MsgBox(64, "Warning", "Mail attribute is missing")

 

Link to comment
Share on other sites

Which version of AutoIt do you run?
Which version of the AD UDF do you run?

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2024-07-28 - Version 1.6.3.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 (2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki

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

Tutorials:
ADO - Wiki
WebDriver - Wiki

 

Link to comment
Share on other sites

19 hours ago, water said:

Which version of AutoIt do you run?
Which version of the AD UDF do you run?

SciTE
Version 3.7.3

I tought i was on the latest AD  UDF, but now i updated to 1.4.8.0 and its working.

Thank you.
 

Link to comment
Share on other sites

:) 

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2024-07-28 - Version 1.6.3.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 (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 weeks later...

Hi Water

I am using your ad.au3 a lot and it works fantastic.
Today I got an error when I read the object properties from an AD user.

error message: Array variable has incorrect number of subscripts or subscript dimension range exceeded.

For $vPropertyValue In $oPropertyEntry.Values
   $iPropertyRecord = $iPropertyRecord + 1
   $aObjectProperties[$iPropertyRecord][0] = $sPropertyName

This peace of code is locate in your ad.au3 file.

 

Function:

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

 Local $aObjectProperties[1000][2], $oObject

 

It works fine after increasing the array declaration to:  Local $aObjectProperties[2000][2].

 

Br. Ivo

 

 

 

Edited by Ivo

Ivo

Link to comment
Share on other sites

So there is an object with > 1000 properties.
Seems that I need to brush up the function for a variable number of properties :)
 

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2024-07-28 - Version 1.6.3.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 (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

Next release will hold up to 10000 properties. That was the simplest solution ;) 

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2024-07-28 - Version 1.6.3.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 (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 apologize if this has been addressed before and I've searched the forum for _AD_GetObjectAttribute and _AD_GetObjectProperties but I'm coming up with nothing.  

If i run Get-ADUser theuser -Properties * | Select * in PowerShell, I get a full list of all properties for the user "theuser", including custom properties like OtherName .  If I run _AD_GetObjectProperties for that same user, I do not see the custom property OtherName listed.  As such, I get errors or empty results when trying to use _AD_GetObjectAttribute or _AD_GetObjectProperties to return the data stored in OtherName.

Is there something I'm missing as far as a setting to have _AD_GetObjectAttribute and _AD_GetObjectProperties return info on custom properties in AD?

Thanks.

ETA - Solved my own problem.  User error!  The properties that I thought were custom seem to be duplicates of existing properties.  When I made a change to what I'm calling the master property, the secondary property changed as well.

Edited by DFWITGuy
Link to comment
Share on other sites

Never had to cope with custom properties before.
Can you make sure that a LDAP query returns the custom properties?
Something like:

dsquery * -Filter "(&(objectCategory=person)(objectClass=User)(cn=theuser))" -Attr YourCustomProperty

 

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2024-07-28 - Version 1.6.3.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 (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 asking, water.  I'm getting expected results from the OtherName property when I run the following:

dsquery * "user's distinguished name" -scope base -attr sAMAccountName OtherName

sAMAccountName shows JDoe and OtherName shows Jane as expected.

Ran dsquery * "user's distinguished name" -attr * to see what all is displayed and OtherName appears in the list.

ETA - Solved my own problem.  User error!

Edited by DFWITGuy
pasted wrong word
Link to comment
Share on other sites

Sure. Use _AD_GetObjectsInOU.

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2024-07-28 - Version 1.6.3.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 (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

:)

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2024-07-28 - Version 1.6.3.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 (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

"mail" is the address to use when sending mails.
"proxyaddresses" gives additional information about SMTP and X400 addresses.

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2024-07-28 - Version 1.6.3.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 (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...