У нас есть имя LDAP для доступа к схеме. Можно использовать его для доступа к каталогу и для считывания свойств. Мы заинтересованы не только в свойствах класса User, но также в свойствах базовых классов для User
: Organizational-Person
, Person
и Top
. В этой программе имена базовых классов жестко закодированы. Можно было бы прочитать базовый класс динамически с помощью атрибута subClassOf
. Метод GetSchemaProperties()
возвращает строковый массив со всеми именами свойств определенного типа объектов. Все имена свойств собраны в объекте properties
типа StringCollection
:
protected void SetUserProperties(string schemaNamingContext) {
StringCollection properties = new StringCollection();
string[] data = GetSchemaProperties(schemaNamingContext, 'User');
properties.AddRange(GetSchemaProperties(schemaNamingContext, 'Organizational- Person'));
properties.AddRange(GetSchemaProperties(schemaNamingContext, 'Person'));
properties.AddRange(GetSchemaProperties(schemaNamingContext, 'Top'));
listBoxProperties.Items.Clear();
foreach (string s in properties) {
listBoxProperties.Items.Add(s);
}
}
В методе GetSchemaProperties()
мы снова обращаемся к активному каталогу. В этот раз вместо rootDSE
используется имя LDAP в схеме, которое мы обнаружили ранее. Свойство systemMayContain
содержит коллекцию всех атрибутов, которые допустимы в классе objectType
:
protected string[] GetSchemaProperties(string schemaNamingContext, string objectType) {
string [] data;
using (DirectoryEntry de = new DirectoryEntry()) {
de.Username = username;
de.Password = password;
de.Path = 'LDAP://' + hostname + '/CN=' + objectType + ',' + schemaNamingContext;
DS.PropertyCollection properties = de.Properties;
DS.PropertyValueCollection values = properties['systemMayContain'];
data = new String[values.Count];
values.CopyTo(data, 0);
}
return data;
}
Одно интересное замечание к этому коду: в приложении Windows Forms класс PropertyCollection
пространства имен System.DirectoryServices
имеет конфликт имен с System.Data.PropertyCollection
. Поскольку писать такие длинные имена как System.DirectoryServices.PropertyCollection
не всегда хочется, то с целью разрешения конфликта имя пространства имен можно сократить с помощью
namespace DS = System.DirectoryServices;
Именно отсюда появляется DS.PropertyCollection
.
Шаг 2 приложения завершен. Окно списка (listbox
) содержит все имена свойств объектов User
.
Поиск объектов User
Обработчик для кнопки поиска вызывает вспомогательный метод FillResult()
:
private void buttonSearch_Click(object render, System.EventArgs e) {
try {
FillResult();
} catch (Exception ex) {
MessageBox.Show('Check your input: ' + ex.Message)
}
}
В методе FillResult()
выполняется обычный поиск в полном домене активного каталога, как мы видели раньше. SearchScope
задается как Subtree
, Filter
для строки мы получаем из TextBox
, а свойства, которые должны быть загружены в кэш, задаются значениями, которые пользователь выбирает в окне списка
protected void FillResult() {
using (DirectoryEntry root = new DirectoryEntry()) {
root.Username = username;
root.Password = password;
root.Path = 'LDAP://' + hostname + defaultNamingContext;
using (DirectorySearcher searcher = new DirectorySearcher()) {
seacher.SearchRoot = root;
searcher.SearchScope = SearchScope.Subtree;
searcher.Filter = textboxfilter.Text;
searcher.PropertiesToLoad.AddRange(GetProperties());
SearchResultCollection results = searcher.FindbAll();
StringBuilder summary = new StringBuilder();
foreach (SearchResult result in results) {
foreach (string propName in result.Properties.PropertyNames) {
foreach (string s in result.Properties[propName]) {
summary.Append(' ' + propName + ': ' + s + '
');
}
}
summary.Append('
');
}
textBoxResults.Text = summary.ToString();
}
}
}
Запустив приложение, мы получим список всех объектов, которые прошли через фильтр:

Заключение
В этой главе рассматривалась архитектура активного каталога, важные концепции о доменах,