Category Archives: Active Directory

Active Directory | Compacting the NTDS Database file NTDS.DIT

Recently my home server started reporting some errors with reading from the AD database file:

NTDS (612) NTDSA: A request to read from the file "C:\Windows\NTDS\ntds.dit" at offset 14368768 (0x0000000000db4000) for 8192 (0x00002000) bytes succeeded, but took an abnormally long time (25 seconds) to be serviced by the OS. In addition, 1 other I/O requests to this file have also taken an abnormally long time to be serviced since the last message regarding this problem was posted 3267 seconds ago. This problem is likely due to faulty hardware. Please contact your hardware vendor for further assistance diagnosing the problem.

Now, searching for the issue on the Internet seemed to just return a bunch of answers to check the disk, HDD is failing, etc.  All of which I knew was not to be true.  This wasn’t a hardware issue but something related to the way the system was working, so I decided to run a quick compact of the database and see if that cleared up the issue as compacting the AD DS database NTDS.DIT improves performance. Although the improvement varies depending on amount of changes to the database – at the very least I figured if it was bad sectors, a compact and copy would move the file to good sectors.

  1. Open the Services.msc panel and stop "Active Directory Domain Services" (also stops the services below)
    1. File Replication Service
    2. Kerberos Key Distribution Center
    3. Intersite Messaging
    4. DNS Server
  2. Open a command line, type the following (without quotes):
    1. “ntdsutil”
    2. “activate instance ntds”
      1. At this point, you should see the following:
      2. image
    3. “files”
    4. “compact to c:\temp”
      1. And now you should see a very poorly rendered ASCII graph showing that the compact was successful
      2. image
    5. At this point, enter “quit” twice.  Once to get out of file maintenance, the second to get out of the ntdsutil program
    6. Now, copy the ntds.dit file from temp over the file located in C:\windows\ntds\ntds.dit and delete all the *.log files
    7. Last step, start the "Active Directory Domain Services" in services.msc, the other dependant services that stopped will also come back up.

So, fingers crossed it all looks good.

Active Directory Attributes List

Quick reference guide for me to remember what things are called in Active Directory:

 

ADSearch User Property Attributes:

Display Name

ADSearch Name

International ISDN Number (Others)

internationalISDNNumber

accountExpires

accountExpires

accountNameHistory

accountNameHistory

aCSPolicyName

aCSPolicyName

adminCount

adminCount

altSecurityIdentities

altSecurityIdentities

Assistant

assistant

badPasswordTime

badPasswordTime

badPwdCount

badPwdCount

City

l

codePage

codePage

Comment

comment

Company

company

controlAccessRights

controlAccessRights

Country

co

Country Abbreviation

c

countryCode

countryCode

dBCSPwd

dBCSPwd

defaultClassStore

defaultClassStore

Department

department

desktopProfile

desktopProfile

destinationIndicator

destinationIndicator

Division

division

dynamicLDAPServer

dynamicLDAPServer

E-Mail Address

mail

E-Mail Address (Others)

otherMailbox

Employee ID

employeeID

Fax Number

facsimileTelephoneNumber

Fax Number (Others)

otherFacsimileTelephoneNumber

First Name

givenName

garbageCollPeriod

garbageCollPeriod

Generational Suffix

generationQualifier

groupMembershipSAM

groupMembershipSAM

groupPriority

groupPriority

groupsToIgnore

groupsToIgnore

Home Address

homePostalAddress

Home Drive

homeDrive

Home Folder

homeDirectory

Home Phone

homePhone

Home Phone (Others)

otherHomePhone

Initials

initials

International ISDN Number

primaryInternationalISDNNumber

IP Phone Number

ipPhone

IP Phone Number (Others)

otherIpPhone

Job Title

title

lastLogoff

lastLogoff

lastLogon

lastLogon

legacyExchangeDN

legacyExchangeDN

lmPwdHistory

lmPwdHistory

localeID

localeID

lockoutTime

lockoutTime

Logon Name

userPrincipalName

Logon Name (pre-Windows 2000)

sAMAccountName

Logon Workstations

userWorkstations

logonCount

logonCount

logonHours

logonHours

logonWorkstation

logonWorkstation

Manager

manager

maxStorage

maxStorage

mhsORAddress

mhsORAddress

Middle Name

middleName

Mobile Number

mobile

Mobile Number (Others)

otherMobile

mS-DS-CreatorSID

mS-DS-CreatorSID

mSMQDigests

mSMQDigests

mSMQDigestsMig

mSMQDigestsMig

mSMQSignCertificates

mSMQSignCertificates

mSMQSignCertificatesMig

mSMQSignCertificatesMig

msNPAllowDialin

msNPAllowDialin

msNPCallingStationID

msNPCallingStationID

msNPSavedCallingStationID

msNPSavedCallingStationID

msRADIUSCallbackNumber

msRADIUSCallbackNumber

msRADIUSFramedIPAddress

msRADIUSFramedIPAddress

msRADIUSFramedRoute

msRADIUSFramedRoute

msRADIUSServiceType

msRADIUSServiceType

msRASSavedCallbackNumber

msRASSavedCallbackNumber

msRASSavedFramedIPAddress

msRASSavedFramedIPAddress

msRASSavedFramedRoute

msRASSavedFramedRoute

Name

cn

networkAddress

networkAddress

Notes

info

ntPwdHistory

ntPwdHistory

nTSecurityDescriptor

nTSecurityDescriptor

o

o

objectSid

objectSid

Office Location

physicalDeliveryOfficeName

operatorCount

operatorCount

otherLoginWorkstations

otherLoginWorkstations

ou

ou

Pager Number

pager

Pager Number (Others)

otherPager

Phone Number (Others)

otherTelephone

Post Office Box

postOfficeBox

postalAddress

postalAddress

preferredDeliveryMethod

preferredDeliveryMethod

preferredOU

preferredOU

primaryGroupID

primaryGroupID

profilePath

profilePath

pwdLastSet

pwdLastSet

registeredAddress

registeredAddress

rid

rid

sAMAccountType

sAMAccountType

scriptPath

scriptPath

securityIdentifier

securityIdentifier

servicePrincipalName

servicePrincipalName

showInAddressBook

showInAddressBook

sIDHistory

sIDHistory

State/Province

st

street

street

Street Address

streetAddress

supplementalCredentials

supplementalCredentials

Telephone Number

telephoneNumber

teletexTerminalIdentifier

teletexTerminalIdentifier

Telex Number

primaryTelexNumber

Telex Number (Others)

telexNumber

terminalServer

terminalServer

textEncodedORAddress

textEncodedORAddress

thumbnailLogo

thumbnailLogo

thumbnailPhoto

thumbnailPhoto

Title

personalTitle

tokenGroups

tokenGroups

tokenGroupsGlobalAndUniversal

tokenGroupsGlobalAndUniversal

tokenGroupsNoGCAcceptable

tokenGroupsNoGCAcceptable

unicodePwd

unicodePwd

userAccountControl

userAccountControl

userCert

userCert

userCertificate

userCertificate

userParameters

userParameters

userSharedFolder

userSharedFolder

userSharedFolderOther

userSharedFolderOther

userSMIMECertificate

userSMIMECertificate

x121Address

x121Address

ZIP/Postal Code

postalCode

Extracting User List from AD Groups in SharePoint Sites For All Site Users

There is a nice web part called “Site Users” that will display SharePoint users and SharePoint Groups that have access to the site on the webpage.  This is an out of the box (OOTB) webpart, but will only display the name of the AD group and not the members within it.

In order to display all the user names for the site, we need to create a custom webpart to handle this additional expansion that will query the Active Directory LDAP store.  Time to fire up Visual Studio…I won’t go into all the details for solution set up, but here’s the basic functionality…

First we create a function where we pass in an AD group and get back a StringCollection of the users’ names:

//Query Active Directory to get users from Active Directory Groups 
public StringCollection GetGroupMembers(stringstrGroup)
{
    StringCollection groupMemebers = new StringCollection(); 
    try
    {
        DirectoryEntry ent = new DirectoryEntry(LDAP://OU=yourCompanyOU,DC=yourCompanyDC);
        DirectorySearcher srch = new DirectorySearcher(“(CN=” + strGroup + “)”);
        SearchResultCollection coll = srch.FindAll(); 
        foreach (SearchResult rs in coll)
        {
            ResultPropertyCollection resultPropColl = rs.Properties;
            foreach (Object memberColl in resultPropColl["member"])
            {
                DirectoryEntry gpMemberEntry = new DirectoryEntry(“LDAP://”+ memberColl);
                System.DirectoryServices.PropertyCollection userProps = gpMemberEntry.Properties;
                //getting user properties from AD
                object obVal = userProps["displayName"].Value;
                object obAcc = userProps["sAMAccountName"].Value;
                if (null != obVal) 
                {
                    groupMemebers.Add( “User Name:” +obAcc.ToString() + “, User login name:” + obVal.ToString() + “<br>”);
                }
            }
        }
    }
    catch (Exception ex)
    {//writer.Write(ex.Message);}
    Return groupMemebers;
}

We also need to get the names of the site users from the SharePoint security groups:

ArrayList belongToDomain = new ArrayList(); 
ArrayList names = new ArrayList();
using(SPSite collSite = new SPSite(SPContext.Current.Site.ID))
{
    using (SPWeb elevatedWeb = collSite.OpenWeb(SPContext.Current.Web.ID))
    {//All users in the site
        SPUserCollection collUser = SPContext.Current.Web.AllUsers;
        SPGroupCollection collgroup = SPContext.Current.Web.Groups;
        //for each item in the collection of groups
        foreach (object group in collgroup)
        {
            //We don’t care about displaying the visitors
            if (group.ToString() != “Visitors”)
            {
                //check that the users in the site collection belong to current site group
                foreach (SPUser singleuser in collUser)
                {//get the list of groups that the user belongs to
                    foreach (SPGroup userGroup in singleuser.Groups)
                    {//check if it matches any of the current site groups
                        if (group.ToString() == userGroup.ToString())
                        {//check if the user from the sharepoint group is a AD group
                            if (singleuser.IsDomainGroup)
                            {//pass the name into Array that query the AD
                                belongToDomain.Add(singleuser.ToString());
                            }
                            else
                            {//otherwise add into the Array that stores list of names, in case the user name is not from an AD group.
                                names.Add(singleuser.LoginName);
                            }
                        }
                    }
                }
            }
        }
    }
}

Now that we have this big array of user names, we need to make sure that there are no duplicate names, as a user can possibly be in multiple groups. So call the function below and pass in the names array so we have a distinct list:

//remove duplicate users name Function 
public ArrayList RemoveDups(ArrayList items)
{
    ArrayList noDups = new ArrayList();
    foreach (string strItem in items)
    {
        if (!noDups.Contains(strItem.Trim()))
        {
            noDups.Add(strItem.Trim());
        }
    }
    noDups.Sort();
    return noDups;
}

 

And there you go, full expansion of an AD group to return a distinct ArrayList of users who have access to the site.