Войти

Показать полную графическую версию : [решено] Создание пользователей PowerShell


Tuniq
08-08-2022, 11:07
Всем привет!
Коллеги, решил попытать счастья в PowerShell и для автоматизации рутинных задач решил написать скрипт по созданию пользователей в ActiveDirectory.
Объём небольшой, поэтому решил использовать GUI форму. И глазу приятно, и интересно.
Застопорился вот на чем:
При создании пользователя, логин транслитерируется и формируется автоматически по стандарту организации (Фамилия_Инициал1Инициал2, например Ivanov_II). Но если пользователь уже существует в рамках леса - то естественно появляется ошибка в уникальности SamAccountName.
Хочу сделать так, чтобы при занятом логине, в конце SamAccountName добавлялась цифра 1, 2, 3 и тд. То есть если найден Ivanov_II в разрезе леса, то должен создаться пользователь с логином Ivanov_II1 и так далее
Прошу Вас, опытных вояк, помочь с такой задачей. Недели 2 мучаюсь, логику как должно быть понимаю, но с реализацией хромает.
Ниже разместил код, который сварганил.
P.S. прошу не бросаться тапками, первый в карьере скрипт : )
P.P.S. Специально конфиденциальную информацию заменил пояснительными словами.
Спасибо!

#Создание УЗ
# Функция транслитерации ru->en
Function global:Get-Translit {
Param(`
[string]$inString`
)
$Translit = @{
[char]'а' = "a"
[char]'А' = "A"
[char]'б' = "b"
[char]'Б' = "B"
[char]'в' = "v"
[char]'В' = "V"
[char]'г' = "g"
[char]'Г' = "G"
[char]'д' = "d"
[char]'Д' = "D"
[char]'е' = "e"
[char]'Е' = "E"
[char]'ё' = "e"
[char]'Ё' = "E"
[char]'ж' = "zh"
[char]'Ж' = "Zh"
[char]'з' = "z"
[char]'З' = "Z"
[char]'и' = "i"
[char]'И' = "I"
[char]'й' = "y"
[char]'Й' = "Y"
[char]'к' = "k"
[char]'К' = "K"
[char]'л' = "l"
[char]'Л' = "L"
[char]'м' = "m"
[char]'М' = "M"
[char]'н' = "n"
[char]'Н' = "N"
[char]'о' = "o"
[char]'О' = "O"
[char]'п' = "p"
[char]'П' = "P"
[char]'р' = "r"
[char]'Р' = "R"
[char]'с' = "s"
[char]'С' = "S"
[char]'т' = "t"
[char]'Т' = "T"
[char]'у' = "u"
[char]'У' = "U"
[char]'ф' = "f"
[char]'Ф' = "F"
[char]'х' = "kh"
[char]'Х' = "Kh"
[char]'ц' = "ts"
[char]'Ц' = "Ts"
[char]'ч' = "ch"
[char]'Ч' = "Ch"
[char]'ш' = "sh"
[char]'Ш' = "Sh"
[char]'щ' = "sch"
[char]'Щ' = "Sch"
[char]'ъ' = ""
[char]'Ъ' = ""
[char]'ы' = "y"
[char]'Ы' = "Y"
[char]'ь' = ""
[char]'Ь' = ""
[char]'э' = "e"
[char]'Э' = "E"
[char]'ю' = "yu"
[char]'Ю' = "Yu"
[char]'я' = "ya"
[char]'Я' = "Ya"
}
$outCHR=""
foreach ($CHR in $inCHR = $inString.ToCharArray()){
if ($Translit[$CHR] -cne $Null )
{$outCHR += $Translit[$CHR]}
else
{$outCHR += $CHR}
}
Write-Output $outCHR
}
#Формирование лога
$logs = "C:\test\LogFile.csv"
#Для использования функционала .NET загружаем класс System.Windows.forms
Add-Type -assembly System.Windows.Forms

#Создание графического окна
$window_form = New-Object System.Windows.Forms.Form

#Установка заголовка и выведение окна формы в пикселях
$window_form.Text = "Создание учетной записи в домене GBU"
$window_form.Width = 800
$window_form.Height = 550

#Установка возможности растягивания формы
$window_form.AutoSize = $true


#Фамилия
$formLabel1 = New-Object System.Windows.Forms.Label
$formLabel1.Text = "Фамилия"
$formLabel1.Location = New-Object System.Drawing.Point (0,10)
$formLabel1.AutoSize = $true
$window_form.Controls.Add($formLabel1)

#Создание текстового поля
$textBox1 = New-Object System.Windows.Forms.TextBox
$textBox1.Text = ""
$textBox1.Location = New-Object System.Drawing.Point (65,10)
$textBox1.Size = New-Object System.Drawing.Size (180,20)
$window_form.Controls.Add($textBox1)

#Имя
$formLabel2 = New-Object System.Windows.Forms.Label
$formLabel2.Text = "Имя"
$formLabel2.Location = New-Object System.Drawing.Point (0,40)
$formLabel2.AutoSize = $true
$window_form.Controls.Add($formLabel2)

#Создание текстового поля
$textBox2 = New-Object System.Windows.Forms.TextBox
$textBox2.Text = ""
$textBox2.Location = New-Object System.Drawing.Point (65,40)
$textBox2.Size = New-Object System.Drawing.Size (180,20)
$window_form.Controls.Add($textBox2)

#Отчество
$formLabel3 = New-Object System.Windows.Forms.Label
$formLabel3.Text = "Отчество"
$formLabel3.Location = New-Object System.Drawing.Point (0,70)
$formLabel3.AutoSize = $true
$window_form.Controls.Add($formLabel3)

#Создание текстового поля
$textBox3 = New-Object System.Windows.Forms.TextBox
$TextBox3.Text = ""
$textBox3.Location = New-Object System.Drawing.Point (65,70)
$textBox3.Size = New-Object System.Drawing.Size (180,20)
$window_form.Controls.Add($textBox3)

#Должность
$formLabel4 = New-Object System.Windows.Forms.Label
$formLabel4.Text = "Должность"
$formLabel4.Location = New-Object System.Drawing.Point (250,10)
$formLabel4.AutoSize = $true
$window_form.Controls.Add($formLabel4)

#Создание текстового поля
$textBox4 = New-Object System.Windows.Forms.TextBox
$textBox4.Text = ""
$textBox4.Location = New-Object System.Drawing.Point (320,10)
$textBox4.Size = New-Object System.Drawing.Size (180,20)
$window_form.Controls.Add($textBox4)

#Отдел
$formLabel5 = New-Object System.Windows.Forms.Label
$formLabel5.Text = "Отдел"
$formLabel5.Location = New-Object System.Drawing.Point (250,40)
$formLabel5.AutoSize = $true
$window_form.Controls.Add($formLabel5)

#Создание текстового поля
$textBox5 = New-Object System.Windows.Forms.TextBox
$textBox5.Text = ""
$textBox5.Location = New-Object System.Drawing.Point (320,40)
$textBox5.Size = New-Object System.Drawing.Size (180,20)
$window_form.Controls.Add($textBox5)

#Контейнер
$formLabel6 = New-Object System.Windows.Forms.Label
$formLabel6.Text = "Контейнер"
$formLabel6.Location = New-Object System.Drawing.Point (0,100)
$formLabel6.AutoSize = $true
$window_form.Controls.Add($formLabel6)

#Создание текстового поля
$textBox6 = New-Object System.Windows.Forms.ComboBox
$textBox6.Location = New-Object System.Drawing.Point (65,100)
$textBox6.Size = New-Object System.Drawing.Size (450,20)
$textBox6.Text = ""
$OU = Get-ADOrganizationalUnit -LDAPFilter '(Name=*)' -SearchBase 'Путь к головной OU в АД' -Properties Name | Sort-Object -CaseSensitive
foreach ($OU1 in $OU)
{
$textBox6.Items.Add($OU1);
}
$window_form.Controls.Add($textBox6)

#Email с кредами
$formLabel7 = New-Object System.Windows.Forms.Label
$formLabel7.Text = "Письмо на"
$formLabel7.Location = New-Object System.Drawing.Point (250,70)
$formLabel7.AutoSize = $true
$window_form.Controls.Add($formLabel7)

#Создание текстового поля
$textBox7 = New-Object System.Windows.Forms.ComboBox
$textBox7.Text = ""
$textBox7.Location = New-Object System.Drawing.Point (320,70)
$textBox7.Size = New-Object System.Drawing.Size (180,20)
$csv = Import-Csv "\\NETLOGON\Scrips\Email.csv" -Encoding UTF8 -Delimiter ";"
foreach ($User in $csv)
{
$textBox7.Items.Add($User.Email);
}
$window_form.Controls.Add($textBox7)

#Кнопка выхода
$CloseButton = New-Object System.Windows.Forms.Button
$CloseButton.Location = New-Object System.Drawing.Point (100,300)
$CloseButton.Text = "Выход из программы"
$CloseButton.Width = 150
$CloseButton.Height = 50
$CloseButton.Add_Click({$window_form.Close()})
$window_form.Controls.Add($CloseButton)

#создание кнопки создания
$button = New-Object System.Windows.Forms.Button
$button.Text = 'Создать учетную запись'
$button.Location = New-Object System.Drawing.Point (550,20)
$button.Width = 160
$button.Height = 50
$window_form.Controls.Add($button)

#Привязка клика
$button.Add_Click(
{
[string]$Domain = "@домен"
$Company = "Наименование организации"
$OU = $textBox6.Text
$Server = "Контроллер домена"
#Имя
$FirstName = $textBox2.Text
#Отчество
$Initials = $textBox3.Text
#Отдел
$Departament = $textBox5.Text
#Должность
$Title = $textBox4.Text
#Фамилия
$SN = $textBox1.Text
#Формирование пароля
$pass = "Aa123456" | ConvertTo-SecureString -AsPlainText -Force
#Отображаемое имя
$FullName = $SN + " " + $FirstName + " " + $Initials
#Полное имя
$Name = $FullName
#Перевод ФИО в транслит
$translateSN = Translit $SN
$translateFirstname = Translit $FirstName.Split("")
$translateInitiasl = Translit $Initials
#Формирование логина по стандарту организации
$sam = $translateSN + "_" + $translateFirstname[0] + "" + $translateInitiasl[0]
$UserPrincipalName = $sam + $Domain
#Команда на создание юзера на основании вышеперечисленных переменных
New-ADUser -Path $OU -Server $Server -Name $Name -Department $Departament -Title $Title -DisplayName $FullName -GivenName $FirstName -Initials $Initials -Surname $SN -Company $Company -AccountPassword $pass -UserPrincipalName $UserPrincipalName -SamAccountName $sam -Enabled $true -ChangePasswordAtLogon $true
Out-File $logs -Append -InputObject ($sam + ";" + $FullName + ";" + (Get-Date).ToLongDateString() )
#Креды от почтового ящика, с которого отправится письмо
$pass = ConvertTo-SecureString "Пароль от ящика" -AsPlainText -Force
$creds = New-Object System.Management.Automation.PSCredential ("Email СТП", $pass)
#Отправка письма с результатами
Send-MailMessage -From email СТП -To $textBox7.Text -SmtpServer Почтовый сервер -Subject "Создана учетная запись" -Body "<h1>Добрый день!</h1> <p><strong>Создана учетная запись в домене GBU:</strong></p> <p><strong>Логин: $sam </p></strong> <p><strong> Пароль: Aa123456 </p></strong> <p><strong> Дата и время создания: $(Get-Date -format g) </p></strong> <p><strong> ФИО: $FullName </p></strong>" -Encoding 'UTF8' -BodyAsHtml -Credential $creds

}

)

#Запуск формы
$window_form.ShowDialog()

DJ Mogarych
09-08-2022, 09:55
$c = 1
while ($(try {Get-ADUser $sam} catch {$null})) {
$sam = "$($sam -replace "\d+$")$c"
$c++
}


Я бы ещё убрал из транслитератора заглавные буквы, т. к. в них нет смысла - логины AD нечувствительны к регистру.

И заставлять пользователей набирать символ подчёркивания при логине негуманно. Лучше вообще без него, например, ivanovii или, если уж совсем нельзя без разделителя, выбирайте такой, который можно набрать без нажатия на Shift.

Tuniq
09-08-2022, 10:24
Добрый день!
Спасибо за ответ!
Я бы ещё убрал из транслитератора заглавные буквы, т. к. в них нет смысла - логины AD нечувствительны к регистру. » - это привычка с прошлого места работы ) Про нечувствительность к регистру знаю.
И заставлять пользователей набирать символ подчёркивания при логине негуманно. Лучше вообще без него, например, ivanovii или, если уж совсем нельзя без разделителя, выбирайте такой, который можно набрать без нажатия на Shift. » - Согласен, но пока таков регламент именования объектов, поэтому приходится терпеть. В будущем году регламент планируется пересматривать и я хочу сделать без разделителя.

По коду:
Спасибо, сейчас начал формироваться уникальный логин (получаю отбивку на почту), но возникает ошибка с созданием. С чем может быть связано ?

$c = 1
while ($(try {Get-ADUser $sam} catch {$null})) {
$sam = "$($sam -replace "\d+$")$c"
$c++
}
New-ADUser -Path $OU -Server $Server -Name $Name -Department $Departament -Title $Title -DisplayName $FullName -GivenName $FirstName -Initials $Initials -Surname $SN -Company $Company -AccountPassword $pass -UserPrincipalName $UserPrincipalName -SamAccountName $sam -Enabled $true -ChangePasswordAtLogon $true
Out-File $logs -Append -InputObject ($sam + ";" + $FullName + ";" + (Get-Date).ToLongDateString() )

Ошибка стандартная, New-ADUser : Не удалось выполнить операцию, так как значение имени участника-пользователя, предоставленное для добавления или изменения, не является уникальным в пределах леса

Tuniq
09-08-2022, 11:00
Разобрался. Формирование UPN сместил под функцию и все отрабатывает корректно!
Спасибо большое за помощь!

DJ Mogarych
09-08-2022, 14:05
Формирование UPN »
А зачем его формировать? Он и сам умеет.




© OSzone.net 2001-2012