asp tutorials, asp.net tutorials, sample code, and Microsoft news from 15Seconds
Data Access  |   Troubleshooting  |   Security  |   Performance  |   ADSI  |   Upload  |   Email  |   Control Building  |   Component Building  |   Forms  |   XML  |   Web Services  |   ASP.NET  |   .NET Features  |   .NET 2.0  |   App Development  |   App Architecture  |   IIS  |   Wireless
 
Pioneering Active Server
 Power Search





Active News
15 Seconds Weekly Newsletter
• Complete Coverage
• Site Updates
• Upcoming Features

More Free Newsletters
Reference
News
Articles
Archive
Writers
Code Samples
Components
Tools
FAQ
Feedback
Books
Links
DL Archives
Community
Messageboard
List Servers
Mailing List
WebHosts
Consultants
Tech Jobs
15 Seconds
Home
Site Map
Press
Legal
Privacy Policy
internet.commerce














internet.com
IT
Developer
Internet News
Small Business
Personal Technology
International

Search internet.com
Advertise
Corporate Info
Newsletters
Tech Jobs
E-mail Offers

HardwareCentral
Compare products, prices, and stores at Hardware Central!

Learning ADSI - Part 2: Editing Users and Administering Groups
By Remie Bolte
Rating: 4.5 out of 5
Rate this article


  • email this article to a colleague
  • suggest an article

    Introduction

    When I started ASP, I tried reading a couple of phone directory-sized $50 books. Each of them was filled with samples that didn't make sense to me. I then found a Web site with simple ASP code samples, which I used to create some ASP pages. Today, when I look back at those pages, I'm truly embarrassed. When I revist those books, everything finally makes sense. But with ADSI, making sense simply means learning the syntax. How do you know the right syntax? Read this article, which covers how to edit an existing user and administer groups.

    Caveat

    Please keep in mind that you are going to modify the basics of the Windows NT security model. You should be very alert when dealing with ADSI. Keep in mind that a simple mistype could mean reformatting and reinstalling your system. Don't do it on a operational machine! Please know that I have tried to make the following code as accurate as possible. Yet I can't guarantee their outcome. So please don't just copy and paste. I know it is very attractive, but it could cause you to spend the next couple of hours looking at a very appealing Windows installation screen.

    EXTRA NOTE:
    For those who read my first article, please heed the following. In that article I forgot one of the most important aspects of programming. The codes I provided could cause a memory leak since I forgot to cleanup the objects I used. So please add this to the codes in order to prevent this (The first article has been updated with this change).

    
    Set Computer = nothing
    Set User = nothing
    Set Flags = nothing
    
    

    Editing an Existing User

    As I explained in my first article, every action performed here goes directly through the Windows SAM. In response to my first article, there were some questions on how to change the logon hours or the terminal server home path. Sorry, but I have to disappoint you . This , as well as some other vital functions, can't be changed by ADSI. Then again, ADSI does do a lot. In the upcoming articles we are going to dive into the IIS metabase. But before we do that, let's start with editing a user.

    Renaming Users

    
    <%
    1.  RenameUser("MyDomain","MyUsername","MyNewUsername")
    2.
    3.   Sub RenameUser(strDomain,strOldUsername,strNewUsername)
    4.     Dim Computer
    5.     Dim User
    6.     Dim MoveUser
    7.    
    8.     Set Computer = GetObject("WinNT://" & strDomain)
    9.     Set User = GetObject("WinNT://" & strDomain & "/" & strOldUsername & ",user")
    10.   Set MoveUser = Computer.MoveHere(User.ADsPath, strNewUsername)
    11.
    12.   Set Computer = nothing
    13.   Set User = nothing
    14.   Set MoveUser = nothing
    15. End Sub
    %>
    
    
    There isn't much to explain. The computer just grabs all the information about a user (the user.ADsPath) and projects that to the new user, deleting the old.

    Changing User-Properties

    
    <%
    1.   ChangeUser("MyUser","MyDomain","MyFullname","MyDescription","MyOldPass"
          ," MyNewPass"
    2.
    3.   Sub ChangeUser(strUser,strDomain,strFullname,strDesc,strOldPassword, 
    4.                              strNewPassword)
    5.     Dim User
    6.     Set User = GetObject("WinNT://" & strDomain & "/" & strUser & ",user")
    7.     User.Fullname = strDesc
    8.     User.Description = strDesc
    9.     User.ChangePassword(strOldPassword,strNewPassword)
    10.   User.Setinfo
    11.   Set User = nothing
    12. End Sub
    %>
    
    
    In the above code we changed some basic elements of a user account. It isn't that different from adding a user. The only thing difference is the way a password is changed. Because of security reasons you can only change a password by providing the old password. The outcome of this subroutine is very simple. The user "MyUser" now has "MyFullname","MyDescription", and "MyNewpass" as a fullname, description and password. The next part is a bit harder since we are going into Hex/Decimal codes with the User-Flags. Again the code looks a lot like the code I used in my first article, but with one difference. Because we are now changing the user settings we use XOR instead of OR when dealing with userflags.

    Changing Specific User Boundaries

    
    <%
    
    1.  UserFlags "newuser","mydomain",0,False,True,True,True
    2. 
    3.    Sub UserFlags(strUser,strDomain,strPassexpires,strNochange,strNoexpire, & _        
                                   strDisable,strLocked)
    4.      Dim User
    5.      Dim Flags
    6.
    7.      Set User = Getobject("WinNT://" & strDomain & "/" & strUser & ",user")
    8.      Flags = User.Get("UserFlags")
    9.
    10.    User.put "PasswordExpired",strPassexpires
    11.    User.Accountdisabled = strDisable
    12.    if strNochange = "true" then 
    13.      User.put "UserFlags", Flags OR &H00040
    14.    End if
    15.    If strNoexpire = "true" then
    16.      User.put "Userflags", flags OR &H10000
    17.    end if
    18.    User.IsAccountLocked = strLocked
    19.
    20.    Set User = nothing
    21. End sub
    
    %>
    
    
    I'm not going to explain this code since it is an almost exact copy of the coding in the first article. Please make sure that you use XOR to change a userflag and OR to initially set it. The following part is a direct copy since nothing has changed. In order to change the logon script, profile path, etc., we use the same code as we used to initially set it.
    
    <%
    
    1.    userconfig "newuser","mydomain","c:\myprofiles\","myscript.cmd","c:\","z:\", & _
                             #mm/dd/yyyy#,"true"
    2.
    3.    sub userconfig(strUser,strDomain,strProfile,strScript,strHomedir, & _
                                   strHomedirdrive,strAccountexpire,strPassrequired)
    4.      Dim User
    5.      Dim Flags
    6.
    7.      Set User = Getobject("WinNT://" & strDomain & "/" & strUser & ",user")
    8.      
    9.      User.Profile = strProfile
    10.    User.LoginScript = strScript
    11.    User.Homedirectory = strHomedir
    12.    User.Put("HomeDirDrive"),strHomedirdrive
    13.    User.AccountExpirationDate = strAccountexpire
    14.    User.Passwordrequired = strPassrequired
    15.
    16.  end sub
    
    %>
    
    
    Now we edited the same information that we applied to the computer in the previous article. After doing this we might as well remove the user we created, leaving us with nothing.

    Removing Users

    
    <%
    1.  DelUser("MyDomain","MyUsername",)
    2.
    3.   Sub DelUser(strDomain,strUsername)
    4.     Dim Computer
    5.    
    6.     Set Computer = GetObject("WinNT://" & strDomain)
    7.     Computer.Delete("User", strUsername)
    8.     Set Computer = nothing
    9.   End Sub
    %>
    
    
    In the next article I will provide codes on how to query specific user information. For now we are going to order our thousands of users by making groups.

    Creating, Editing and Populating Groups

    Groups are made to make the life of system administrators a bit easier. By creating groups you don't have to give folder rights to each specific user. You only have to give folder rights to the group. With ADSI and some good old DOS programming we can automate both.

    Creating a Group

    
    <%
    1.    '//Creating a local group
    2.    AddLocalGroup("MyDomain", "MyGroup")
    3.  
    4.    Sub AddLocalGroup(strDomain,strGroupname)
    5.      Dim Computer
    6.      Dim Group
    7.
    8.      Set Computer = GetObject("WinNT://" & strDomain)
    9.      Set Group = Computer.Create("Group", strGroupname)
    10.    Group.Put "groupType", 4
    11.    Group.Setinfo
    12.
    13.    Set Computer = nothing
    14.    Set Group = nothing
    15.  End Sub
    16.  '//End Creating a local group
    %>
    
    <%
    1.    '//Creating a global group
    2.    AddGlobalGroup("MyDomain","MyGroup")
    3.
    4.    Sub AddGlobalGroup(strDomain,strGroupname)
    5.      Dim Computer
    6.      Dim Group
    7.  
    8.      Set Computer = GetObject("WinNT://" & strDomain)
    9.      Set Group = Computer.Create("Group", strGroupname)
    10.    Group.Put "groupType", 2
    11.    Group.Setinfo
    12. 
    13.    Set Computer = nothing
    14.    Set Group = nothing
    15.  End Sub
    16.  '//End Creating a global group
    %>
    
    
    You may have noticed that in the first code sample the grouptype is 4, and in the second it is 2. The grouptype defines if the group is a local group, or a global group. Local groups are created to make independent groups on a workstation, and global groups are made for the whole domain. By default ADSI creates a Global group, so if you want to make a group without thinking, use the second sample and remove the Group.Put "groupType", 2 part.

    Adding Users to a Group

    
    <%
    1.    AddUserToGroup("MyDomain","MyUsername","MyGroup")
    2.
    3.    Sub AddUserToGroup(strDomain,strUsername,strGroupname)
    4.      Dim User
    5.      Dim Group
    6.
    7.      Set User = GetObject("WinNT://" & strDomain & "/" & strUsername & ",user")
    8.      Set Group = GetObject("WinNT://" & strDomain & "/" & strGroupname & 
                                                   ",group")
    9.      Group.Add(User.ADsPath)
    10.    Group.Setinfo
    11.
    12.    Set User = nothing
    13.    Set Group = nothing
    14.  End Sub
    %>
    
    
    Removing Users from a Group
    
    <%
    1.    DelUserFromGroup("MyDomain","MyUsername","MyGroup")
    2.
    3.    Sub DelUserFromGroup (strDomain,strUsername,strGroupname)
    4.      Dim User
    5.      Dim Group
    6.
    7.      Set User = GetObject("WinNT://" & strDomain & "/" & strUsername & ",user")
    8.      Set Group = GetObject("WinNT://" & strDomain & "/" & strGroupname & 
                                                   ",group")
    9.      Group.Remove(User.ADsPath)
    10.    Group.Setinfo
    11.
    12.    Set User = nothing
    13.    Set Group = nothing
    14.  End Sub
    %>
    
    
    Editing the Group Description Field
    
    <%
    1.    EditGroup("MyDomain","MyGroup","MyDescription")
    2.
    3.    Sub EditGroup (strDomain,strGroupname,strGroupDesc)
    4.      Dim Group
    5.
    6.      Set Group = GetObject("WinNT://" & strDomain & "/" & strGroupname & 
                                                   ",group")
    7.      Group.Description = strGroupDesc
    8.      Group.Setinfo
    9.
    10.    Set Group = nothing
    11.  End Sub
    %>
    
    
    Maybe some of you missed my explanation here. But I couldn't think of anything to comment on. The creation of a group doesn't involve difficult pieces of coding. Frankly, the only thing that is different between adding and removing a user in a group is the words "add" and "remove". There is nothing as easy as making new groups; you just have to know the syntax. So that is what I've provided here. Let's cleanup our little experiment by removing the group.

    Removing a Group

    
    <%
    1.  DelGroup("MyDomain","MyGroup",)
    2.
    3.   Sub DelGroup(strDomain,strGroupname)
    4.     Dim Computer
    5.     Set Computer = GetObject("WinNT://" & strDomain)
    6.     Computer.Delete("Group", strGroupname)
    7.     Set Computer = nothing
    8.   End Sub
    %>
    
    
    That is all there is to say about groups in the ADSI. So now for the special bonus: Automatically changing the Folder Rights. After creating a group, or a user, you can automatically set the folder rights by using old fashion DOS methods. Every Windows server has a little program called cacls.exe. This program changes the user rights on folders. You can just run it by using Windows Scripting, but then you will get stuck. Why? Because the cacls.exe is waiting for confirmation. In order to do this you should pipe a Y to the cacls.exe, forcing it to accept the new settings.
    
    <%
    1.    ChangeFolderSettings("c:\myfolder","Myuser","C")
    2.
    3.    Sub ChangeFolderSettings(strFolderPath,strUser,strPermission)
    4.      Dim caclscommand
    5.      Dim whs
    6.      Dim whsRun
    7.
    8.      Caclscommand = "cmd /c echo y| CACLS " & strFolderPath
    9.      Caclscommand = Caclscommand & " /E /C /G " & strUser & ":" & strPermission
    10.
    11.    Set whs = server.createobject("WScript.Shell")
    12.    Set whsRun = whs.run(Caclscommand, 0, True)
    13.
    14.    Set whsrun = nothing
    15.    Set whs = nothing
    16.  End Sub
    %>
    
    
    The code creates a commandline that is executed in by the Windows Script Host. In that commandline I specify a few different things:
    
    1. "cmd /c echo"
    2. "y| CACLS"
    3. & strFolderPath & " /E /C"
    4. "/G " & strUser & ":" & strPermission
    
    
    The first thing I do is open a command window and pointing out that I want to see the what's happening. After that I pipe the letter Y to the CACLS.exe by using the y| symbol. By piping Y, I avoid the "Are you Sure" question. Then I give the name of the folder (or file) I want to edit, followed by /E and /C. The /E says that I want to edit the user rights. Without the /E the rights will be overwritten. The /C says that the code should continue even if an error occurs. The last part is where I grant to user strUser (this can also be a group) a specific right. In the example I use C. But there are more rights:
    
    - R (read only)
    - W (write only)
    - C (change (read/write))
    - F (Full Control)
    
    
    Please note that if you want to change the rights of a user you have to use "/P " & strUser & ":" & strPermission

    I'm going to end with some answers to questions I received concerning my previous article. Hope you enjoyed it, and happy programming.

    FAQ

    Q: I can't set the AccountExpirationDate
    A: This could be because the user has the "Password Never Expires" toggled on. If so, the account won't expire, and therefore ADSI isn't able to set it.

    Q: I get a "General Access Denied Error" when I apply the codes
    A: The server will only allow changes to be made to the SAM using an Administrator username and password. So the IUSR_machinename (IIS anonymous account) isn't allowed to execute the codes. Make sure that you toggle off the anonymous access in IIS, and let people login using a valid Administrator account.

    Q: Can I Automatically create an exchange Mail account?
    A: Yes you can, but I will handle that later.

    Q: can I set the Terminal Services Properties using ADSI.
    A: No you can't. ADSI can't set the terminal services properties, as well as it can't change logon hours.

    Beside these questions, there were some question about LDAP. This article doesn't involve LDAP; it just refers to the ADSI language. If you do have question about LDAP, you can e-mail me. I'm not really good at it, but I can help to figure out a solution.

    About the Author

    Remie Bolte is a student at communicatiesystemen in the Netherlands. He has experience with VB, ASP, VBScript and SQL. His goal in life is to clean up the Internet and show people how it can benefit their needs. Remie can be reached at r.bolte@vinrem.nl.

  • Rate This Article
    Not HelpfulMost Helpful
    1 2 3 4 5
    Other Articles
    Jul 30, 2002 - Accessing Active Directory Through the .NET Framework
    In this article, Robert Chartier shows how to use the System.DirectoryServices Class for some simple User and Group administration tasks with impersonation.
    [Read This Article]  [Top]
    Jan 30, 2002 - Add to Your ADSI Code Library
    Remie Bolte has put together a collection of ADSI scripts for some of the more common Windows administration tasks.
    [Read This Article]  [Top]
    Oct 5, 2001 - Learning ADSI - Part 1: Adding Users To W2K
    Remie Bolte uses his popular Adding Users to W2K code sample as a basis for introducing and exploring Microsoft's Active Directory Services Interface.
    [Read This Article]  [Top]
    Jul 10, 2001 - Web site Administration with ADSI and the .NET DirectoryServices Namespace
    The power of Active Directory Service Interfaces (ADSI) and the Microsoft .NET Framework is introduced by Tony Caudill. After completing this article you will be able to easily tame the System.DirectoryServices Namespace and use ADSI services to programatically create, delete, and update all aspects of your Web farm's virtual directories.
    [Read This Article]  [Top]
    Mar 16, 1998 - ADSI Part II: Configuring NTLM with ADSI
    ADSI Part II describes and demonstrations the power of ADSI by showing how to manipulate the NTLM database. Examples in this article show how to add a user to a domain, delete the user, add a group, and add the user to the group. There is also a discussion on security and an overview of the Group, User and Domain ADSI objects.
    [Read This Article]  [Top]
    Mar 4, 1998 - Programming IIS 4.0 with ADSI
    Have you wanted to add virtual roots through VBScript? Create ISAPI server extensions that install themselves in IIS 4.0? Or script the installation of your entire web site including user permissions? You can do this and more with ADSI.
    [Read This Article]  [Top]
    Mailing List
    Want to receive email when the next article is published? Just Click Here to sign up.

    Support the Active Server Industry

    internet.comearthweb.comDevx.commediabistro.comGraphics.com

    Search:

    Jupitermedia Corporation has two divisions: Jupiterimages and JupiterOnlineMedia

    Jupitermedia Corporate Info

    Legal Notices, Licensing, Reprints, Permissions, Privacy Policy.
    Advertise | Newsletters | Tech Jobs | Shopping | E-mail Offers