Великий и могучий.... Powershell :) Интерактивный поиск пользователей в Active Directory
Замечательный скриптовый язык Powershell, хотя я "по старинке" и пользуюсь еще скриптами WSH и CMD.
Однажды для форума technet потребовалось модифицировать скрипт, выполняющий интерактивный поиск пользователей в Active Directory. Исходный скрипт - http://www.windowspowershell.ru/public/usersview.ps1.txt
Недостатком данного скрипта является его "медлительность" - сперва делается выборка данных в переменную, далее эта переменная обрабатывается. Когда пользователей немного, скрипт отрабатывает быстро, но если пользователей более 1000 то возникает проблема, все очень долго-долго работает, т.к. загрузить такой массив в переменную и обработать его не так просто...
Предложенное мной решение заключается в следующем - поиск объектов и вывод результатов поиска в таблицу производится только после ввода в поле поиска определенного количества символов. Вот что у меня получилось:
#Путь к OU в котором ищем объекты
$Path = "DC=domain,DC=ru"
#Создаем хеш-таблицу для временного хранения объектов
$Table = @{}
#Подгружаем сборку для работы с окнами и графическими элементами
[Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") | Out-Null
#Функция для заполнения списка с фильтрацией по маске
function Fill-First ($Mask = "*")
{
if ($txtSearch.Text.length -ge 5)
{
#Создаем объект для запроса в Active Directory
$Selector = New-Object System.DirectoryServices.DirectorySearcher
#Задаем путь по которому искать объекты
$Selector.SearchRoot = [ADSI]"LDAP://$Path"
#Задаем фильтр
$Selector.Filter = '(&(objectClass=user)(anr='+$Mask+'))'
#Запускаем поиск, и помещаем результаты в переменную $Contacts
$Contacts = $Selector.FindAll()
#Для всех объектов полученных из запроса
$Contacts | foreach {
#Получаем объект Directory Entry в переменную $e
$e = $_.GetDirectoryEntry()
#Если на объекте не стоит галка "Hide from Exchange address list"...
if (-not $e.msExchHideFromAddressLists)
{
#Помещаем объект в таблицу, используя в качестве ключа имя
$Table["$($e.Name)"] = $e
}
}
Fill-List
}
}
function Fill-List ($Mask = "*")
{
#Очищаем список
$List.Items.Clear()
#Для каждого ключа в таблице, если он подпадает под маску...
$Table.Keys | where {$_ -like $Mask} | foreach {
#Добавляем элемент в список
$I = $List.Items.Add($_)
#Добавляем подэлемент (почтовый адрес) для показа во втором столбце
$I.SubItems.Add($Table[$_].mail) | Out-Null
}
}
#Создаем форму и элементы управления
$Form = New-Object system.Windows.Forms.Form
$List = New-Object System.Windows.Forms.ListView
$txtSearch = New-Object System.Windows.Forms.TextBox
$txtInfo = New-Object System.Windows.Forms.TextBox
#Помещаем элементы на форму
$Form.Controls.add($List)
$Form.Controls.add($txtSearch)
$Form.Controls.add($txtInfo)
#И настраиваем их свойства
$Form.Text = "Контакты"
$Form.Width = 450
$Form.Height = 600
$txtInfo.dock = "Bottom"
$txtInfo.Height = 60
$txtInfo.ReadOnly = $True
$txtInfo.Multiline = $True
$List.dock = "Fill"
$List.View = "Details"
$List.MultiSelect = $false
$List.Sorting = "Ascending"
$List.Columns.Add("Имя").width = 200
$List.Columns.Add("E-Mail").width = 200
$txtSearch.dock = "Top"
#Добавляем обработчик на событие TextChanged, который выполняет функцию Fill-List
$txtSearch.add_TextChanged({Fill-First ($txtSearch.Text)})
#Скриптблок выполняющийся при выборе элемента в списке
$SB_SelectionChanged = {
if( $list.SelectedItems )
{
#Получаем из $Table объект, используя в качестве ключа имя элемента
$de = $Table[$list.SelectedItems[0].text]
#Заполняем txtInfo данными из объекта
$txtInfo.Text = @"
Имя: $($de.name)`r
Телефон: $($de.telephoneNumber)`r
E-Mail: $($de.mail)`r
Организация: $($de.company)`r
"@
}
}
#Привязываем обработчик к событию выбора элемента списка
$List.add_SelectedIndexChanged($SB_SelectionChanged)
#Fill-First
#Показываем окно
$Form.ShowDialog()
Работающий скрипт поиска выглядит так:

Опубликовано
24 сентября 2009 г. 10:44
в
SysAdmin Nest
-1
Просмотров: 1169