Архив

Archive for the ‘PowerShell’ Category

Актуализация данных в Active Directory (версия XLSX)

Перейдем сразу к телу.
Данная заметка является продолжением темы «Актуализация данных в Active Directory» и представляет новую — вторую версию скрипта.
В первой версии в качестве источника данных выступала SQL база данных системы управления персоналом «БОСС – Кадровик» и PowerShell командлеты для работы с Active Directory от Quest Software.
В этой — второй версии скрипта в качестве источника данных выступает Excel-файл формата .xlsx и PowerShell со штатными командлетами работы с Active Directory в WIndows Server 2008 R2.

Итак, имеем:
— Active Directory, Windows Server 2008 R2, PowerShell с установленными командлетами по управлению Active Directory
— «Источник данных» — Excel-файл — список сотрудников (пример)
— Специально обученный офис менеджер или секретарь, вручную обновляющий информацию в «Источнике данных»

Необходимо:
— периодически обновлять некоторую информацию о пользователях в каталоге Active Directory на основе информации, полученной из «Источника данных»
— журналировать произведенные изменения
— высылать по электронной почте отчёт о работе и рекомендации системному администратору

Решение:
Скрипт на PowerShell, реализующий заданные требования.
Скрипт можно выполнять интерактивно, или через планировщик задач, например командой: %windir%\system32\WindowsPowerShell\v1.0\powershell.exe -command ‘\\ad.demo.ru\dfs$\Deploy\SyncXLS2AD\SyncXLS2AD.ps1’ .

Особенность скрипта состоит в том, что чтение данных из Excel-файла производится без использования приложения Microsoft Office Excel.

Далее представлен сам скрипт «как есть».
Скачать скрипт целиком в виде текстового файла. Тег «Далее»

Рубрики:PowerShell

Microsoft Office Communications Server 2007 R2 PowerShell Scripts


Примеры PowerShell скриптов для OCS 2007 R2
http://blogs.technet.com/b/csps/p/ocs2007r2.aspx

Update:
Другие скрипты:
Получить список номеров телефонов пользователей
dsquery * dc=ad,dc=webzavod,dc=ru -scope subtree  -attr msRTCSIP-PrimaryUserAddress msRTCSIP-Line -limit 1000 -l -filter «(msRTCSIP-Line=*)»


Дополнительно:
Microsoft Lync Server 2010 PowerShell Scripts

Рубрики:OCS, PowerShell

Enable existing email users for Lync Server

LyncServerLogo

PowerShell Скрипт, автоматизирующий заведение пользователя в Lync Server на основе его email адреса, аналогично, как мы делали для OCS тут — Enable existing email users for Communications Server:


Clear-Host
#################################################################################


# Илгиз Мамышев
# Power Shell. Включение Email-Enabled пользователей в Lync Server
# Версия: 03.11.2010
#################################################################################
Write-Host -foregroundcolor Green "Включение Email-Enabled пользователей в Lync Server"
Write-Host -foregroundcolor Green "Пожалуйста подождите.."

### Определим переменные
#################################################################################
$OU="ou=webzavod,dc=ad,dc=webzavod,dc=ru" #OU, в котором будем искать пользователей
$LyncServer="wz-Lync.ad.webzavod.ru" #Lync RegistrarPool
# Получить список политик: Get-CsVoicePolicy
$VoicePolicy="Внутренние и по России звонки"#Lync Voice Policy
# Получить список планов: Get-CSDialPlan
$DialPlan="SamaraProfile" #Lync Voice Dial Plan
# Получить список политик: Get-CSExternalAccessPolicy
$ExternalAccessPolicy="Allow Federation+Public+Outside Access" #Lync External Access Policy
$LogFile = "C:\Share\Scripts\Enable-CSEmailEnabledUsers\Enable-CSEmailEnabledUsers.log"
$dt = Get-Date -Format "dd.MM.yyyy HH:mm:ss"
#################################################################################

### Импортируем модуль с командлетами Lync Server
cd $env:UserProfile; Import-Module 'C:\Program Files\Common Files\Microsoft Lync Server 2010\Modules\Lync\Lync.psd1'

### Получим список пользователей в OU, не включенных в Lync Server, с заполненным полем WindowsEmailAddress, с незаполненным полем SIPAddress
$OUUsers = &{Get-CsAdUser -OU $OU -Filter {Enabled -ne $True} | Where-Object {$_.UserAccountControl -notlike "*AccountDisabled*"} | Where-Object {$_.WindowsEmailAddress -ne ""} | Where-Object {$_.SIPAddress -eq ""} };
### Завершим скрипт если нет пользователей для обработки
if ($OUUsers -eq $Null) {Write-Host -foregroundcolor Green "Нет пользователей для обработки. Завершение через 10 секунд..";Start-Sleep -s 10; exit};

### Включить пользователей в Lync Server
$OUUsers | Foreach-Object {Enable-CsUser -Identity $_.UserPrincipalName -RegistrarPool $LyncServer -SipAddressType EmailAddress}

### Отключить ВСЕХ пользоваателей Lync Server в конкретном OU (Пример. Для тестирования)
#Get-CsUser -OU $OU | Foreach-Object { Disable-CsUser -Identity $_.UserPrincipalName };

### Пауза 15 секунд для распространения изменений Lync Server
Write-Host -foregroundcolor Green "Пауза 15 секунд для распространения изменений Lync Server.."
Start-Sleep -s 15

### Настроить пользователей, который только что включили в Lync Server
Write-Host -foregroundcolor Green "Настройка пользователей Lync Server.."
$OUUsers | Set-CSUser -EnterpriseVoiceEnabled $True
$OUUsers | Grant-CSVoicePolicy -policyname $VoicePolicy
$OUUsers | Grant-CSVoicePolicy -policyname $VoicePolicy
$OUUsers | Grant-CSDialPlan -policyname $DialPlan
$OUUsers | Grant-CSExternalAccessPolicy -policyname $ExternalAccessPolicy

### Выведем информацию о настроенных пользователях
Write-Host -foregroundcolor Green "Lync Server Summary.."
"" + $dt + " Enabled Users for Lync Server" >> $LogFile
$OUUsers | Get-CSUser | Format-Table DisplayName, SipAddress, Enabled >> $LogFile

exit

Скачать скрипт Enable-CSEmailEnabledUsers.ps1

Копируем скрипт на Lync Server и настраиваем его на периодический запуск в планировщике задач Windows командами:

REM Изменим ExecutionPolicy
%windir%\system32\windowspowershell\v1.0\powershell.exe Set-ExecutionPolicy Unrestricted

REM Создадим задание в Планировщике заданий. Запуск PowerShell скрипта ежедневно в 13:00, запуск от учетной записи Системы
schtasks /create /tn "Enable-CSEmailEnabledUsers" /tr "%windir%\system32\windowspowershell\v1.0\PowerShell.exe -command C:\Share\Scripts\Enable-CSEmailEnabledUsers\Enable-CSEmailEnabledUsers.ps1" /sc daily /st 13:00 /ru System

З.Ы.:
Еще материал на эту тему — PowerShell Script to create new user, enable for Exchange, UM and Lync Server

Рубрики:Lync, PowerShell

Microsoft Lync Server 2010 PowerShell Scripts

LyncServerLogo

Примеры скриптов, которые Вам помогут в работе с Lync Server
http://blogs.technet.com/b/csps/p/scripts.aspx


Как включить HD Video в Lync 2010
Set-CsMediaConfiguration -Identity:Global -MaxVideoRateAllowed HD720p15m
Экспорт переписки из базы Archiving Server
Export-CsArchivingData -UserUri «adonin@croc.ru» -DBInstance SQLServer –StartDate “2/3/2011” –EndDate “2/4/2011” -OutputFolder «c:\temp»
How to enable Siren?
set-CsMediaConfiguration –identity global -EnableSiren $true
Увеличить разрешенное кол-во групп рассылки в списке контактов с 10 до 64
Set-CsClientPolicy -Identity Global -MaximumDGsAllowedInContactList 64
Получить список блокируемых Lync расширений файлов
(Get-CsFileTransferFilterConfiguration).extensions
Получить список номеров телефонов пользователей
Get-CSUser  | ? {$_.LineURI} | ft Identity,LineURI
Получить список номеров телефонов (Вариант от А.Донина)

$path=»c:\temp\PhoneBook.csv»
$PhoneBook=@()
$PhoneBook = (Get-CsUser | ?{$_.LineURI -ne «»} | %{$_.Name + «,»+$_.LineURI+»,User»})
$PhoneBook += (Get-CsAnalogDevice | %{$_.DisplayName+ «,»+$_.LineURI+»,Analog Device»})
$PhoneBook += (Get-CsCommonAreaPhone | %{$_.DisplayName+ «,»+$_.LineURI+»,Common Area Phone»})
$PhoneBook +=(Get-CsExUmContact | %{$_.Name + «,»+$_.LineURI+»,UM Contact»})
$PhoneBook +=(Get-CsRgsWorkflow | %{$_.Name + «,»+$_.LineURI+»,Workflow»})
$PhoneBook += (Get-CsDialInConferencingAccessNumber | %{$_.DisplayName+ «,»+$_.LineURI+»,DialIn»})
$PhoneBook += (Get-CsCallParkOrbit| %{$_.Identity+ «,»+$_.NumberRangeStart+»-«+$_.NumberRangeEnd+»,Call Park Orbit»})
$PhoneBook >> $path


Дополнительно:
Microsoft Office Communications Server 2007 R2 PowerShell Scripts

Рубрики:Lync, PowerShell

Актуализация данных в 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»
#===== КОНЕЦ ===========

Рубрики:PowerShell