Johny Clelland

Active Members
  • Content count

  • Joined

  • Last visited

Johny Clelland's Activity

  1. Johny Clelland added a post in a topic: Active Directory UDF   


    I'm back again...apologies for my absence.

    Congratulations on your fabulous work! I'm very impressed with the conversion to UDF format that you've carried out. I could never have managed all this (there's only so many hours in the day).

    Have you thought about how to convert old scripts to the UDF versions? I'll have a look and see if there's any simple way of doing it. I have rather a lot of scripts that use my original 'include' file, and it would probably make sense to convert to using your UDF, but I don't fancy manually modifying 9500+ lines of code.

    I'll have a play with the new UDF version and see if I can't figure out a simple way of converting. I guess I'll need to consult your version history to see what changes have occurred to functions over the course of your work.

    I think since we last spoke I've only added one further function to my own copy. This is a way to add additional SMTP addresses to an Exchange-enabled account. I also have code for Removing/Editing these, though I haven't formalised it into ADFunctions yet.

    Here's my attempt at making the code compatible with your UDF format, let me know if you need anything else.

    ; #FUNCTION# ==================================================================================================================== ; Name...........: _AD_AddEmailAddress ; Description ...: Add an additional SMTP email address to the 'Email Addresses' tab of an Exchange-enabled AD account ; Syntax.........: _AD_AddEmailAddress($sAD_User, $sAD_newemail[, $fAD_primary = False]) ; Parameters ....: $sAD_User - User account (sAMAccountName or FQDN) ; $sAD_newemail - Email address to add to the account ; $fAD_Flag - Optional: if TRUE the new email address will be set as primary address ; Return values .: Success - 1 ; Failure - 0, @error set ; |1 - $sAD_User does not exist ; |2 - Could not connect to $sAD_User ; Author ........: Jonathan Clelland ; Modified.......: ; Remarks .......: ; Related .......: ; Link ..........: ; Example .......: No ; =============================================================================================================================== Func _AD_AddEmailAddress($sAD_User, $sAD_newemail, $fAD_primary = False) If _AD_ObjectExists($sAD_User) = 0 Then Return SetError(1, 0, 0) If StringMid($sAD_User, 3, 1) <> "=" Then $sAD_User = _AD_SamAccountNameToFQDN($sAD_User) ; sAMAccountName provided Local $oAD_User = _ADObjGet("LDAP://" & $sAD_HostServer & "/" & $sAD_User) If Not IsObj($oAD_User) Then MsgBox(0, "Error!", "An error occurred attaching to the user object '" & $sAD_User & "'.") Return SetError(2, 0, 0) EndIf Local $aAD_proxyaddresses = $oAD_User.GetEx("proxyaddresses") If $fAD_primary Then For $i = 0 To UBound($aAD_proxyaddresses) - 1 If StringInStr($aAD_proxyaddresses[$i], "SMTP:", 1) Then $aAD_proxyaddresses[$i] = StringReplace($aAD_proxyaddresses[$i], "SMTP:", "smtp:", 0, 1) EndIf Next _ArrayAdd($aAD_proxyaddresses, "SMTP:" & $sAD_newemail) $oAD_User.Put("mail", $sAD_newemail) Else _ArrayAdd($aAD_proxyaddresses, "smtp:" & $sAD_newemail) EndIf $oAD_User.PutEx(2, "proxyaddresses", $aAD_proxyaddresses) $oAD_User.SetInfo If @error <> 0 Then Return SetError(@error, 0, 0) Return 1 EndFunc
    And here's an example of how to use it;

    ; ***************************************************************************** ; Example 1 ; Add an email address to a user ; ***************************************************************************** #include <AD.au3> #include <ButtonConstants.au3> #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> ; Open Connection to the Active Directory _AD_Open() $iReply = MsgBox(308, "Active Directory Functions - Example 1", "This script adds an email address to a user." & @CRLF & @CRLF & _ "Are you sure you want to change the Active Directory?") If $iReply <> 6 Then Exit ; Enter user account and description #Region ### START Koda GUI section ### Form= $Form1 = GUICreate("Active Directory Functions - Example 1", 514, 124) GUICtrlCreateLabel("User account (samAccountName or sAMAccountName):", 8, 10, 231, 34) GUICtrlCreateLabel("New email address:", 8, 42, 231, 17) $IUser = GUICtrlCreateInput(@UserName, 241, 8, 259, 21) $IEmail = GUICtrlCreateInput("", 241, 40, 259, 21) $BOK = GUICtrlCreateButton("Add address", 8, 72, 121, 33) $BCancel = GUICtrlCreateButton("Cancel", 428, 72, 73, 33, BitOR($GUI_SS_DEFAULT_BUTTON, $BS_DEFPUSHBUTTON)) GUISetState(@SW_SHOW) #EndRegion ### END Koda GUI section ### While 1 $nMsg = GUIGetMsg() Switch $nMsg Case $GUI_EVENT_CLOSE, $BCancel Exit Case $BOK $sUser = GUICtrlRead($IUser) $sEmail = GUICtrlRead($IEmail) ExitLoop EndSwitch WEnd ; Change attribute $iValue = _AD_AddEmailAddress($sUser, $sEmail, True) If $iValue = 1 Then MsgBox(64, "Active Directory Functions - Example 1", "Email address for user '" & $sUser & "' successfully changed") ElseIf @error = 1 Then MsgBox(64, "Active Directory Functions - Example 1", "User '" & $sUser & "' does not exist") Else MsgBox(64, "Active Directory Functions - Example 1", "Return code '" & @error & "' from Active Directory") EndIf ; Close Connection to the Active Directory _AD_Close()
    Thanks again for all your hard work, as I say, the UDF version would never have been possible without you,


  2. Johny Clelland added a post in a topic: Make adfunctions.au3 an "official" AutoIt UDF   

    Hi guys,

    First of all, thanks for all the support for this function library. It's always nice to hear that people are benefitting from my work :-)

    Due to my own work commitments, I have been unable to put much time into any efforts to convert ADFunctions to a proper UDF. It was always my hope that it could be done, but I never had the time to learn how to do all the help file stuff, and it wasn't really a requirement for me so I couldn't justify doing it on company time.

    I'm more than happy to lend any assistance in making changes. I suspect that a couple of 'Global' variables in particular are going to have to be replaced with a _ADOpenConnection() type function (I'm thinking of the principle objects $objRootDSE and $objConnection here), and I'm not sure what the policy is on Error handling.

    Because ADFunctions relies on the error handling in _ADDoError() to report on certain 'known' Active Directory errors, it will need to be registered somehow.

    Please let me know if there's any help I can give, or if you have any questions about the functions. I am constantly creating new functions for my own projects, and will try and keep you updated with any new functions as they are written (no promises, as I do this at work and technically shouldn't ;-) )

    Thanks again,

  3. Johny Clelland added a post in a topic: Active Directory Scripts   

    Hi DevilMan,

    You are correct that the format of that OU structure is wrong in the comments for CreateUser and CreateGroup. I will update the comments next time I upload the code.

    The reason you are getting the user created as Disabled is because this is the default when you call a create function in this manner. To resolve, simply use _ADEnableAccount to enable the account after creation.

    You are getting Description of 'FALSE' because you have performed a comparison in the description argument '$description = "User"', where you should just have put the $description variable you setup.

    It would also appear that I never actually set the FName and LName fields, just used these to create the full name of 'LName, FName'.

    Add these two lines to the function, under the $ObjUser.Put("description... line to add these;

    $ObjUser.Put("givenName", $fname)
    $ObjUser.Put("sn", $lname)

    That should add those to attributes during creation.

    Let me know if this helps,


  4. Johny Clelland added a post in a topic: Active Directory Scripts   

    Hi Prophet,

    Always nice to hear good things about my scripts :-)

    On the note of alternative logon credentials, the Functions library has two ways of dealing with this.

    Firstly, look at _ADAlternativeLogon on line 1852. That does the equivalent of your code below, although as you have pointed out it is not secure (I'll add this to the next version).

    Secondly, to enable _ADObjGet to use alternative credentials, simply set the Global variables $alt_userid and $alt_password to the relevant ID. I'm not sure if this logon is secure or not, there's a BitOr in there which may or may not be for secure connections. It's that long since I wrote those bits of code I'm not certain what that last argument does.

    Hope this helps, and thanks for the suggestions about making it secure. I'm not sure what to do about running it on a non-domain PC, as I never thought you would need to use it outside of a domain.


  5. Johny Clelland added a post in a topic: Active Directory Scripts   


    Attached is my suggested vesion 3.3.1. UPDATE - Updated to 3.3.2 to remove a reference to an external include file (DoProgress.au3)

    It has the additions by KenE, and my recent updates. The only thing I haven't included is the _ADComputerExists function, as it is not required. The claim is that _ADObjectExists doesn't work for computer objects, but it does. You just need to note that the SamAccountName of a computer account is the computer's name with a '$' on the end, so to check for a computer you use;

    If _ADObjectExists("mycomputer$") Then
    MsgBox(0,"","MyComputer exists!")
    MsgBox(0,"","MyComputer doesn't exist :-(")

    I've had a couple of requests about unlocks and password resets which i'm planning to add as well.


  6. Johny Clelland added a post in a topic: Active Directory Scripts   

    Any chance you could point me in the direction of a link to the latest version on the forum? The search doesn't seem to find 3.1.6 anywhere :-(

  7. Johny Clelland added a post in a topic: Active Directory Scripts   


    I'm sorry I haven't been around for a while (hadn't realised it had been quite so long...)

    The function that GrayWalker wrote looks very similar to __ADSamAccountNameToFQDN, only with a restriction that it only works for computers.

    I have attached the version of ADFunctions that I currently use. I'm not sure how different it is from the original versions, I suspect it may cause some problems with people's existing code. I've tried to include what's been updated, but to be honest I haven't been great at keeping track of changes in this particular script.

    The most notable changes recently were to the Recursive GroupMembers and MemberOf functions, as they return slightly different data now (the results are still DNs, with inherited groups after '|' chars, but the list contains all of them now, not just the 'first' inherited group)

    Unfortunately I do not have access to W2k8 yet, so i can't develop anything in that direction. I am more than happy for someone else to take that particular task on ;-)

    Please feel free to play with this latest version and let me know if you have any problems.

    I promise I will try to respond to anything on this forum a little quicker this time.


    Latest Version -- Link
  8. Johny Clelland added a post in a topic: Active Directory Scripts   


    The problem here is that Computer's SamAccountName attribute in ADSI have a '$' symbol on the end of them. If you change the first line of your code to this;

    $object = @Computername & "$"
    Then it should work. The full code would look like this;

    $object = @ComputerName & "$" $result = _ADObjectExists($object) MsgBox(0,"",$result) $result = _ADSamAccountNametoFQDN($object) MsgBox(0,"",$result)
    Hope that helps.


  9. Johny Clelland added a post in a topic: Active Directory Scripts   

    This has now been fixed in the comments. v3.1.2 has been uploaded to the forums.

  10. Johny Clelland added a post in a topic: Active Directory Scripts   


    The only thing I can see that might be causing an issue is the syntax of the OU. I believe if you change the line

    $userou = "users=ou, 04unique=ou, GermanUSGGroup=dc ,local=dc"

    to something more like

    $userou = "ou=users,ou=04unique,dc=GermanUSGGROUP,dc=local"

    then this should fix the issue. From the error, I'm guessing that the ObjOU is never being generated because it can't open the OU Object from the variable you've passed it.

    Try that and let me know if it works.


  11. Johny Clelland added a post in a topic: Active Directory Scripts   

    The problem here is actually a bug in the ADFunctions.au3 code itself. Apologies for this, i've never noticed it before now because I never used the 'default' filter option after I wrote it.

    To fix the problem, change the Func line in ADFunctions to read like this;

    Func _ADGetObjectsInOU(ByRef $ObjectArray, $ou, $filter = "(name=*)", $searchscope = 2, $datatoretrieve = "sAMAccountName", $sortby = "sAMAccountName")

    You should Dim the array before calling the function, so that the function has somewhere to pass the data. An example would look like this;

    #include <adfunctions.au3> #include <array.au3> Dim $objectarray $ou = "ou=users,dc=mydomain,dc=com" _ADGetObjectsInOU($objectarray, $ou) _ArrayDisplay($objectarray)
    I can't seem to figure out how to use it at all. Do I have to create my own array or does it create one for me? If so, how would I display this array?

    I tried _ADGetObjectsInOU($ObjectArray, $ou) (I define the $ou variable as CN=Users,DC=vmtest,DC=local ) and the error I get:

    COM Error #: 000000A9
    Description: Variable must be of type "Object"
    Script Line #: 641 (in adfunctions.au3)

    Can anyone help?
  12. Johny Clelland added a post in a topic: Active Directory Scripts   

    The problem below is because the _ADIsMemberOf function requires full DN Syntax for both the group and the user. The easiest way to get this is to use _ADSamAccountNametoFQDN('samid') to return the fully qualified distinguished name of the objects.

    #include <adfunctions.au3> $domain_admins_dn = _ADSamAccountNametoFQDN("Domain Admins") $test_user_dn = _ADSamAccountNametoFQDN("Admin") If _ADIsMemberOf($domain_admins_dn, $test_user_dn) Then MsgBox(64, "", "True") EndIf
    Hope this helps, if you're still having problems let me know.


  13. Johny Clelland added a file in Libraries   

    ADFunctions.Au3 -- Active Directory Functions v
    UDF Library containing functions for manipulating data in Active Directory / Exchange
    • 0 reviews
  14. Johny Clelland added a post in a topic: Active Directory Scripts   

    This reply should have the latest version of ADFunctions attached.
  15. Johny Clelland added a post in a topic: Active Directory Scripts   

    Apologies for taking so long to get back to you. This error was caused by a change in ADFunctions where some functions changed from requiring SamAccountNames to FQDNs. Simple fix is to change the line that calls _ADGetGroupMembers to this;

    If _ADGetGroupMembers($Members, _ADSamAccountNametoFQDN($GroupName), 0) == 1 Then

    That sorts it out :-)

    Hope this helps,