This article describes a PowerShell script that can be used to retrieve information from your
Active Directory. The script prompts for three things. First, it prompts for the "base" of the query. Second, it prompts for an LDAP syntax
filter. Finally, the script prompts for the Active Directory attributes to be retrieved. Results can be output in list or csv
(comma delimited) format and redirected to a text file. Or you can request just the count of the number of objects retrieved by the query.
The script is in the TechNet Gallery here:
Generic Search of Active Directory
↑ Return to Top
The primary purpose of the script is to query Active Directory. The script can be used to test various LDAP syntax filters in your
AD. The script outputs the actual values of the attributes (where feasible). But in many cases it also displays a "friendly" format of the value. For example, the value of the pwdLastSet attribute is a large integer. The script converts this number into
a datetime in the time zone of the local client.
Active Directory is an LDAP compliant database. All queries of AD must be converted into LDAP syntax. For example, suppose you use a PowerShell AD cmdlet such as Get-ADUser to query AD. These cmdlets support an extended form of the PowerShell Expression
Language. You use the -Filter parameter to specify a PowerShell syntax filter. But Active Directory does not support this syntax directly. The AD cmdlets convert the PowerShell filter into LDAP syntax before sending it to a
domain controller. All of the AD cmdlets also support LDAP syntax filters directly, with the -LDAPFilter parameter.
LDAP syntax filters can be used in many situations. For example:
The script is designed to be run at a PowerShell prompt. The script displays results at the prompt, or you can redirect the output to a text file. The script accepts three optional parameters. If you specify -csv, the script outputs in a comma delimited
format. Otherwise, the script outputs in a list format where each value is on a separate line. The csv format can be read into Excel and converted into a spreadsheet. The image below shows the result when you specify csv format. Note that all values that could
conceivably include commas are quoted. The value of objectSID could never include a comma. The image shows what the user entered at each prompt, followed by what the script output. If the output had been redirected to a text file, only the output from the
script would be included in the file. In this case, the lines output by the script are the heading line that specifies the attributes, plus one line of values (word wrapped).
If you specify -OneLevel, the query only considers objects that are direct children of the "base". Otherwise, the default is "SubTree", meaning that the query considers objects in the "base" and all child OU's
and containers of the "base". If you specify -Count, the script simply outputs the number of objects retrieved by the query. In the image
below we retrieve the number of groups in the
When you run the script at a PowerShell prompt it first requests the "base" of the query. This is the distinguished name of the
organizational unit, or container where the query will start. If you enter nothing, the script will default to the current domain. The query will start at the base and include all nested OU's and containers within the base, unless you have specified the
If you enter an OU, container, or partition, you can skip the domain portion of the distinguished name. If the script does not find the string
"dc=" in the base you provide, it will append the distinguished name of the current domain to the base.
Examples for the "base" of a query are listed below. These assume that your domain is "dc=mydomain,dc=com".
Some AD attributes are not replicated to all domain controllers. Instead, for each object a different value for the attribute is saved
DC. For example, the lastLogon, logonCount, badPasswordTime, and whenChanged attributes are not replicated. If you want to view the values of any of these on a particular DC, you must include the NetBIOS
name of the DC in the base of the query. To target the domain controller MyDC, the base of the query should be similar to "MyDC/dc=mydomain,dc=com". The script will process the query on the specified DC. Note that you can also specify just "MyDC/" and the
script will append the distinguished name of the domain to the base.
After prompting for the "base" of the query, the script next prompts for the LDAP syntax filter to be used. LDAP syntax filters consist of clauses in parentheses combined by operators. Each clause consists of the lDAPDisplayName
of an attribute, an operator, and a value. For example, to query for all user objects the filter would be:
"(&(objectCategory=person)(objectClass=user))". For complete documentation of LDAP syntax filters, see
Active Directory: LDAP Syntax Filters.
Finally, the script prompts for a comma delimited list of attribute values to retrieve for each AD object that meets the conditions of the filter in the base. Use the lDAPDisplayName of the attributes. The script will always retrieve the distinguished names
of all objects retrieved, so do not include that attribute.
Most attributes can be displayed directly and do not require any conversion into a "friendly" format. These include attributes with datatypes String, DN (distinguished names), Boolean, Generalized Time, and 32-bit numbers that are not flag attributes. The
image below demonstrates a query to retrieve several such attributes for a user.
Note above that the domain controller "Wisconsin" has been specified in the base of the query, because whenChanged and uSNChanged are not replicated. Also, the filter is (anr=Kenneth Mueller). This uses Ambiguous Name Resolution (ANR) to
find all objects where the first name is "Kenneth" and the last name is "Mueller". This feature is explained in detail in references in the "Other Resources" and "See Also" sections below.
Some Active Directory attributes are stored as byte arrays (also called OctetStrings). We could display the values as a series of decimal bytes, but that is not useful. The script converts many byte array attributes into a "friendly" format. The image below
shows how all types of byte arrays described below are output.
The 21 bytes of the logonHours attribute are converted into bits by the script function OctetToHours. This function displays the bits in 7 rows of 24 bits each, representing the 24 hours in each day of the week. A
"0" means the user is not allowed to logon during that hour. A
"1" means the user is allowed to logon. The 168 bits are adjusted for the time zone of the local client. In the image above the logonHours attribute is displayed for a user.
If the byte array consists of 16 bytes, it assumed to be a GUID value. This could be objectGUID, netbootGUID, siteGUID, or any of several other
attributes. The script function OctetToGUID is used convert the bytes into the friendly format, including the curly braces and dashes.
The table below documents how SID attributes are recognized. If the number of bytes in the array and the values of the first two bytes match
an entry in the table, then the attribute is a SID value.
The value of SID attributes is converted into the well known "friendly" form.
Flag attributes are integer values that indicate settings or options. In some cases, each value has a different meaning. For most, however, each bit of the integer value indicates a different setting. Each bit of the value must be tested with a bit mask
to check if the setting is on or off. Separate functions are used in the script to evaluate the following attributes.
The following image shows how the script displays the userAccountControl, sAMAccountType, and instanceType attributes of users.
The following image shows how the script displays the searchFlags and systemFlags attributes of attribute objects in the Schema container.
And the image below shows how the groupType attribute is displayed for group objects.
Many attributes in Active Directory are Large Integers. The syntax is sometimes referred to as Integer8, meaning it has 8 bytes. This is a 64-bit value. Such large integers can represent several types of values.
If the value of the attribute exceeds the maximum positive number allowed in PowerShell, or is less than the minimum negative number allowed, then the value displays as
"<never>". The maximum positive ticks is 3,155,378,975,999,999,999, which corresponds to the datetime Friday, December 31, 9999 11:59:59 PM. The minimum negative ticks is -9,223,372,036,854,775,808, which corresponds
to a timespan greater than 29,227 years.
If the value of the Large Integer attribute exceeds 120,000,000,000,000,000 ticks, but is less than the maximum value allowed, then it is assumed to represent a datetime. Attributes such as lastLogonTimeStamp, accountExpires, and pwdLastSet are Large Integer
values that represent dates. The dates are represented as the number of 100-nanosecond intervals (ticks) since 12:00 AM January 1, 1601. In addition, the dates are in UTC
(after the French acronym for Coordinated Universal Time), which used to be referred to as GMT. The script converts these values into a datetime value in the time zone of the local client. 120,000,000,000,000,000 ticks corresponds to April 07, 1981, 9:20 PM
UTC. The image below shows how the lastLogon and pwdLastSet attributes are displayed. The uSNChanged, logonCount, and maxStorate attributes are also Large Integer, but their values are displayed as large numbers, as described later.
Note that the domain controller "Wisconsin" is specified because lastLogon, uSNChanged, and logonCount are not replicated.
If the value of the LargeInteger attribute is negative, but greater than the minimum negative value allowed, then the value is assumed to represent a timespan. Large Integer attributes represent time spans in ticks. A tick is a 100-nanosecond interval, or
1 x 10^7 (0.0000001) second. Examples include maxPwdAge, minPwdAge, lockoutDuration, and lockoutThreshold. The image below shows how these values are displayed.
Other Large Integer attributes are simply large numbers. The script assumes that any LargeInteger value between 0 and 120,000,000,000,000,000 is simply a large number. For example, the maxStorage attribute is the number of bytes of disk space a user is allocated.
This value is displayed as a number, with culture-specific separators (such as commas or periods) between the thousands to improve readability, as shown in the "Datetime Values" section above.
In the default list output mode, multi-valued attributes are displayed with each value on a separate line. In CSV mode, the
values are concatenated into one string with the individual values delimited by semicolons, the
";" character. The image below shows the directReports attribute, a multi-valued DN attribute, for a user.
A few attributes, like unicodePwd, ntPwdHistory, and userPassword, cannot be evaluated by the script. Others, like userParameters, can be displayed, but are difficult to interpret. ntSecurityDescriptor displays as an array of decimal bytes.
Multi-valued operational attributes (also called constructed attributes) raise errors. This includes the attributes tokenGroups,
tokenGroupsGlobalAndUniversal, tokenGroupsNoGCAcceptable, and the objectClasses attribute of attributeSchema objects in the
Schema container. These attributes cannot be used in a filter or attribute list. Single valued operational attributes, like canonicalName, createTimeStamp, and modifyTimeStamp, can be specified in an attribute list. Their values can be displayed. But if
they are used in filters an error will be raised.
The following errors are trapped and an error message is displayed.
If a non-existent attribute is requested, the value of the attribute is simply shown as
"<no value>". The script cannot tell the difference between an attribute that has no value assigned and a misspelled attribute name.