Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Listing user accoutn attributes in many OUs 2

Status
Not open for further replies.

JPJeffery

Technical User
May 26, 2006
600
GB
I have a sub which is meant to go through all the user accounts in the AD domain and check a given username, and other details against them. However, all it's doing is listing the OUs, not the user account objects within them.
Code:
Set objDomain = GetObject("LDAP://" & conDomainName)

Sub TestForDuplicateSamAccountName
    wscript.echo " Test uniqueness of the username '" & strPre2kLogon & "'"
	For Each objUser In objDomain
        wscript.echo "Pre2KLogon  ='" & lcase(objUser.Name) & "'" & vbCrLf &_
                     "SamAccount  ='" & lcase(objUser.SAMAccountName) & "'" & vbCrLf &_
                     "CommonName  ='" & lcase(objUser.CN) & "'" & vbCrLf &_
                     "SMTP        ='" & lcase(objUser.Mail) & "'" & vbCrLf &_
                     "UPN         ='" & lcase(objUser.UserPrincipalName) & "'" & vbCrLf &_
                     "DisplayName ='" & lcase(objUser.DisplayName) & "'"
		If LCase(objUser.Name) = LCase(strPre2kLogon) Then
            wscript.echo " Duplicate account name found!"
            SuggestAlternativeName
            Exit Sub
		End If
	Next
	'wscript.quit
End Sub

This simpler version of the sub only uses the NT4 attributes but can't return the same details, although it does at least work as far as it goes:
Code:
Sub TestForDuplicateSamAccountName
    Dim objDomainNT
    Set objDomainNT = GetObject("WinNT://" & conDomainName)
    objDomainNT.Filter = Array("user")
    wscript.echo " Test uniqueness of the username '" & strPre2kLogon & "'" 'strUserName
	For Each objUser In objDomainNT
        wscript.echo "Pre2KLogon  ='" & lcase(objUser.Name) & "'"
        If LCase(objUser.Name) = LCase(strPre2kLogon) Then
            wscript.echo " Duplicate account name found!"
            SuggestAlternativeName
            Exit Sub
		End If
	Next
	wscript.quit
End Sub
What gives?

JJ
[small][purple]Variables won't. Constants aren't[/purple]
There is no apostrophe in the plural of PC (or PST, or CPU, or HDD, or FDD, and so on)[/small]
 
In your top example you are not executing a query of AD. You are binding to the domain but then don't query it for information.

Here is an example to get you started.

Code:
On Error Resume Next

Dim qQuery, objConnection, objCommand, objRecordSet, obj
Dim oRootDSE, strDomain

Set oRootDSE = GetObject("LDAP://rootDSE")
strDomain = oRootDSE.get("defaultNamingContext")

' other categories = computer, user, printqueue, group
qQuery = "<LDAP://" & strDomain &">;" & _
		"(objectCategory=person)" & _
       ";[red]name[/red];subtree"

Set objConnection = CreateObject("ADODB.Connection")
Set objCommand = CreateObject("ADODB.Command")
objConnection.Open "Provider=ADsDSOObject;"
objCommand.ActiveConnection = objConnection
objCommand.CommandText = qQuery
Set objRecordSet = objCommand.Execute

While Not objRecordSet.EOF
    Wscript.Echo objRecordSet.Fields("name")
    
    objrecordset.MoveNext
Wend

objConnection.Close

Notice the section in red. That is where you specify what other properties you want to return. Separate them with a comma.

I hope you find this post helpful.

Regards,

Mark

Check out my scripting solutions at
Work SMARTER not HARDER. The Spider's Parlor's Admin Script Pack is a collection of Administrative scripts designed to make IT Administration easier! Save time, get more work done, get the Admin Script Pack.
 
Mark to the rescue again. Do you ever let anyone else have a go?

;-)

That's working now, thanks.

JJ
[small][purple]Variables won't. Constants aren't[/purple]
There is no apostrophe in the plural of PC (or PST, or CPU, or HDD, or FDD, and so on)[/small]
 
Are you kidding? PHV and tsuji kick my butt in response times. I think they have a matrix interface or something similar.

I hope you find this post helpful.

Regards,

Mark

Check out my scripting solutions at
Work SMARTER not HARDER. The Spider's Parlor's Admin Script Pack is a collection of Administrative scripts designed to make IT Administration easier! Save time, get more work done, get the Admin Script Pack.
 
So, the function works BUT seemingly only for the first entry. Specifically, I'm testing the function's ability to check the SMTP address on the grounds that sometimes people change their name (through marriage/divorce) but may retain the old SMTP address in addition to the new SMTP address that reflects that name change.

So, Jo Smith (SMTP:smithj@acme.com) gets married and becomes Jo Bloggs (SMTP:bloggsj@acme.com) but to avoid missing some emails keeps the smithj address as a secondary address.

I need the script to flag up a conflict if a John Smith joins as he would be assigned SMTP:smithj@acme.com which would clash with Jo's SMTP secondary address. Right now, it's failing to do that as it seems to only be comparing against the primary SMTP address:
Code:
Sub TestForDuplicateSamAccountName '_ByLDAP
    Dim qQuery
    Dim objConnection
    Dim objCommand
    Dim objRecordSet

    ' other categories = computer, user, printqueue, group
    ' After the ObjectCategory semi-colon is listed the fields required from the namned category. 'name' is = 'CommonName'
    qQuery = "<LDAP://" & strDNSDomain &">;(objectCategory=person);name,UserPrincipalName,mail,DisplayName,SAMAccountName;subtree"

    Set objConnection = CreateObject("ADODB.Connection")
    Set objCommand = CreateObject("ADODB.Command")
    objConnection.Open "Provider=ADsDSOObject;"
    objCommand.ActiveConnection = objConnection
    objCommand.CommandText = qQuery
    Set objRecordSet = objCommand.Execute

    While Not objRecordSet.EOF
        Wscript.Echo " NAME : " & objRecordSet.Fields("name") & vbCrLf &_
                     "   UPN         : " & objRecordSet.Fields("UserPrincipalName") & vbCrLf &_
                     "   SMTP        : " & objRecordSet.Fields("mail") & vbCrLf &_
                     "   DisplayName : " & objRecordSet.Fields("DisplayName") & vbCrLf &_
                     "   SAM Account : " & objRecordSet.Fields("SAMAccountName")

        if lcase(strUserName) = lcase(objRecordSet.Fields("name")) then
            bDuplicateCommonName = True
            bDuplicateDetailFound = True
            wscript.echo " Duplicate CN/Account name found: " & strUserName
        end if

        if lcase(strPost2kLogon) = lcase(objRecordSet.Fields("UserPrincipalName")) then
            bDuplicateUserPrincipalName = True
            bDuplicateDetailFound = True
            wscript.echo " Duplicate UPN found: " & strPost2kLogon
        end if

        if lcase(strSMTP) = lcase(objRecordSet.Fields("mail")) then
            bDuplicateSMTP = True
            bDuplicateDetailFound = True
            wscript.echo " Duplicate SMTP address found: " & strSMTP
        end if

        if lcase(strUserName) = lcase(objRecordSet.Fields("DisplayName")) then
            bDuplicateDisplayName = True
            bDuplicateDetailFound = True
            wscript.echo " Duplicate DisplayName found: " & strUserName
        end if

        if lcase(strPost2kLogon) = lcase(objRecordSet.Fields("SAMAccountName")) then
            bDuplicateSamAccount = True
            bDuplicateDetailFound = True
            wscript.echo " Duplicate SAM Account name found: " & strPost2kLogon
        end if

        objrecordset.MoveNext
    Wend

    objConnection.Close
End Sub
In fact, having run a second test after setting my example test SMTP address to be the Primary SMTP address I've found it's still not flagging up the conflict, so perhaps it's a more fundamental problem.

JJ
[small][purple]Variables won't. Constants aren't[/purple]
There is no apostrophe in the plural of PC (or PST, or CPU, or HDD, or FDD, and so on)[/small]
 
OK, I've resolved the issue about not flagging up any conflict on the Primary address:

Code:
        if lcase(strSMTP & conDomainSuffix) = lcase(objRecordSet.Fields("mail")) then
            bDuplicateSMTP = True
            bDuplicateDetailFound = True
            wscript.echo "  Duplicate SMTP address found: " & strSMTP & conDomainSuffix
        end if
However, I've still got the issue of it not finding a conflict on the secondary address.

How can I get the script to check against more than one SMTP address?

JJ
[small][purple]Variables won't. Constants aren't[/purple]
There is no apostrophe in the plural of PC (or PST, or CPU, or HDD, or FDD, and so on)[/small]
 
You should return, rather than anything else, ProxyAddresses as well. For the part of checking strSMTP, check a match for each entry in the ProxyAddresses (if non null, it would be an array). If strSMTP contains the smtp: prefix, check insensitive string comparision should be used. If it does not contain the prefix, add the prefix and do the case insensitive string comparison.
 
That's it! Thank you! :)

JJ
[small][purple]Variables won't. Constants aren't[/purple]
There is no apostrophe in the plural of PC (or PST, or CPU, or HDD, or FDD, and so on)[/small]
 
And just to make sure you know the difference, the primary address under Proxy Addresses will be listed as:

SMTP:username@companyname.com

Where any additional smtp addresses will be listed as

smtp:username@companyname.com

That is why tsuji has suggested case insensitive comparrison.

I hope you find this post helpful.

Regards,

Mark

Check out my scripting solutions at
Work SMARTER not HARDER. The Spider's Parlor's Admin Script Pack is a collection of Administrative scripts designed to make IT Administration easier! Save time, get more work done, get the Admin Script Pack.
 
Just for once, I actually knew that! :)

But still, thanks, Mark.

JJ
[small][purple]Variables won't. Constants aren't[/purple]
There is no apostrophe in the plural of PC (or PST, or CPU, or HDD, or FDD, and so on)[/small]
 
OK, so having shown I can detect a conflict with the SMTP address (thanks to you guys), I put the following scenario to our team leader.
[tt]
User : Jo Bloggs
Logon : Bloggs_J
SMTP : bloggsj@company.com[/tt]

Happy days! Jo gets married to Peter Smith, and as she's a traditional kind of girl she takes his surname. So we change her account name and details but keep her old SMTP address for continuity of communication with external contacts:
[tt]
User : Jo Smith
Logon : Smith_J
SMTP : smithj@company.com
smtp : bloggsj@company.com[/tt]

AGNB...until John Bloggs joins the company. His username, logon and Display name will all be OK:
[tt]
User : Jo Bloggs
Logon : Bloggs_J
[/tt]
The problem will be with John's SMTP address which will clash with Jo's secondary smtp address:
[tt]
SMTP : bloggsj@company.com[/tt]

When I chatted to my Team Lead about it I was expecting him to suggest we rename the new SMTP for something like bloggsj1@company.com or indeed the whole new account with an additional '1'.

However, what he asked for, and hence this new post, was to delete the secondary smtp address from Jo Smith's (nee Bloggs) account.

So, my question is, how to remove the (old) secondary smtp address?

JJ
[small][purple]Variables won't. Constants aren't[/purple]
There is no apostrophe in the plural of PC (or PST, or CPU, or HDD, or FDD, and so on)[/small]
 
>So, my question is, how to remove the (old) secondary smtp address?
This is how.

[1] When you find a user with secondary email address(es) - "smtp:...", you know, in the proxyaddresses array, - use the found distinguished name or adspath to bind to the user object.
[2] Retrieve again the proxyAddresses array.
[3] Send the primary address, hence the dim only 1, to an array variable.
[4] Use putex method with parameter 2 (ADS_PROPERTY_UPDATE).
[5] setInfo to write to the directory.
[tt]
'adspath retrieved from the query and that the user has secondary email address
dim anew()
redim anew(-1)
set ouser=getobject(adspath)
aproxyaddress=ouser.proxyAddresses
for each address in aproxyaddress
if left(address,5)="SMTP:" then
redim anew(0)
anew(0)=address
exit for
end if
loop
if ubound(anew)<>-1 then
ouser.putex 2, anew 'ADS_PROPERTY_UPDATE=2
ouser.setInfo
end if
'it is done for this user
[/tt]
 
Correction
I wrote this line too quick. It should be read like this instead.
[tt] ouser.putex 2, [red]"ProxyAddresses", [/red]anew 'ADS_PROPERTY_UPDATE=2[/tt]
 
Further notes
From another angle of looking at it, the above is too strong and too aggressive in eliminating entries. It leaves only the primary smtp address. Upon reflexion, it should be weakened to eliminate _only_ the secondary address, period. The block could be re-scripted like this.
[tt]
for each address in aproxyaddress
if left(address,5)<>"smtp:" then
redim preserve anew(ubound(anew)+1)
anew(ubound(anew))=address
end if
loop
[/tt]
Then it should be eliminating only the secondary smtp addresses.
 
Actually, even that might be too strong as I only want to delete smtp: addresses that equate to the intended SMTP address for the new user account.

So I'd add in a line like
Code:
for each address in aproxyaddress
    if left(address,5)<>"smtp:" then
        [b][COLOR=blue]if strSMTP & conDomainSuffix = address then[/color][/b]
            redim preserve anew(ubound(anew)+1)
            anew(ubound(anew))=address
        [b][COLOR=blue]end if[/color][/b]
    end if
loop
(Completely untested, as I'm at home!)

JJ
[small][purple]Variables won't. Constants aren't[/purple]
There is no apostrophe in the plural of PC (or PST, or CPU, or HDD, or FDD, and so on)[/small]
 
Upon re-read what you said doing, if strSMTP is secondary, the logic is not exactly right in the above. (The above mean preserve the secondary rather than taking it out.) If it is a definite address, simply match the string with the address. But then again, I am not sure what strSMTP and conDomainSuffix really are, hence I may miss the point.
[tt]
for each address in aproxyaddress
if strSMTP & conDomainSuffix <> address then
redim preserve anew(ubound(anew)+1)
anew(ubound(anew))=address
end if
loop
[/tt]
 
Code:
strSMTP = "smithj"
conDomainSuffix = "@domainname.com"
So combined: [tt]smithj@domainname.com[/tt]

JJ
[small][purple]Variables won't. Constants aren't[/purple]
There is no apostrophe in the plural of PC (or PST, or CPU, or HDD, or FDD, and so on)[/small]
 
In that case, if you only want to eliminate that email address as secondary (again not exactly sure as reflected from your elaboration 2 posts above which means quite the contrary!), it should be this.
[tt]
for each address in aproxyaddress
if "smtp:" & strSMTP & conDomainSuffix <> address then
redim preserve anew(ubound(anew)+1)
anew(ubound(anew))=address
end if
loop
[/tt]
With all those variations, you should get the idea and I have no intention to entangling further on this.
 
OK, so that snippet will leave an smtp: address in place if it's not equal to the new user's SMTP address?

JJ
[small][purple]Variables won't. Constants aren't[/purple]
There is no apostrophe in the plural of PC (or PST, or CPU, or HDD, or FDD, and so on)[/small]
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top