Или вот взять мою ситуацию — пришел работать маленьким винтиком большой корпоративной системы! Она распределена по всей стране — и была не организована — но за время моей работы — подтянулась к реалиям современного мира, и вместо отдельно взятого домена в каждом филиале, не связанным с остальными — построила большое AD на всю страну! И поехали мои пользователи в новое прогрессивное будущее через ADMT, и их рабочие станции поехали, и они сами! И быстро организовались и OU, и групповые политики с логон — скриптами, действующими WMI — фильтрами и прочее — прочее! Да только вот старый их домен не хранил никаких знаний о них — ни о кабинете, где сидят, ни о том, как их зовут толком, ни об отделе, где трудятся! И так они поехали, простите, голыми в новый домен, что уже само по себе неприлично! А отсюда выросла задача первая:
1) Заполняем данные о пользователе в AD с помощью powershell
Надо сказать — что, несмотря на то, что филиал у нас был отдаленный от центра как России, так и организации — но есть и у нас увлеченные люди! Ну, а куда без них! И поэтому в свое время — одним из хороших товарищей была написана утилита к местному кадровому 1С: Предприятие, — которая позволяла выгрузить все, что ведет отдел кадров по сотруднику — в обычную Excel-таблицу. Есть Excel — есть powershell — значит можно запихать данные в AD! Поехали:
Здесь я немного отступлю, и расскажу, что вообще надо для того, что бы с помощью powershell начать общаться с AD.
Есть первый путь для начала общения с AD из Powershell — это установка на рабочую станцию пакета Microsoft Remote Server Administration Tolls (RSAT). Кроме того, что бы все заработало — на вашем контроллере домена должны быть установлены web-службы active directory, что не всегда возможно. Например, в своем филиале я могу администрировать свою OU – но не могу, что — либо ставить на контроллер домена – прав не хватает.
Но есть выход и из этой ситуации. Хорошая фирма Quest Software разработала свое бесплатное решение для обращения к AD из PowerShell – Active Roles Management Shell for Active Directory (ссылка). Пакет так же ставиться на рабочую станцию c операционной системой не ниже Windows XP. На контроллер домена в данном случае ставить ничего не нужно – все работает из коробки.
Итак, вернемся к задаче получения информации из таблицы excel. Сама таблица выглядит следующим образом:
Все данные являются выдуманными – нам же не надо проблем с разглашением персональных данных.
При этом в нашем AD есть только данные по фамилии, имени и отчеству – следовательно, это и будет ключевым полем. Начинаем писать.
Сначала необходимо подгрузить библиотеку Active Roles Management Shell for Active Directory. В открытой консоле powershell это можно сделать следующей командой:
Add-pssnapin Quest.ActiveRoles.ADManagement
Тоже самое надо написать в файл скрипта, что бы не подключать модуль руками.
Дальше приведу весь код с комментариями:
# очищаем экран cls #Задаем путь к справочнику сотудников $TelSPR="C:\info2AD\телефонный.xls" #Имя листа (WorkSheet) рабочей книги Excel $SheetName="Лист1" #"Запускаем" Excel (создаем COM-объект Excel.Application) $objExcel=New-Object -comobject Excel.Application #выполняем открытие файла ("Рабочей книги") в Excel $objWorkbook=$objExcel.Workbooks.Open($TelSPR) #Номер колонки, содержащей ФИО $ColumnName=1 #Номер колонки, содержащей должность $ColumnTitle=2 #номера телефонов $ColumnHomePhone=3 $ColumnPhone=4 $ColumnMobPhone=5 #Комната $ColumnOffice=6 $ColumnMail=7 #Департамент $ColumnDep=8 # #Константа для использования с методом SpecialCells $xlCellTypeLastCell = 11 # #Получаем номер последней используемой строки на листе #$TotalsRow=$objWorkbook.Worksheets.Item($SheetName).UsedRange.SpecialCells($xlCellTypeLastCell).CurrentRegion.Row #Выполняем перебор строк в открытом файле Excel for ($Row=1;$Row -le $TotalsRow; $Row++) { #Сохраняем в переменных значения соответствующих ячеек $UserName=$objWorkbook.ActiveSheet.Cells.Item($Row, $ColumnName).Value() $Title=$objWorkbook.ActiveSheet.Cells.Item($Row, $ColumnTitle).Value() $HomePhone=$objWorkbook.ActiveSheet.Cells.Item($Row, $ColumnHomePhone).Value() $Phone=$objWorkbook.ActiveSheet.Cells.Item($Row, $ColumnPhone).Value() $MobPhone=$objWorkbook.ActiveSheet.Cells.Item($Row, $ColumnMobPhone).Value() $Office=$objWorkbook.ActiveSheet.Cells.Item($Row, $ColumnOffice).Value() $Mail=$objWorkbook.ActiveSheet.Cells.Item($Row, $ColumnMail).Value() $Department=$objWorkbook.ActiveSheet.Cells.Item($Row, $ColumnDep).Value() #разбиваем ФИО, так как в AD это разные поля $arrfio =-split $UserName $arrfio[2]=$arrfio[2].Substring(0,1) # Добавляем префикс к номеру телефона if ($Phone -ne $null) { $Phone="(888) "+$Phone } if ($MobPhone -ne $null) { $MobPhone="(888) "+$MobPhone } #Пишем данные в AD, если пользователь включен (enabled), включаем обработку ошибок try { Get-QADUser -DisplayName $UserName -enabled | Set-QADUser -FirstName $arrfio[1] -Initials $arrfio[2] -LastName $arrfio[0] -Department $Department -HomePhone $HomePhone -Phone $Phone -MobilePhone $MobPhone -Office $Office -Title $Title -Company "ООО Комета" -Mail $Mail } catch { $ReportString=("{0,-50} <-> {1,50}" -f $UserName, "Ошибка записи") } write-Host $reportString $reportString=" " } #Закрываем книгу Excel $objExcel.Workbooks.Close() #Выходим из Excel (вернее даем команду на выход из Excel) $objExcel.Quit() #обнуляем объект $objExcel = $null #запускаем принудительную сборку мусора для освобождения памяти и окончательного завершения процесса [gc]::collect() [gc]::WaitForPendingFinalizers()
Вот такой скрипт. Работает достаточно быстро. Скажем, список из 300 человек, обрабатывается не дольше минуты. Скрипт также можно повесить в запланированные задачи и попросить отдел кадров выгружать файл с данными сотрудников куда-нибудь в сетевую папку при изменении штатного расписания. Тогда в AD вы будете иметь соответствующую реалиям структуру.
2) Забираем данные из AD в список Sharepoint
После внедрения в нашей конторе Microsoft Sharepoint возникла необходимость использовать списки сотрудников внутри этого монстрообразного детища Microsoft. И опять нам на помощь приходит Powershell.
Для начала заберем данные из AD в текстовый файл формата csv – делается это в две строки:
Add-pssnapin Quest.ActiveRoles.ADManagement
$user=get-qaduser -SearchRoot «OU=Accounts,OU=comenta,DC=domen,DC=local»|Select-Object GivenName, DN, DisplayName, mail, LogonName, telephoneNumber, Office, Department, Title, HomePhone, MobilePhone, sid |Export-CSV -delimiter ";" -path «C:\PowershellScripts\ADUsers.csv» -Encoding UTF8
Можно было бы отгружать в csv и все данные по пользователям – но мы обратили внимание –что время работы скрипта тогда существенно увеличивается.
А уже следующим скриптом грузим данный файл в список Sharepoint. Приведу текст целиком, но под катом – я думаю, будет полезно:
################################################################################## param([string]$path, [string]$url,[string]$ou,[switch]$help) [void][System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint") #функция помощи function GetHelp() { $HelpText = @" Описание: Данный скрипт используется для актуализации данных списка пользователей. Предварительно данные из ActiveDirectory должны быть экспортированы в *.csv файл. Из csv файла в список SharePoint'а забираются следующие столбцы: * sn - Фамилия * givenName - Имя * DisplayName - Полное имя (Ф.И.О.) * mail - E-mail адрес * LogonName - Логин * telephoneNumber - Телефонный номер ВТС * Office - Кабинет * Department - Отдел * Title - Должность * HomePhone - Домашний телефон (в нашем случае Городсокй телефон ) * MobilePhone - Телефонный номер мобильный -------------------------------------------------------------------------------- Параметры: -path Путь расположения csv файла, откуда будут импортироваться данные -url http путь расположения конечного списка, куда будут импортироваться данные -ou Указать Organization unit в AD, откуда будут импортироваться пользователи, например: OU=accaunts- загрузяться все пользователи. OU=cometa - загрузяться только пользователи филиала -------------------------------------------------------------------------------- Синтаксис: Запуск скрипта из PowerShell: .\ImportADUsersToSPList.ps1 -path "Your path" -url "List URL" -ou "OU=cometa" Вызов справки: .\ImportADUsersToSPList.ps1 -help -------------------------------------------------------------------------------- Синтаксис: Запуск скрипта из командной строки Windows: powershell .\ImportADUsersToSPList.ps1 -path "Your path" -url "List URL" -ou "OU=Magadan" Вызов справки: powershell .\ImportADUsersToSPList.ps1 -help -------------------------------------------------------------------------------- "@ $HelpText } function nz($value) { if ($value -eq $null) { $value="" } return $value } function UpdateList([string]$path,[string]$url,[string]$ou) { #Загружаем необхоимые данные и вводим переменные: $site=New-Object Microsoft.SharePoint.SPSite($url) $web=$site.OpenWeb() $list=$web.GetList($url) $csv_file=Import-Csv -Delimiter ";" $path $listItems=$list.Items $spFiledType=[Microsoft.SharePoint.SPFieldType]::Text ######################################################### #В цикле проверяем каждую строку csv файла и заносим данные в список: #пишем лог: "Script started at:" | Out-File -encoding default ".\UpdateUsers.log" -Append Get-Date | Out-File -encoding default ".\UpdateUsers.log" -Append foreach ($line in $csv_file) { $update=$false if (!($item=$list.Items | where {$_["Sid"] -eq $line.Sid})) { #убираем служебные учетные записи if (!(select-string -pattern "88" -inputobject $line.givenName) -and (!(select-string -pattern "Admin" -inputobject $line.givenName)) -and (!(select-string -pattern "Operator" -inputobject $line.givenName))-and ((select-string -pattern $ou -inputobject $line.DN))) { Write-Output $line $item=$list.Items.Add() $item["Sid"]=$line.Sid $update=$true } else {continue} } [array]$sids+=$line.Sid $t=$line.DisplayName -split " ",3 if ((nz($item["Фамилия"])) -ne (nz($t[0]))) { $item["Фамилия"]=$t[0] $update=$true } if ((nz($item["Имя"])) -ne (nz($t[1]))) { $item["Имя"]=$t[1] $update=$true } if ((nz($item["Отчество"])) -ne (nz($t[2]))) { $item["Отчество"]=$t[2] $update=$true } $tfioname=$t[1] -split "",3 $tfioMidName=$t[2] -split "",3 $fio=$t[0]+" "+$tfioname[1]+"."+$tfioMidName[1]+"." if ((nz($item["Ф.И.О."])) -ne (nz($fio))) { $item["Ф.И.О."]=$fio $update=$true } $fio=$tfioname[1]+"."+$tfioMidName[1]+". "+$t[0] if ((nz($item["И.О.Ф."])) -ne (nz($fio))) { $item["И.О.Ф."]=$fio $update=$true } if ((nz($item["E-mail"])) -ne (nz($line.mail))) { $item["E-mail"]=$line.mail $update=$true } if ((nz($item["Логин"])) -ne (nz($line.LogonName))) { $item["Логин"]=$line.LogonName $update=$true } if ((nz($item["ВТС"])) -ne (nz($line.telephoneNumber))) { $item["ВТС"]=$line.telephoneNumber $update=$true } if ((nz($item["Кабинет"])) -ne (nz($line.Office))) { $item["Кабинет"]=$line.Office $update=$true } if ((nz($item["Отдел"])) -ne (nz($line.Department))) { $item["Отдел"]=$line.Department $update=$true } if ((nz($item["Должность"])) -ne (nz($line.Title))) { $item["Должность"]=$line.Title $update=$true } if ((nz($item["ГТС"])) -ne (nz($line.HomePhone))) { $item["ГТС"]=$line.HomePhone $update=$true } if ((nz($item["DECT"])) -ne (nz($line.MobilePhone))) { $item["DECT"]=$line.MobilePhone $update=$true } if ($update -eq $true) { $item.Update() } } $listItems=$list.Items for ($x=$listItems.Count-1; $x -ge 0; $x--) { if (($sids | where {$_ -eq $listItems[$x]["Sid"] }) -eq $null) { $notify="Удален пользователь: "+ $listItems[$x]["Фамилия"].ToString() $notify | Out-File -encoding default ".\UpdateGUUsers.log" -Append $listItems[$x].Recycle() } } "Script finished at:" | Out-File -encoding default ".\UpdateGUUsers.log" -Append Get-Date | Out-File -encoding default ".\UpdateGUUsers.log" -Append "______________________________" | Out-File -encoding default ".\UpdateGUUsers.log" -Append $site.Dispose() } if($help) { GetHelp; Continue } if($path -AND $url -AND $ou) { UpdateList -path $path -url $url -ou $ou}
В результате работы последнего скрипта – мы получаем готовый список в sharepoint, при этом актуальный.
Если по теме статьи у вас возникли какие-то вопросы – готов ответить. Спасибо за внимание.
ссылка на оригинал статьи http://habrahabr.ru/post/168997/
Добавить комментарий