[python-win32] Adding Users to a Specific Organization Unit in a Domain

Mark Hammond mhammond at skippinet.com.au
Thu Apr 3 01:26:59 CEST 2008


Since Windows 2000, it sometimes better to try and manage users via the
ActiveDirectory - and one excellent reason is that VB etc samples can be
found, which can make life easier.  Here is a little code I've used to
create users via AD - I'm afraid you will need to find out how to add OU
references - it is likely another property that accepts multiple values.

This is cut from a larger project, so some stuff may be missing, and some
stuff may be more complicated than necessary in an attempt to work across
the entire "global catalog" rather than a single domain.  If someone else
can help with adding the OU via win32net, you should probably stick with
that while you can...

Cheers,

Mark

from win32com import adsi
from win32com.adsi.adsicon import *
from ntsecuritycon import *
from win32netcon import *
from win32con import *

def GetWellKnownContainerDN(guid, domain = ""):
    if domain:
        domain = domain + "/" # suitable for sticking in the path.
    dse = OpenObject("LDAP://%sRootDSE" % domain, adsi.IID_IADs)
    dnc = dse.get("defaultNamingContext")
    bind_string = "LDAP://%s<WKGUID=%s,%s>" % (domain, guid, dnc)
    dirObject = OpenObject(bind_string)
    # Now open the container itself.
    return dirObject.get("distinguishedName")

def CreateDomainUser(dirObject, cn, domain, samAcctName=None,
               description = USER_DESCRIPTION):
    """Creates a user with only the essential properties explicitly set
    (cn, sAMAccountType), other optional properties set, and
IDirectoryObject
    for the new user object
    """
    if dirObject is None:
        # Get the default 'users' folder.
        dn = GetWellKnownContainerDN(GUID_USERS_CONTAINER_A, domain)
        dirObject = OpenObject("LDAP://" + dn, adsi.IID_IDirectoryObject)

    dirObject = dirObject.QueryInterface(adsi.IID_IDirectoryObject)

    samAcctName = samAcctName or cn
    assert len(samAcctName) <= 20, \
           "SamAccountName CANNOT be bigger than 20 characters"

    attrInfo = [
       ( "objectClass", ADS_ATTR_UPDATE, ADSTYPE_CASE_IGNORE_STRING,
("user",)),
       ( "sAMAccountName", ADS_ATTR_UPDATE, ADSTYPE_CASE_IGNORE_STRING,
(samAcctName,)),
       ( "description",  ADS_ATTR_UPDATE, ADSTYPE_CASE_IGNORE_STRING,
(description,)),
               ]
    user = dirObject.CreateDSObject("cn="+cn,  attrInfo);
    EnableDomainAccount(user)
    return user.QueryInterface(adsi.IID_IADsUser)

def EnableDomainAccount(user_ob):
    # Ensure the user account is enabled.
    user_ob = user_ob.QueryInterface(adsi.IID_IADs)
    try:
        user_ob.put("pwdLastSet", -1)
        user_ob.SetInfo()
    except pythoncom.com_error, details:
        # This appears to fail on 2003-server.
        logger.warning("Failed to set 'pwdLastSet': %s", details)

    try:
        # And the below seems to fail in some. But complicating
        # things a little is
http://groups.google.com.au/group/microsoft.public.adsi.general/browse_frm/t
hread/be113549cb62ebbe/a4cf4de3756367ad
        # which indicates UserAccountControl isn't even used by later
        # versions of Windows.  It says "If you want to unlock a locked out
        # account, set the lockouttime to 0."
        #
        # Mask out the default bits.  UF_PASSWD_NOTREQD fails on Win2003.
        new_val = user_ob.get("UserAccountControl") |
ADS_UF_DONT_EXPIRE_PASSWD
        new_val &= ~(UF_ACCOUNTDISABLE)
        user_ob.put("UserAccountControl", new_val)
        user_ob.SetInfo()
    except pythoncom.com_error, details:
        # This appears to fail on 2003-server.
        logger.warning("Failed to set 'UserAccountControl': %s", details)

def OpenObject(path, iid = adsi.IID_IADs):
    return adsi.ADsOpenObject(path,
                          None, None, # username/password
                          ADS_SECURE_AUTHENTICATION, # flags
                          iid)


> -----Original Message-----
> From: python-win32-bounces at python.org [mailto:python-win32-
> bounces at python.org] On Behalf Of Ian John Newton
> Sent: Wednesday, 2 April 2008 11:52 PM
> To: python-win32 at python.org
> Subject: [python-win32] Adding Users to a Specific Organization Unit in
> a Domain
> 
> Hi
> 
> I  need to take a text file with a list of users, groups and
> Organization Units and then add these users into a Domain. Currently
> the
> server is Win 2K, but I will also need to do this on Win2003.
> 
> I used the BatchUserCreate.py from ch 16 of Mark Hammonds Python
> Programming on Win32 <http://www.ora.com/catalog/pythonwin32/> and then
> added a win32net.NetGroupAddUser(serverName, group, userName) function
> to add the user to a particular security group. This all works fine.
> 
> I can't seem to find a way to change the organizational unit - all
> users
> get added to the Default container "Users" in the security group Domain
> Users.
> 
> Is there any com method to add them to a specific Organizational Unit?
> 
> Thanks in advance for any help you may be able to provide.
> 
> Regards,
> 
> Ian Newton
> 
> 
> _______________________________________________
> python-win32 mailing list
> python-win32 at python.org
> http://mail.python.org/mailman/listinfo/python-win32



More information about the python-win32 mailing list