Link to home
Start Free TrialLog in
Avatar of Member_2_761121
Member_2_761121

asked on

Script works in test but not in live site, why??

Have this script to remove hidden mailbox accounts from distribution groups (both Security & Universal) in Active Directory.  Tested ok in lab conditions the only difference being the number of accounts in the distribution group about 10 in lab and approx 3,500 in live.  Also single Domain Controller in test and 3 in Live.
Also how do I specify in the LDAP search an OU with spaces in it?? As this would save me moving the groups to run the script then moving them back.
Script runs through ok without errors, it creates the text file but doesn't remove any accounts??????? and text file is empty

This is the script
Option Explicit

Dim objContainer
Dim objGroup
Dim objUser
Dim objExUser
Dim strFile
Dim objFSO
Dim objFile
Const ForAppending = 8
strFile = "Removed All Staff Members.txt"
Set objFSO = CreateObject("Scripting.FileSystemObject")
set objFile = objFSO.OpenTextFile(strFile,ForAppending, True)

Set objContainer = GetObject("LDAP://OU=People,dc=domain,dc=co,dc=uk")
Set objGroup = objContainer.GetObject("group","CN=All Staff Members")

objContainer.Filter = Array("user")
For Each objUser in objContainer
   Set objExUser = GetObject(objUser.adspath)
   If objExUser.msExchHideFromAddressLists=TRUE Then
       objFile.WriteLine "Removing: "& objUser.Name
       Call objGroup.Remove(objUser.adspath)
   End If
Next
objFile.Close
Wscript.Echo "Finished"

Avatar of Chris Dent
Chris Dent
Flag of United Kingdom of Great Britain and Northern Ireland image


Comma is the delimiter for LDAP connections, so to specify an OU with spaces in it is simply a case of including the space.

e.g.

Set objRootDSE = GetObject("LDAP://rootDSE")
Set objContainer = GetObject("LDAP://ou=The One With Spaces,ou=TheOneWithout," & objRootDSE.Get("defaultNamingContext"))

Check that it enters this If statement - it's the most likely point of failure:

If objExUser.msExchHideFromAddressLists=TRUE Then
      objFile.WriteLine "Removing: "& objUser.Name
      Call objGroup.Remove(objUser.adspath)
End If

Easiest way to do that is just throw in some wscript.echo statements...

Why did you add objExUser? You already have a connection to each user object with objUser.

Chris
Avatar of Member_2_761121
Member_2_761121

ASKER

Thanks for the response, unfortunately it doesn't appear to be as easy as just entering the space, have tested this on test lab and it fails (runs script, creates txt file, doesn't remove anyone) if OU has space in it.  Move Group to OU without a space and update script and works great??? But not that concerned with this as just need to get the users out of the group

Not sure why add objExuser, as got some help of this site with the script, didn't really question it as it worked :)

The major problem is why it will not run on live site, its now urgent purpose is to remove approx 1200 accounts from 2 groups

Thought I was on to a winner as it worked as expected on test lab??

Is the test environment identical to the live? Windows 2003 domains, for example, have no problem dealing with the space in the LDAP connection - I admit I haven't tested the same against Windows 2000.

I take it all the accounts you want to remove are in one OU?

It would be possible to use the WinNT method to remove the users from the group after pulling a list from LDAP. Let me know what you're looking to achieve anyway, I'm sure we can come up with something that works.

Chris
Test & Live both native w2k domains, test is single DC with all 5 FSMO roles, Live is 3 DC's  with roles split between them.

The actual accounts could be in 3 different OU's, however the Group is in one OU called People, there are some accounts in here and some in sub OU's

The goal is to remove 1200 user accounts from a distribution group based on the attribute of them being hidden from the address list.  Thus leaving an up to date group for people to email to

Makes sense...

I think the main problem is going to be:

objExUser.msExchHideFromAddressLists

If that were returning properly you'd get something written into your output file - the fact that you get nothing in there implies that the If statement is never running.

Could you try this? Afriad I don't have an exchange server here so the properties just aren't present. But this attempts both methods to see what there is there.

For Each objUser in objContainer
      On Error Resume Next
      Err.Clear
      booHidden = FALSE
      booHidden = objUser.Get("msExchHideFromAddressLists")
      If Err.Number <> 0 Then
            wscript.echo "Unable to retrieve value from " & objUser.Name & " with Get"
            booHidden = objUser.msExchHideFromAddressLists
            If booHidden <> TRUE Then
                  wscript.echo objUser.Name & " is either not hidden or query failed - " & booHidden
            End If
      End If
      On Error Goto 0

      If booHidden = TRUE Then
            objFile.WriteLine "Removing: "& objUser.Name
            objGroup.Remove(objUser.adspath)
      End If
Next

Thanks, tried this and got an error on line 32 character 6 ?

Line 32 is "If booHidden = TRUE"?

And is the error Type Mismatch?

Chris
When run script it shows a single window saying it was unable to retireve information from a single account and then show error Variable is undifined 'boohidden'

Ahh you either need to turn off Option Explicit or Dim booHidden.

Then it should at least run...
ok, now it runs through script and writes out text file with members that it should remove, doesn't remove them and returns error Line 34 CHar 11 the server is unwilling to process the request?

Could you post Line 34?

And I take it you don't get anything posting from these two:

wscript.echo "Unable to retrieve value from " & objUser.Name & " with Get"
wscript.echo objUser.Name & " is either not hidden or query failed - " & booHidden
Here is what I'm running, will try the other options now
Dim objContainer
Dim objGroup
Dim objUser
Dim objExUser
Dim strFile
Dim objFSO
Dim objFile
Const ForAppending = 8
strFile = "All Staff.txt"
Set objFSO = CreateObject("Scripting.FileSystemObject")
set objFile = objFSO.OpenTextFile(strFile,ForAppending, True)

Set objContainer = GetObject("LDAP://OU=People,dc=domain,dc=co,dc=uk")
Set objGroup = objContainer.GetObject("group","cn=All Staff")

For Each objUser in objContainer
     On Error Resume Next
     Err.Clear
     booHidden = FALSE
     booHidden = objUser.Get("msExchHideFromAddressLists")
     If Err.Number <> 0 Then
          wscript.echo "Unable to retrieve value from " & objUser.Name & " with Get"
          booHidden = objUser.msExchHideFromAddressLists
          If booHidden <> TRUE Then
               wscript.echo objUser.Name & " is either not hidden or query failed - " & booHidden
          End If
     End If
     On Error Goto 0

     If booHidden = TRUE Then
          objFile.WriteLine "Removing: "& objUser.Name
          objGroup.Remove(objUser.adspath)
     End If
Next

Okay, it looks like 34 refers to "objGroup.Remove(objUser.adspath)" which implies there's either a problem with the attachment to the group or the Remove method is just failing / incompatible.

It's a slight improvement as it seems it's actually entering the If Statement and ending up with the right value for msExchHideFromAddressLists.

Can we change the connection to the group to this?

Set objGroup = GetObject("LDAP://cn=All Staff,ou=People,dc=domain,dc=co,dc=uk")

Just to see if it can connect to that.
so rather than
Set objContainer = GetObject("LDAP://OU=People,dc=domain,dc=co,dc=uk")
Set objGroup = objContainer.GetObject("group","cn=All Staff")

Have it as just Set objGroup = GetObject("LDAP://cn=All Staff,ou=People,dc=domain,dc=co,dc=uk")?

You'll still need objContainer, it gets the list of users from there.

But the change applies to objGroup yes.
ok script now looks like this , is htis how you think it should look?
Dim objContainer
Dim objGroup
Dim objUser
Dim objExUser
Dim strFile
Dim objFSO
Dim objFile
Const ForAppending = 8
strFile = "All Staff.txt"
Set objFSO = CreateObject("Scripting.FileSystemObject")
set objFile = objFSO.OpenTextFile(strFile,ForAppending, True)

Set objContainer = GetObject("LDAP://OU=People,dc=domain,dc=co,dc=uk")
Set objGroup = GetObject("LDAP://cn=All Staff,OU=People,DC=domain,dc=co,dc=uk")

For Each objUser in objContainer
     On Error Resume Next
     Err.Clear
     booHidden = FALSE
     booHidden = objUser.Get("msExchHideFromAddressLists")
     If Err.Number <> 0 Then
          wscript.echo "Unable to retrieve value from " & objUser.Name & " with Get"
          booHidden = objUser.msExchHideFromAddressLists
          If booHidden <> TRUE Then
               wscript.echo objUser.Name & " is either not hidden or query failed - " & booHidden
          End If
     End If
     On Error Goto 0

     If booHidden = TRUE Then
          objFile.WriteLine "Removing: "& objUser.Name
          objGroup.Remove(objUser.adspath)
     End If
Next

Script runs and creates empty txt file and returns error Line 32 Char11 The server is unwilling to process the request

Okay I think I have the cause now. There's just a difference between the AD Group Object and the Local Group Object. So to make things more complicated a different remove function has to be used.

Can you try this modification (I also removed some of the bits I added to check it was working):

Dim objFSO, objFile, objContainer, objGroup, objUser
Dim strFile
Dim booHidden

Const ForAppending = 8
Const ADS_PROPERTY_DELETE = 4

strFile = "All Staff.txt"

Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile(strFile,ForAppending, True)

Set objContainer = GetObject("LDAP://OU=People,dc=domain,dc=co,dc=uk")
Set objGroup = GetObject("LDAP://cn=All Staff,OU=People,DC=domain,dc=co,dc=uk")
      
For Each objUser in objContainer
      On Error Resume Next
      Err.Clear
      booHidden = FALSE
      booHidden = objUser.Get("msExchHideFromAddressLists")
      On Error Goto 0

      If booHidden = TRUE Then
            objFile.WriteLine "Removing: "& objUser.Name
            objGroup.PutEx ADS_PROPERTY_DELETE, _
                  "member", Array(objUser.ADsPath)
            objGroup.SetInfo
      End If
      Set objUser = Nothing
Next

objFile.Close

Set objGroup = Nothing
Set objContainer = Nothing
Set objFSO = Nothing
ok it runs creates txt with one entry of a hidden group in the People OU, then errors on Line 27 char 11 , The server is unwilling to process the request

D'oh sorry... think I forgot to put the filter back in... here's an ammendment:

Dim objFSO, objFile, objContainer, objGroup, objUser
Dim strFile
Dim booHidden

Const ForAppending = 8
Const ADS_PROPERTY_DELETE = 4

strFile = "All Staff.txt"

Set objFSO = CreateObject("Scripting.FileSystemObject")
set objFile = objFSO.OpenTextFile(strFile,ForAppending, True)

Set objContainer = GetObject("LDAP://OU=People,dc=domain,dc=co,dc=uk")
Set objGroup = GetObject("LDAP://cn=All Staff,OU=People,DC=domain,dc=co,dc=uk")

objContainer.Filter = Array("user")
For Each objUser in objContainer
      On Error Resume Next
      booHidden = FALSE
      booHidden = objUser.Get("msExchHideFromAddressLists")
      On Error Goto 0

      If booHidden = TRUE Then
            objFile.WriteLine "Removing: "& objUser.Name
            objGroup.PutEx ADS_PROPERTY_DELETE, _
                  "member", Array(objUser.ADsPath)
            objGroup.SetInfo
      End If
Next

One more thing... it may throw up a complaint if the user isn't a member of the group but you try to remove them - it would be possible to compare with the current membership of the group, but that can be quite timeconsuming for large groups (another set of For Each).

The quick and dirty fix is to remove the "On Error Goto 0" line above (originally there to disable error suppression after getting the msExch attribute).

Hope that makes sense.

Chris
ok script runs and writes txt file with a single entry of the first person that it should remove but doesn't actually remove them from the group? and errors with Line 27 Char 11 The server is unwilling to process the request?

That's basically a permissions problem as far as I can tell. I take it you're running the script as domain administrator?

Going to have another look around anyway to see what can be done...
running as administrator in domain admins group on domain controller.  The following script works on test lab creates file with removed members and actually removes them, it just doesn't work on live system for some reason???? It does run just doesn't write anything to the txt file or remove them??


Dim objContainer
Dim objGroup
Dim objUser
Dim objExUser
Dim strFile
Dim objFSO
Dim objFile
Const ForAppending = 8
strFile = "Removed All Staff.txt"
Set objFSO = CreateObject("Scripting.FileSystemObject")
set objFile = objFSO.OpenTextFile(strFile,ForAppending, True)
Set objContainer = GetObject("LDAP://OU=People,dc=domain,dc=co,dc=uk")
Set objGroup = objContainer.GetObject("group","CN=All Staff")
objContainer.Filter = Array("user")
For Each objUser in objContainer
   Set objExUser = GetObject(objUser.adspath)
   If objExUser.msExchHideFromAddressLists=TRUE Then
       objFile.WriteLine "Removing: "& objUser.Name
       Call objGroup.Remove(objUser.adspath)
   End If
Next
objFile.Close
Wscript.Echo "Finished"

thanks for looking into this its greatly appreciated!
ok looking it at from the other side I have a txt or csv file with the names on of the people that I want to remove from the group.  What would the script look like to read the file and remove from group?  Could bind direct to a specific domain controller and the group?

Are both the test and live versions running at the same functional level?

That will have an effect on how objects can be retrieved from the user account and could explain why you can do "objExUser.msExchHideFromAddressLists = TRUE" on one but have to do "objUser.Get("msExchHideFromAddressLists")" on the other.

ADSI scripting is always a bit of a complex one because there is little standardisation in how and what you can access in an object.

Just for the sake of testing... does the altered script work on the test environment at all?

As an alternative approach it shoud be possible to approach it from the other way, by altering the memberOf list on the user account.

Give me a few moments and I'll see what I can do with the csv file input as well.
both native 2000 mode, the only difference is test lab has 2 DC and live has 3, the altered script has run abd created txt file but I don't recall it removing anyine from the group.
ASKER CERTIFIED SOLUTION
Avatar of Chris Dent
Chris Dent
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial