Downloads
8796.zip

Do you have a scripting-related question or problem? You can send your question or problem to bobwells@win2000mag.com.

I'm working on a script that moves all the users in a top-level organizational unit (OU) to a bottom-level OU. I tried using the Microsoft Active Directory Service Interfaces' (ADSI's) IADsContainer::MoveHere method in a For Each...Next statement to perform the move operation, but I keep getting the error message Wrong number of arguments or invalid property assignment: 'oTargetContainer.MoveHere'. The only way I can get the script to work is to hard-code the username, as the script UserMove.vbs in Listing 1 shows. However, in production mode, hard-coding won't work because I must move blocks of users into sub-OUs. What am I doing wrong?

The problem lies in the parameters you're passing to MoveHere. This method uses an ADsPath and relative distinguished name (RDN) to determine which object to move or rename. Thus, MoveHere requires two parameters:

  • The ADsPath of the object you're moving or renaming. Every object in the directory exposes this important path. The ADsPath is an object's distinguished name (DN) prefixed with the appropriate ADSI provider (in this case, Lightweight Directory Access Protocol—LDAP).
  • The RDN for the moved or renamed object in the current container.

Although you're providing the two mandatory parameters, you're making the task more difficult than it needs to be. You're trying to construct the ADsPath when every directory object already exposes its ADsPath through the IADs interface. Thus, you don't need to construct the path manually. Instead, you can use the ADsPath property that the object provides.

Another potential problem is that you didn't apply a filter to the source OU container. As a result, the For Each...Next loop in Listing 1 (providing it works) will move every object in the source container to the target container. This might or might not be the intended result. To play it safe, I recommend that you use filters to ensure that you're applying your batch operation to the appropriate object types.

Listing 2 contains the fixed script NewUserMove.vbs. The script's primary steps are

  1. Bind to source OU.
  2. Bind to destination OU.
  3. Filter the OUs.
  4. Just do it!

As Listing 2 shows, the first two steps are identical to the bind operations performed in Listing 1. The code in step 3 uses the IADsContainer::Filter property to filter the OUs for objects of class User. The code at callout A in Listing 2 simply echoes the names of the User objects in the source and target containers before performing the move operation. Step 4 is where MoveHere performs the move operation. If you compare Listing 2's For Each...Next loop with its counterpart in Listing 1, you'll likely agree that the move operation is now much simpler. The key to this simplicity is knowing the properties that the directory objects provide and using those properties rather than trying to recreate them. The code at callout B in Listing 2 again echoes the names of the User objects in the source and target containers. Figure 1 shows an example of the output you'll receive from NewUserMove.vbs.