Актуализация данных в Active Directory
Имеем:
- Active Directory
- систему управления персоналом “БОСС – Кадровик”
Необходимо:
- периодически обновлять некоторую информацию о пользователях в каталоге Active Directory на основе информации, полученной из системы “БОСС – Кадровик”.
Решение:
Скрипт на PowerShell, реализующий заданные требования.
Скрипт можно выполнять интерактивно, или через планировщик задач, например командой – “C:\WINDOWS\system32\WindowsPowerShell\v1.0\powershell.exe -Command D:\Sync_AD_BOSS.ps1“.
Для работы скрипта также понадобятся PowerShell Commands (CMDLETs) for Active Directory by Quest Software.
Как говорится – “Как есть”.
Из него Вам пригодятся ключевые моменты по реализации той или иной логики.
====================================================================
Далее код PowerShell.
#===============================================================================
# СИНХРОНИЗАЦИЯ УЧЕТНЫХ ЗАПИСЕЙ ПОЛЬЗОВАТЕЛЕЙ ACTIVE DIRECTORY
# С ДАННЫМИ ПО СОТРУДНИКАМ КОМПАНИИ ИЗ СИСТЕМЫ БОСС Кадровик
# НАПРАВЛЕНИЕ СИНХРОНИЗАЦИИ БОСС Кадровик -> ACTIVE DIRECTORY
# СОЕДИНЕНИЕ ПО “ФАМИЛИЯ ИМЯ ОТЧЕСТВО” или по табельному номеру
#
# ОАО ПКК “Весна”. Илгиз Мамышев
# Версия 17.06.2008
#===============================================================================
#=== Инициализация переменных ===
$Count = 1; $Count2 = 1; $Count3 = 1; $Count4 = 1;
$script:BOSS_Data_by_FN_recomend_Counter = 0;
$script:BOSS_Data_by_FN_recomend = “”;
$LogFile = “\\domen.local\dfs2$\Deploy\Sync_AD_BOSS\SynchronizationActiveDirectoryWithBOSS.log”
$RulesFile = “\\domen.local\dfs2$\Deploy\Sync_AD_BOSS\SynchronizationActiveDirectoryWithBOSS_RULES.txt”
$SmtpServer = “exchsrv.domen.ru”
$SmtpFrom = “alerts@domen.ru”
$SmtpTo = “alerts@domen.ru”
$Subject = “Синхронизация Active Directory и БОСС-Кадровик. РЕКОМЕНДАЦИИ АДМИНИСТРАТОРУ.”
#$VerbosePreference = “Continue” #Разрешить вывод сообщений Write-Verbose
$VerbosePreference = “SilentlyContinue” #Запретить вывод сообщений Write-Verbose
#===============================================================================
“=====================================================================” > $RulesFile
“СИНХРОНИЗАЦИЯ УЧЕТНЫХ ЗАПИСЕЙ ПОЛЬЗОВАТЕЛЕЙ ACTIVE DIRECTORY” >> $RulesFile
“С ДАННЫМИ ПО СОТРУДНИКАМ КОМПАНИИ ИЗ СИСТЕМЫ БОСС Кадровик” >> $RulesFile
“” >> $RulesFile
“`t`t`tО С Н О В Н Ы Е П Р А В И Л А” >> $RulesFile
“” >> $RulesFile
“1. НАПРАВЛЕНИЕ СИНХРОНИЗАЦИИ БОСС Кадровик – > ACTIVE DIRECTORY” >> $RulesFile
“2. СОЕДИНЕНИЕ ПО ‘ФАМИЛИЯ ИМЯ ОТЧЕСТВО’ (поле ‘Выводимое имя’) или по табельному номеру (поле ‘Адрес\Почтовый ящик’)” >> $RulesFile
“3. Поля учетной записи пользователя домена, подлежащие обновлению:” >> $RulesFile
“- Общие\Фамилия” >> $RulesFile
“- Общие\Имя” >> $RulesFile
“- Общие\Инициалы” >> $RulesFile
“- Общие\Описание” >> $RulesFile
“- Общие\Веб страница (Уровень сотрудника(руководителя))” >> $RulesFile
“- Адрес\Почтовый ящик (Табельный номер)” >> $RulesFile
“- Организация\Должность” >> $RulesFile
“- Организация\Отдел” >> $RulesFile
“- Организация\Организация” >> $RulesFile
“4. В случае изменения полей фамилия, имя, инициалы, описание, веб страница, должность, отдел, организация” >> $RulesFile
“для учетной записи пользователя, найденного в БОСС кадровик по ФИО, будут обновлены все поля, подлежащие синхронизации.” >> $RulesFile
“5. В случае изменения фамилии сотрудника, если учетная запись пользователя ранее была синхронизирована и было заполнено поле Адрес\Почтовый ящик (Табельный номер),” >> $RulesFile
“то в результате синхронизации будет выдана рекомендация по корректировке учетной записи пользователя.” >> $RulesFile
“6. Если сотрудник уволен, – выводимое имя в свойствах учетной записи пользователя будет откорректировано (дописано ‘- уволен..’).” >> $RulesFile
“и будет выдана рекомендация по отключению учетной записи.” >> $RulesFile
“7. Отключенные учетные записи не обновляются.” >> $RulesFile
“8. Все произведенные изменения в Active Directory логируются.” >> $RulesFile
“9. Рекомендации по ручной корректировке Active Directory отправляются электронным письмом.” >> $RulesFile
“” >> $RulesFile
“Замечания, пожелания, предложения – ст. администратор ОЭ УИТ ФД И.Мамышев” >> $RulesFile
“=====================================================================” >> $RulesFile
#================== ФУНКЦИИ ======================================
#===============================================================================
#=== Получить данные сотрудника по ФИО
#=== Результат FALSE в случае ошибки или отсутствия данных для вывода.
#=== В случае положительного результата – возврат строки с данными
#===============================================================================
function Get-BOSS_Data_by_FN ([string]$full_name=”")
{
if ($full_name.length -eq 0) {Write-Verbose “Не переданы ФИО в качестве параметра”; return $false}
#=== Разбор FULL_NAME. Выделим только первые ТРИ слова (ФИО). Если меньше – не принимаем к обработке. Если больше – усекаем что больше первых 3-х слов.
Write-Verbose “ФИО До обработки: `t`t$full_name”
if ($full_name.split(” “).Count -lt 3) {Write-Verbose “Передана некорректная строка в качестве ФИО”; return $false}
$full_name.split(” “) | ForEach-Object -begin{$c=0; $full_name=”"} -process{$c++; if($c -le 2) {$full_name += $_+ ” “}; if($c -eq 3) {$full_name += $_} }
Write-Verbose “ФИО После обработки: `t$full_name”
#========= Подключаемся к серверу БД и читаем их базы данных данные о сотрудниках
#=== В результирующем наборе ОДИН сотрудник и его данные по основному месту работы – сотрудники – уникальны – повторяющихся нет (НО! – исключения есть – парочка)
$SQLCn = New-Object System.Data.SqlClient.SqlConnection( “Server=VSN_SRV4;Trusted_Connection=Yes;Database=Lite”)
$SQLCn.Open()
$SQLCMD = $SQLCn.CreateCommand()
$SQLCMD.CommandText = “SELECT distinct
(case
when people.id_firm = 9 then ‘э’+people.NUM_TAB
when people.id_firm = 10 then ‘л’+people.NUM_TAB
else ‘в’ +people.NUM_TAB end) as EmplID, — ТАБЕЛЬНЫЙ НОМЕР \ ПОЧТОВЫЙ ЯЩИК
people.id_firm as FirmID,
card.Full_Name, — ФИО \ ВЫВОДИМОЕ ИМЯ
card.Name, — ФАМИЛИЯ \ ФАМИЛИЯ
card.Name_i, — ИМЯ \ ИМЯ
LEFT(card.Name_i,1)+’.'+LEFT(card.Name_o,1)+’.’ as Initials, — ИНИЦИАЛЫ \ ИНИЦИАЛЫ
card.date_birth as BirthDate,
card.typUdost as IdentityCardCode_ru,
card.passp_ser as IdentityCardSeries_ru,
card.passp_num as IdentityCardNumber_ru,
card.passp_date as IdentityCardIssueDate_ru,
card.passp_grant as IdentityCardIssueBy_ru,
card.addr_zip as ZipCode, — ИНДЕКС \ ПОЧТОВЫЙ ИНДЕКС
card.addr_city as City, — ГОРОД \ ГОРОД
card.addr_street as Street, — УЛИЦА \ УЛИЦА
card.addr_house as House, — ДОМ \ УЛИЦА + УЛИЦА
card.addr_block as Block, — КОРПУС \ УЛИЦА + УЛИЦА + УЛИЦА
card.addr_flat as Flat, — КВАРТИРА \ УЛИЦА + УЛИЦА + УЛИЦА + УЛИЦА
appointments.name_appoint as Title, — ДОЛЖНОСТЬ \ ДОЛЖНОСТЬ
(case when structs.struct_lev =0 then structs_r.struct_name else structs.struct_name end) as Otdel, — ПОДРАЗДЕЛЕНИЕ \ ОТДЕЛ
structs.tree_path, — ПОЛНЫЙ ПУТЬ \ ОПИСАНИЕ
setup.Short_name as Company, — КОМПАНИЯ \ ОРГАНИЗАЦИЯ
people.in_date, — ДАТА ПРИЕМА НА РАБОТУ
people.out_date, — ДАТА УВОЛЬНЕНИЯ
(case when people.out_date = ’2099-01-01′ then 1 else 0 end) as Works, — РАБОТАЕТ \ ОТКЛЮЧИТЬ УЧЕТНУЮ ЗАПИСЬ
pr_group_value.string as EmplLevel — УРОВЕНЬ \
FROM card
LEFT OUTER JOIN people (NOLOCK) on card.Auto_Card = people.Auto_Card
LEFT OUTER JOIN PR_CURRENT (NOLOCK) ON PEOPLE.PID = PR_CURRENT.pId
LEFT OUTER JOIN appointments (NOLOCK) on appointments.code_appoint = pr_current.code_appoint
JOIN structs on people.struct_code=structs.struct_code
JOIN structs structs_r on structs.struct_root=structs_r.struct_code
JOIN setup on setup.id_firm = people.id_firm
LEFT OUTER JOIN pr_group_value on pr_current.cell_item = pr_group_value.id_ref and pr_group_value.id_group = 147
WHERE PR_CURRENT.flag_last=’*’
AND people.id_firm in (1,9,10) — Выводим сотрудников только этих компаний
AND card.Full_Name = @full_name
AND out_date = (select max(out_date)
from people people1
where people.auto_card = people1.auto_card
and people1.id_firm in (1,9,10))
and pr_current.Work_Code = (select min(Work_Code)
from pr_current pr_current1, people people1
where pr_current1.pid = people1.pid
and pr_current1.auto_card=card.auto_card
and flag_last=’*’
and people1.out_date = (select max(out_date)
from people people2
where people1.auto_card = people2.auto_card
and people2.id_firm in (1,9,10)))”
$P = $SQLCMD.Parameters.AddwithValue(“@full_name”, $full_name)
$SQLResult = $SQLCMD.ExecuteReader() # В этой переменной результат запроса к базе БОСС кадровик
#While ( $SQLResult.Read() ){Write-Host $SQLResult.Item(“EmplId”) $SQLResult.Item(“Name”)}
if($SQLResult.Read() -eq $false) { Write-Verbose “Нет данных для вывода по запрошенному ФИО ($full_name)!”;
$script:BOSS_Data_by_FN_recomend_Counter++;
$script:BOSS_Data_by_FN_recomend += “” + $script:BOSS_Data_by_FN_recomend_Counter + “. $full_name”;
return 100}
$out = @{EmplId=$SQLResult.Item(“EmplId”);
Full_Name=$SQLResult.Item(“Full_Name”);
Name=$SQLResult.Item(“Name”);
Name_i=$SQLResult.Item(“Name_i”);
Initials=$SQLResult.Item(“Initials”);
BirthDate=([datetime]$SQLResult.Item(“BirthDate”)).ToShortDateString();
ZipCode=$SQLResult.Item(“ZipCode”);
City=$SQLResult.Item(“City”);
Street=[string]$SQLResult.Item(“Street”)+”, дом “+[string]$SQLResult.Item(“House”)+”, блок “+[string]$SQLResult.Item(“Block”)+”, квартира “+[string]$SQLResult.Item(“Flat”);
Title=$SQLResult.Item(“Title”);
Otdel=$SQLResult.Item(“Otdel”);
tree_path=$SQLResult.Item(“tree_path”);
Company=$SQLResult.Item(“Company”);
out_date=$SQLResult.Item(“out_date”);
Works=$SQLResult.Item(“Works”);
EmplLevel=$SQLResult.Item(“EmplLevel”);
}
$SQLCN.Close()
return $out
}
#===============================================================================
#===============================================================================
#=== Получить данные сотрудника по табельному номеру
#=== Результат FALSE в случае ошибки или отсутствия данных для вывода.
#=== В случае положительного результата – возврат строки с данными
#===============================================================================
function Get-BOSS_Data_by_EID ([string]$EmplId=”")
{
if ($EmplId.length -eq 0) {Write-Verbose “Не передан табельный номер в качестве параметра”; return $false}
if($EmplId[0] -eq “э”){$firm = 9}elseif($EmplId[0] -eq “л”){$firm = 10}else{$firm = 1} #Для поиска сотрудника в списке конкретной компании
if(“э”,”л”,”в”–contains $EmplId[0]){$EmplId = $EmplId.SubString(1,$EmplId.length-1)} #Выделяем чисто табельный номер
#========= Подключаемся к серверу БД и читаем их базы данных данные о сотрудниках
#=== В результирующем наборе ОДИН сотрудник и его данные по основному месту работы – сотрудники – уникальны – повторяющихся нет (НО! – исключения есть – парочка)
$SQLCn = New-Object System.Data.SqlClient.SqlConnection( “Server=VSN_SRV4;Trusted_Connection=Yes;Database=Lite”)
$SQLCn.Open()
$SQLCMD = $SQLCn.CreateCommand()
$SQLCMD.CommandText = “SELECT distinct
(case
when people.id_firm = 9 then ‘э’+people.NUM_TAB
when people.id_firm = 10 then ‘л’+people.NUM_TAB
else ‘в’ +people.NUM_TAB end) as EmplID, — ТАБЕЛЬНЫЙ НОМЕР \ ПОЧТОВЫЙ ЯЩИК
people.id_firm as FirmID,
card.Full_Name, — ФИО \ ВЫВОДИМОЕ ИМЯ
card.Name, — ФАМИЛИЯ \ ФАМИЛИЯ
card.Name_i, — ИМЯ \ ИМЯ
LEFT(card.Name_i,1)+’.'+LEFT(card.Name_o,1)+’.’ as Initials, — ИНИЦИАЛЫ \ ИНИЦИАЛЫ
card.date_birth as BirthDate,
card.typUdost as IdentityCardCode_ru,
card.passp_ser as IdentityCardSeries_ru,
card.passp_num as IdentityCardNumber_ru,
card.passp_date as IdentityCardIssueDate_ru,
card.passp_grant as IdentityCardIssueBy_ru,
card.addr_zip as ZipCode, — ИНДЕКС \ ПОЧТОВЫЙ ИНДЕКС
card.addr_city as City, — ГОРОД \ ГОРОД
card.addr_street as Street, — УЛИЦА \ УЛИЦА
card.addr_house as House, — ДОМ \ УЛИЦА + УЛИЦА
card.addr_block as Block, — КОРПУС \ УЛИЦА + УЛИЦА + УЛИЦА
card.addr_flat as Flat, — КВАРТИРА \ УЛИЦА + УЛИЦА + УЛИЦА + УЛИЦА
appointments.name_appoint as Title, — ДОЛЖНОСТЬ \ ДОЛЖНОСТЬ
(case when structs.struct_lev =0 then structs_r.struct_name else structs.struct_name end) as Otdel, — ПОДРАЗДЕЛЕНИЕ \ ОТДЕЛ
structs.tree_path, — ПОЛНЫЙ ПУТЬ \ ОПИСАНИЕ
setup.Short_name as Company, — КОМПАНИЯ \ ОРГАНИЗАЦИЯ
people.in_date, — ДАТА ПРИЕМА НА РАБОТУ
people.out_date, — ДАТА УВОЛЬНЕНИЯ
(case when people.out_date = ’2099-01-01′ then 1 else 0 end) as Works, — РАБОТАЕТ \ ОТКЛЮЧИТЬ УЧЕТНУЮ ЗАПИСЬ
pr_group_value.string as EmplLevel — УРОВЕНЬ \
FROM card
LEFT OUTER JOIN people (NOLOCK) on card.Auto_Card = people.Auto_Card
LEFT OUTER JOIN PR_CURRENT (NOLOCK) ON PEOPLE.PID = PR_CURRENT.pId
LEFT OUTER JOIN appointments (NOLOCK) on appointments.code_appoint = pr_current.code_appoint
JOIN structs on people.struct_code=structs.struct_code
JOIN structs structs_r on structs.struct_root=structs_r.struct_code
JOIN setup on setup.id_firm = people.id_firm
LEFT OUTER JOIN pr_group_value on pr_current.cell_item = pr_group_value.id_ref and pr_group_value.id_group = 147
WHERE PR_CURRENT.flag_last=’*’
AND people.id_firm = @firm — Выводим сотрудников только этой компании
AND people.NUM_TAB = @EmplId
AND out_date = (select max(out_date)
from people people1
where people.auto_card = people1.auto_card
and people1.id_firm in (1,9,10))
and pr_current.Work_Code = (select min(Work_Code)
from pr_current pr_current1, people people1
where pr_current1.pid = people1.pid
and pr_current1.auto_card=card.auto_card
and flag_last=’*’
and people1.out_date = (select max(out_date)
from people people2
where people1.auto_card = people2.auto_card
and people2.id_firm in (1,9,10)))”
$P = $SQLCMD.Parameters.AddwithValue(“@firm”, $firm)
$P = $SQLCMD.Parameters.AddwithValue(“@EmplId”, $EmplId)
$SQLResult = $SQLCMD.ExecuteReader() # В этой переменной результат запроса к базе БОСС кадровик
if($SQLResult.Read() -eq $false) {Write-Verbose “Нет данных для вывода по запрошенному табельному номеру ($EmplId)!”; return $false}
$out = @{EmplId=$SQLResult.Item(“EmplId”);
Full_Name=$SQLResult.Item(“Full_Name”);
Name=$SQLResult.Item(“Name”);
Name_i=$SQLResult.Item(“Name_i”);
Initials=$SQLResult.Item(“Initials”);
BirthDate=([datetime]$SQLResult.Item(“BirthDate”)).ToShortDateString();
ZipCode=$SQLResult.Item(“ZipCode”);
City=$SQLResult.Item(“City”);
Street=[string]$SQLResult.Item(“Street”)+”, дом “+[string]$SQLResult.Item(“House”)+”, блок “+[string]$SQLResult.Item(“Block”)+”, квартира “+[string]$SQLResult.Item(“Flat”);
Title=$SQLResult.Item(“Title”);
Otdel=$SQLResult.Item(“Otdel”);
tree_path=$SQLResult.Item(“tree_path”);
Company=$SQLResult.Item(“Company”);
out_date=$SQLResult.Item(“out_date”);
Works=$SQLResult.Item(“Works”);
EmplLevel=$SQLResult.Item(“EmplLevel”);
}
$SQLCn.Close()
return $out
}
#===============================================================================
#===== НАЧАЛО ===========
“======================================================” >> $LogFile
#”ВНИМАНИЕ! ТЕСТИРОВАНИЕ! К ИСПОЛЕНИЮ НЕ ПРИНИМАТЬ! /И.Мамышев” >> $LogFile
“Синхронизация Active Directory с БОСС Кадровик” >> $LogFile
“Отчет о изменениях в Active Directory:” >> $LogFile
$LogFile >> $LogFile
$dt = Get-Date -Format “dd.MM.yyyy HH:mm:ss”
“Начало: “+$dt >> $LogFile
“——————————————————” >> $LogFile
#
$RecomText = “=====================================================================`n”
#$RecomText += “ВНИМАНИЕ! ТЕСТИРОВАНИЕ! К ИСПОЛНЕНИЮ НЕ ПРИНИМАТЬ! /И.Мамышев`n”
$RecomText += “РЕКОМЕНДАЦИИ по итогам Синхронизации Active Directory с БОСС Кадровик`n”
$RecomText += “Отчет о произведенных изменениях в Active Directory:`n” + $LogFile + “`n”
$RecomText += “Правила работы процесса синхронизации:`n” + $RulesFile + “`n”
$RecomText += “Начало: “+$dt + “`n”
$RecomText += “———————————————————————`n”
$RecomText += “Измените свойства учетных записей в соответствии с информацией ниже`n”
$RecomText += “, затем повторите или дождитесь следующей синхронизации.`n”
#========= Ищем пользователей в глобальном каталоге =======
cls
Write-Host ‘ОАО ПКК “Весна”‘
Write-Host “Синхронизация Active Directory и БОСС Кадровик”
Write-Host “Пожалуйста подождите..”
#$ADUsers=(Get-QADUser -UseGlobalCatalog -SizeLimit 0 -ErrorAction SilentlyContinue | where {($_.Name -eq “chn_bez1″)})
#$ADUsers=(Get-QADUser chn_bez1 -SizeLimit 0 -ErrorAction SilentlyContinue )
$ADUsers=( Get-QADUser -UseGlobalCatalog -SizeLimit 0 -ErrorAction SilentlyContinue | where {$_.DN -notlike “*Горизонт*”} |
where {$_.DN -notlike “*SRV*”} | where {$_.DN -notlike “*Календарь*”} | where {$_.DN -notlike “*SystemMailbox*”} |
where {$_.DisplayName -notlike “*пользователь*”} | where {$_.DisplayName -notlike “*робот*”} | where {$_.DisplayName -notlike “*robot*”} | where {$_.DN -notlike “*test*”} |
where {$_.DisplayName -notlike “*тест*”} | where {$_.DisplayName -notlike “*Служебная*”} | where {$_.DisplayName -notlike “*veritas*”} |
where {$_.DN -notlike “*ЧИН*”} | where {$_.DN -notlike “*Ветснаб*”} )
#=== Перебираем всех отобранных пользователей ActiveDirectory, пытаемся найти данные по ним в результатах запроса к БОССу
#&$ADUsers | ForEach-object {
$ADUsers | ForEach-object -Begin {if($ADUsers.Count -le 0){$ADUCnt=1;}else{$ADUCnt=$ADUsers.Count}; $percent=$ADUCnt/100; $c = 0; “Будет обработано $ADUCnt учетных записей” >> $LogFile} -Process {
$c++; [int]$a = $c/$percent; Write-Progress -Activity “Идет обработка…” -PercentComplete $a -CurrentOperation “$a% завершено” -Status “Пожалуйста подождите.”; #Счетчик – процент выполнения
#=== Пробуем получить данные по сотруднику по ФИО ($_.DisplayName)
#=== Мы здесь даже тогда, когда поле ТАБЕЛЬНЫЙ НОМЕР заполнено, но данные в запросе к БОССу не нашли
#=== Если учетная запись пользователя в AD ВЫКЛЮЧЕНА, то выходим из цикла и идем к следующей итерации
if ([bool](Get-QADUser -Name $_.Name -UseGlobalCatalog -Disabled) -eq $True) { return; };
$Count2++
$b = Get-BOSS_Data_by_FN $_.DisplayName
Write-Verbose “$($_.PostOfficeBox) $($_.Name) $($_.DisplayName) $($_.Type) Счетчик: $Count2″
if ($b.Count -gt 0)
{#=== Информация из БОССа по ФИО получена
$dt = Get-Date -Format “dd.MM.yyyy HH:mm:ss”
if (($b["EmplLevel"]).length -le 0) {$wp = “”} else {$wp = “Уровень ” + $b["EmplLevel"]}
$notes = “День рождения ” + $b["BirthDate"] + “. Синхронизировано с БОСС Кадровик ” + $dt
if ($b["Name"].Length -gt 64) {$b["Name"]=$b["Name"].SubString(0,64)}
if ($b["Name_i"].Length -gt 64) {$b["Name_i"]=$b["Name_i"].SubString(0,64)}
if ($b["Initials"].Length -gt 6) {$b["Initials"]=$b["Initials"].SubString(0,6)}
if ($b["Title"].Length -gt 64) {$b["Title"]=$b["Title"].SubString(0,64)}
if ($b["Otdel"].Length -gt 64) {$b["Otdel"]=$b["Otdel"].SubString(0,64)}
if ($b["Company"].Length -gt 64) {$b["Company"]=$b["Company"].SubString(0,64)}
if ($b["tree_path"].Length -gt 1024) {$b["tree_path"]=$b["tree_path"].SubString(0,1024)}
if ( ([string]$_.WebPage -ne [string]$wp)-or([string]$_.LastName -ne [string]$b["Name"])-or([string]$_.FirstName -ne [string]$b["Name_i"])-or([string]$_.Initials -ne [string]$b["Initials"])-or([string]$_.PostOfficeBox -ne [string]$b["EmplID"])-or([string]$_.Title -ne [string]$b["Title"])-or([string]$_.Department -ne [string]$b["Otdel"])-or([string]$_.Company -ne [string]$b["Company"])-or([string]$_.Description -ne [string]$b["tree_path"]) )
{#=== Если изменились свойства уч. записи – Записываем\обновляем свойства учетной записи ActiveDirectory
$result = Set-QADUser -Identity $_.DN -WebPage $wp -LastName $b["Name"] -FirstName $b["Name_i"] -Initials $b["Initials"] -Notes $notes -PostOfficeBox $b["EmplID"] -Title $b["Title"] -Department $b["Otdel"] -Company $b["Company"] -Description $b["tree_path"] #-WhatIf
“” >> $LogFile
“” + $Count + “. Обновлены свойства: ” + $_.DN >> $LogFile;
# “Было`t=> `tWebPage:`t” + $_.WebPage + “,`tLastName:`t” + $_.LastName + “,`tFirstName:`t” + $_.FirstName + “,`tInitials:`t” + $_.Initials + “,`tNotes:`t” + $_.notes + “,`tPostalCode:`t” + $_.PostalCode + “,`tCity:`t” + $_.City + “,`tStreetAddress:`t” + $_.StreetAddress + “,`tPostOfficeBox:`t” + $_.PostOfficeBox + “,`tStateOrProvince:`t” + $_.StateOrProvince + “,`tTitle:`t” + $_.Title + “,`tDepartment:`t” + $_.Department + “,`tCompany:`t” + $_.Company + “,`tDescription:`t” + $_.Description >> $LogFile
# “Стало`t=> `tWebPage:`t” + $wp + “,`tLastName:`t” + $b["Name"] + “,`tFirstName:`t” + $b["Name_i"] + “,`tInitials:`t” + $b["Initials"] + “,`tNotes:`t” + $notes + “,`tPostalCode:`t” + $b["ZipCode"] + “,`tCity:`t” + $b["City"] + “,`tStreetAddress:`t” + $b["Street"] + “,`tPostOfficeBox:`t” + $b["EmplID"] + “,`tStateOrProvince:`t” + $b["City"] + “,`tTitle:`t” + $b["Title"] + “,`tDepartment:`t” + $b["Otdel"] + “,`tCompany:`t” + $b["Company"] + “,`tDescription:`t” + $b["tree_path"] >> $LogFile
“Было`t=> `tWebPage:`t” + $_.WebPage + “,`tLastName:`t” + $_.LastName + “,`tFirstName:`t” + $_.FirstName + “,`tInitials:`t” + $_.Initials + “,`tNotes:`t” + $_.notes + “,`tPostOfficeBox:`t” + $_.PostOfficeBox + “,`tTitle:`t” + $_.Title + “,`tDepartment:`t” + $_.Department + “,`tCompany:`t” + $_.Company + “,`tDescription:`t” + $_.Description >> $LogFile
“Стало`t=> `tWebPage:`t” + $wp + “,`tLastName:`t” + $b["Name"] + “,`tFirstName:`t” + $b["Name_i"] + “,`tInitials:`t” + $b["Initials"] + “,`tNotes:`t” + $notes + “,`tPostOfficeBox:`t” + $b["EmplID"] + “,`tTitle:`t” + $b["Title"] + “,`tDepartment:`t” + $b["Otdel"] + “,`tCompany:`t” + $b["Company"] + “,`tDescription:`t” + $b["tree_path"] >> $LogFile
if ($result -ne $False) {$Count++}
}
if([string]$b["Works"] -eq “0″)
{$dtout = [datetime]$b["out_date"];
#Обновим Выводимое имя пользователя
$NewDisplayName = $b["Full_Name"] + ” – уволен(а) с ” + $dtout.ToShortDateString()
Set-QADUser -Identity $_.DN -DisplayName $NewDisplayName #-WhatIf
“” + $_.DN + ” Сотрудник уволен. Выводимое Имя сменено на: ” + $NewDisplayName >> $LogFile
#Отключим учетку пользователя, если она не отключена
if ([bool](Get-QADUser -Name $_.Name -UseGlobalCatalog -Disabled) -eq $False) {
Get-QADUser $_.DN | ForEach-Object { $LL = ([datetime]$_.LastLogon).ToString(); if ( $LL.Length -eq 0 ) { $LL = “Нет данных” } };
$RecomTextDSBL += “” + $Count4 + “. ” + $b["Full_Name"] + ” уволен(а) с ” + $dtout.ToShortDateString() + “`t” + $_.DN + “`tLastLogon: ” + $LL + “`n”;
#Disable-QADUser $_.DN -WhatIf ; $RecomTextDSBL += “Действие: Отключена учетная запись $accountDN`n”
$Count4++
} #else{“Уже отключена”}
}
}elseif($b -eq 100){
#=== Информация в БОССе ЗАПРАШИВАЛАСЬ по ФИО и НЕ БЫЛА ПОЛУЧЕНА, готовим инфу для лога рекомендаций
Get-QADUser $_.DN | ForEach-Object { $LL = ([datetime]$_.LastLogon).ToString(); if ( $LL.Length -eq 0 ) { $LL = “Нет данных” } };
$BOSS_Data_by_FN_recomend += “`t” + $_.DN + “`tLastLogon: ” + $LL + “`n” + $_.Description + “`n”;
}
IF ($_.PostOfficeBox.Length -gt 0)
{
#Служебная# Set-QADUser -Identity $_.DN -PostOfficeBox “” #Обнулить всем поле PostOfficeBox (то, куда мы пишем табельный номер из БОССа)
#=== Если заполнено поле табельный номер, то пробуем получить данные по сотруднику по табельному номеру
$b2 = Get-BOSS_Data_by_EID $_.PostOfficeBox
Write-Verbose “$($_.PostOfficeBox) $($_.Name) $($_.DisplayName)”
if( ($b2.Count -gt 0)-and([string]$b2["Name"] -ne [string]$_.LastName)-and([string]$b2["Name_i"] -eq [string]$_.FirstName)-and([string]$b2["Initials"] -eq [string]$_.Initials) )
{#=== Если нашли данные в БОССе по табельному номеру, ИМЯ и ИНИЦИАЛЫ совпадают , а ФАМИЛИЯ в учетке АД НЕ совпадает с ФАМИЛИЕЙ из БОССа, то
#=== Готовим рекомендацию – СМЕНИЛАСЬ ФАМИЛИЯ ПОЛЬЗОВАТЕЛЯ -
$RecomTextLN += “” + $Count3 + “. Изменилась ФАМИЛИЯ (” + $_.PostOfficeBox +”): ” + $_.DN + “`t” + $_.DisplayName + “`n”
$RecomTextLN += “Было (AD)`t`t=> `t” + $_.LastName + “`t” + $_.FirstName + “`t” + $_.Initials + “`n”
$RecomTextLN += “Стало (БОСС)`t=> `t” + $b2["Name"] + “`t” + $b2["Name_i"] + “`t” + $b2["Initials"] + “`n”
$RecomTextLN += “===`n”
$Count3++
#Return #=== Переходим к следующему циклу ForEach-object
}
if( $b2 -eq $False )
{
#=== Записанный в учетке Табельный номер не найден в БОССе, удалим Таб.номер как неверный
Write-Verbose “Табельный номер, указанный в AD не существует в БОССе!”
Set-QADUser -Identity $_.DN -PostOfficeBox “” #-WhatIf
}
if( ($b2.Count -gt 0)-and($b2["Name"] -eq $_.LastName)-and($b2["Name_i"] -eq $_.FirstName) )
{
#=== Записанный в учетке Табельный номер найден в БОССе
Write-Verbose “Табельный номер, указанный в AD НАЙДЕН в БОССе! ФИ соответствуют!!!”
}
}
}#================================================================
“Обновлено ” + ($Count – 1) + ” учетных записей пользователей Active Directory” >> $LogFile
$dt = Get-Date -Format “dd.MM.yyyy HH:mm:ss”
“Конец: “+$dt >> $LogFile
#================================================================
if ($RecomTextLN.Length -gt 0){
$RecomText += “———————————————————————`n”
$RecomText += “Список сотрудников, у которых изменилась фамилия.`n”
$RecomText += “Если рекомендации в части ИЗМЕНЕНИЯ ФАМИЛИИ неверны – удалите содержимое поля ‘Адрес\Почтовый ящик’ свойств учетной записи пользователя.`n”
$RecomText += $RecomTextLN
}
if ($RecomTextDSBL.Length -gt 0){
$RecomText += “=====================================================================`n”
$RecomText += “Следующие сотрудники уволены, – рекомендуется отключить уч. записи:`n”
$RecomText += $RecomTextDSBL
}
$RecomText += “=====================================================================`n”
$RecomText += “Следующие ФИО не были обнаружены при запросе к БОСС Кадровик, возможно их необходимо откорректировать:`n”
$RecomText += $script:BOSS_Data_by_FN_recomend
$RecomText += “Конец: “+$dt + “`n”
Write-Progress -Activity “Working…” -Completed -Status “All done.” #Отображение индикатора выполнения завершим. Пропадет с экрана.
#.\Send-SmtpMail.ps1 -to $SmtpTo -subject “Синхронизация Active Directory и БОСС-Кадровик. РЕКОМЕНДАЦИИ АДМИНИСТРАТОРУ.” -body $RecomText
#===============================================================================
#=== Отправка EMail
#===============================================================================
Write-Verbose “Создаем объекты SmtpClient и MailMessage”
$SmtpClient = New-Object System.Net.Mail.SmtpClient
$Message = New-Object System.Net.Mail.MailMessage
Write-Verbose “Устанавливаем свойства этих объектов”
$SmtpClient.Host = $SmtpServer
#$Message.IsBodyHtml = $True
$Message.Body = $RecomText
$Message.Subject = $Subject
$Message.From = $SmtpFrom
[string[]]$To = $SmtpTo
[System.IO.FileInfo[]]$Attachment=@() # [System.IO.FileInfo[]]$Attachment= (dir c:\*.txt)
Write-Verbose “Создаем и добавляем вложения”
$Attachment | ForEach-Object {
$a = New-Object System.Net.Mail.Attachment($_.fullname)
$Message.Attachments.Add($a)
}
Write-Verbose “Добавляем получателей”
$To | ForEach-Object {$Message.To.Add($_)}
Write-Verbose “Отправляем сообщение”
$smtpclient.Send($Message)
Write-Verbose “Удаляем объекты”
$Message.Dispose()
#===============================================================================
Write-Host “Синхронизация завершена.”
Write-Host “Отчет о произведенных изменениях в Active Directory: $LogFile”
Write-Host “Рекомендации по ручной корректировке базы данных AD высланы на $SmtpTo”
#===== КОНЕЦ ===========
Свежие комментарии