I'm using the following script to compile a list of users and their login scripts. This helps us identify which login scripts are being used and also finding any users who don't have a login script assigned. Here's the script:
code:
Break ON $target = GetObject("LDAP://OU=Users,OU=USA,DC=mycompany,DC=net") If ReDirectOutput("c:\logons.xls") = 0 For Each $user in $target $script = $user.loginscript If $Script = "" ? "Current Script for"+Chr(09)+$user.name+Chr(09)+ "NO SCRIPT ASSIGNED" Else ? "Current Script for "+Chr(09)+$user.name+Chr(09)+$script EndIf Next EndIf
The script works great to retrieve the users from the OU specified. The problem is, under the OU "USA" there are sub OU's for almost every state and then each of those has one or more sub OU's containing user IDs. Is there anyway to have the script search all sub OU's underneath any given "root" OU and return the same info? I know that I could hard code an array of target OU's and loop through that, but we're talking about possibly 100's of OU's and 1000's of users.
Registered: 2000-09-15
Posts: 5809
Loc: Harrisburg, PA USA
When you GETOBJECT on the users OU, your enumeration should also enumerate the other OU objects. You should check the "class" of each object. If the class is "user" then get and report your properties. Otherwise, You should perform another GETOBJECT on the OU to enumerate it. This would be a good use for a recursive UDF.
Howard, if it's not too much to ask could you elaborate a little bit? A lot of this is new to me and I'm now lost . If it's too much trouble, or too detailed to go into I understand.
We can take the code to modify the users from NTLOGON and change it to look for Domain Users that have no script.
code:
CLS BREAK ON $DomainString='DOMAIN' ;Replace with your domain $GroupString='Domain Users' $GroupObj = GetObject('WinNT://' + $DomainString + '/' + $GroupString) For each $UserObj in $GroupObj.Members IF $UserObj.AccountDisabled<>'True' AND $UserObj.LoginScript='' ?$UserObj.Name ?$UserObj.FullName $error=@error $logshare='H:\' ;Change to an available drive or UNC path $logfile=$logshare+$DomainString+'NOSCRIPT.CSV' $logdata=$UserObj.Name+','+$UserObj.FullName+','+$error+@CRLF LOGGER($logfile,$logdata)
ENDIF Next ?'--' ?'Script complete' SLEEP 4
FUNCTION LOGGER($logfile,$logdata) DIM $n WHILE Open(1, $logfile, 5) OR $n=5 IF $n '.' ELSE ?'Please wait' ENDIF $n=$n+1 SLEEP 3 LOOP $n=WriteLine(1, $logdata) $n=Close(1) ENDFUNCTION
Howard, Your function works great but I have two questions. 1. When using the "user" filter, it still returns computers as well. 2. If I wanted to spit out the user's login script (or some other attribute), where the heck would I put that in your function?
Thanks for all of your help from the "scripting challenged".
Registered: 2000-09-15
Posts: 5809
Loc: Harrisburg, PA USA
There seems to be a problem with the IADsContainer FILTER property. In this function the filter works properly for "group", "computer", and "container", but returns computer objects of both 'user' and 'computer' classes when the FILTER is set to "user". This may be related to the fact that computer accounts are indeed hidden user account "computer$", but that should not be the issue since the object definitely return the class "computer" when the FILTER is to "user".
I have added additional code to validate that the object class is indeed the specified and desired class of object the function was sent to enumerate. See the "if $Class = $Filter" construct.
Also I have an oversight when enumerating the complete domain for users. The object called "Users" is in fact of class "container". So the code was modified to recurse on objects of both classes: 'organizationalUnit' and 'container'. The $aFilter array was Redim'ed and the extra filter added.
[ 17. May 2003, 14:47: Message edited by: Howard Bullock ]
Registered: 2000-09-15
Posts: 5809
Loc: Harrisburg, PA USA
Oh, for your second question: you would add a line to get the loginscript property and place the value into a variable with $Name = $item.Name $Class = $item.Class and then add the variable to the out line.
[ 17. May 2003, 01:52: Message edited by: Howard Bullock ]
Thanks Howard. One last question...If you wanted to get the value of a custom optional object property within a class, how would you go about getting that? Example:
code:
$ecode = $item.abc-emplCode
The problem here is the dash in abc-emplCode. And $item.'abc-emplCode' returns nothing. Any suggestions?
There is one other user property that I would like to be able to retrieve from AD and this is if the "password never expires" checkbox is checked. I have tried using $item.PasswordExpirationDate but it returns nothing. Am I searching for the wrong thing.