Almost any characters can be used in Distinguished Names. However, some must be escaped with the backslash "\" escape character. Active Directory requires that the following characters be escaped:

comma ,
Backslash character \
Pound sign (hash sign) #
Plus sign +
Less than symbol <
Greater than symbol >
Semicolon ;
Double quote (quotation mark) "
Equal sign =
Leading or trailing spaces  

The space character must be escaped only if it is the leading or trailing character in a component name, such as a Common Name. Embedded spaces should not be escaped.

In addition, ADSI requires that the forward slash character "/" also be escaped in Distinguished Names. The ten characters above, plus the forward slash, must be escaped in VBScript programs because they use ADSI. If you view attribute values with ADSI Edit you will see the ten characters above escaped, but not the forward slash. Utilities (like adfind.exe) that do not use ADSI need to have the ten characters above escaped, but not the forward slash.

For example, the following table shows example Common Names as they would appear in ADUC and the corresponding escaping required if the Distinguished Name is hard coded in VBScript:

Name in ADUC Escaped in VBScript
cn=Last, First cn=Last\, First
cn=Windows 2000/XP cn=Windows 2000\/XP
cn=Sales\Engr cn=Sales\\Engr
cn=E#Test cn=E\#Test

Some characters that are allowed in Distinguished Names and do not need to be escaped include:

* ( ) . & - _ [ ] ` ~ | @ $ % ^ ? : { } ! '

The following characters are not allowed in sAMAccountName's:

" [ ] : ; | = + * ? < > / \ ,

All of these characters are allowed in Distinguished Names, but the last three must be escaped.

If you are binding to an object in Active Directory and specifying the Distinguished Name in the binding string, the characters listed at the top of this page must be escaped with the backslash escape character. For example:

Set objUser = GetObject("LDAP://cn=Wilson\, Fred,ou=Sales,dc=MyDomain,dc=com")
Set objGroup = GetObject("LDAP://cn=W2k\/XP,ou=East,dc=MyDomain,dc=com")
Set objUser = GetObject("LDAP://cn=Jim Smith,ou=E\#Acctg,dc=MyDomain,dc=com")
Set objGroup = GetObject("LDAP://cn=West\\Engr,ou=West,dc=MyDomain,dc=com")

You can escape any characters, including foreign and other non-keyboard characters. For example, the following characters.

á é í ó ú ñ

would be escaped as follows (in order):

\E1 \E9 \ED \F3 \FA \F1

For escaping characters in PowerShell, see this page:

PowerShellEscape.htm

If you use the NameTranslate object to convert the NT name (NetBIOS name) of an object to the Distinguished Name, these characters will already be escaped by NameTranslate, except for the forward slash character. If the Distinguished Name has the "/" character, you must replace it with "\/" to avoid an error when you bind to the object. For example:

' Constants for the NameTranslate object.
Const ADS_NAME_INITTYPE_GC = 3
Const ADS_NAME_TYPE_NT4 = 3
Const ADS_NAME_TYPE_1779 = 1

' Specify the NetBIOS name of the domain and the NT name of the user.
strNTName = "MyDomain\TestUser"

' Use the NameTranslate object to convert the NT user name to the
' Distinguished Name required for the LDAP provider.
Set objTrans = CreateObject("NameTranslate")

objTrans.Init ADS_NAME_INITTYPE_GC, ""
objTrans.Set ADS_NAME_TYPE_NT4, strNTName

strUserDN = objTrans.Get(ADS_NAME_TYPE_1779)

' Replace any "/" characters with "\/".
' All other characters that need to be escaped already are escaped.

strUserDN = Replace(strUserDN, "/", "\/")
Set objUser = GetObject("LDAP://" & strUserDN)

The same thing happens if you use ADO to retrieve the value of the distinguishedName attribute. All characters will be properly escaped except any "/" characters. For example:

' Setup ADO objects.
Set adoCommand = CreateObject("ADODB.Command")
Set adoConnection = CreateObject("ADODB.Connection")
adoConnection.Provider = "ADsDSOObject"
adoConnection.Open "Active Directory Provider"
adoCommand.ActiveConnection = adoConnection

' Search entire Active Directory domain.
Set objRootDSE = GetObject("LDAP://RootDSE")

strDNSDomain = objRootDSE.Get("defaultNamingContext")
strBase = "<LDAP://" & strDNSDomain & ">"

' Filter on user objects.
strFilter = "(&(objectCategory=person)(objectClass=user))"

' Comma delimited list of attribute values to retrieve.
strAttributes = "distinguishedName"

' Construct the LDAP syntax query.
strQuery = strBase & ";" & strFilter & ";" & strAttributes & ";subtree"
adoCommand.CommandText = strQuery
adoCommand.Properties("Page Size") = 100
adoCommand.Properties("Timeout") = 30
adoCommand.Properties("Cache Results") = False

' Run the query.
Set adoRecordset = adoCommand.Execute

' Enumerate the resulting recordset.
Do Until adoRecordset.EOF
    ' Retrieve values.
    strDN = adoRecordset.Fields("distinguishedName").value
    ' Replace any "/" characters with "\/".
    ' All other characters that need to be escaped already are escaped.
    strDN = Replace(strDN, "/", "\/")
    ' Bind to user object.
    Set objUser = GetObject("LDAP://" & strDN)
    Wscript.Echo "NT Name: " & objUser.sAMAccountName _
        & ", First Name: " & objUser.givenName _
        & ", Last Name: " & objUser.sn
    ' Move to the next record in the recordset.
    adoRecordset.MoveNext
Loop

' Clean up.
adoRecordset.Close
adoConnection.Close

If you use the dsquery and dsget command line utilities the situation is a bit different. The dsget command requires that comma, backslash, and quote characters be escaped. However, the dsquery command only escapes the comma and backslash characters. The quote character must be escaped because the Distinguished Names output by the dsquery command are enclosed in quotes, in case there are any spaces. The dsqet command is fooled by any quote characters embedded in the Distinguished Name. For example, the following command should output the sAMAccountName of all users in the domain:

dsquery user -limit 0 | dsget user -samid

This command raises an error if any users have a quote in their common name. A workaround is to redirect the output of the dsquery command to a text file, modify the text file to escape any quotes with the backslash character, and then feed the modified text file to the dsget command. For example, create the text file of user Distinguished Names with the command.

dsquery user -limit 0 > users.txt

It is not easy to modify the file users.txt since all lines begin and end with quote characters. You need to replace all other instances of " with \". After this modification, use this command:

type users.txt | dsget user -samid

A further complication arises if you use LDAP filters to query Active Directory. For example, if you use ADO to query Active Directory, and you use the LDAP syntax, one of the clauses is an LDAP filter clause. Command line utilities like adfind and dsquery also accept LDAP filters. The LDAP filter specification assigns special meaning to the following characters:

* ( ) \ NUL

The NUL character is ASCII 00. In LDAP filters these 5 characters should be escaped with the backslash escape character, followed by the two digit ASCII hex representation of the character. The following table documents this:

* \2A
( \28
) \29
\ \5C
NUL \00

For example, if you use ADO in a VBScript program to query for the user with Common Name "James Jim*) Smith", the LDAP filter would be:

strFilter = "(cn=James Jim\2A\29 Smith)"

Actually, the parentheses only need to be escaped if they are unmatched, as above. If instead the Common name were "James (Jim) Smith", nothing would need to be escaped. However, any characters, including non-display characters, can be escaped in a similar manner in an LDAP filter.