#powershell #active-directory #comparison #updates
#powershell #active-directory #сравнение #Обновления
Вопрос:
Я обновляю массовую информацию о пользователях. Скрипт получает данные из файла, сравнивает с текущими данными в ARS и при необходимости изменяет.
К сожалению, для двух параметров — «st» и «PostOfficeBox» — данные постоянно обновляются, хотя данные в файле и в AD одинаковы.
первый из них пуст, второй — нет
Я проверил напрямую —
PS> $user.$parameters.postofficebox -eq $userQuery.$parameters.postofficebox
True
Как я могу с этим справиться? Это не ошибка, но это раздражает и неэффективно постоянно обновлять одни и те же данные.
#Internal Accounts
$Parameters = @("SamAccountName", "co", "company", "department", "departmentNumber","physicalDeliveryOfficeName","streetAddress","l","st","postalCode","employeeType","manager", "division", "title", "edsvaEmployedByCountry", "extensionAttribute4", "EmployeeID", "postOfficeBox")
#import of users
$users = Import-csv -Path C:pskrbatch.csv -Delimiter "," -Encoding UTF8
Connect-QADService -Proxy
#Headers compliance
$fileHeaders = $users[0].psobject.Properties | foreach { $_.Name }
$c = Compare-Object -ReferenceObject $fileHeaders -DifferenceObject $Parameters -PassThru
if ($c -ne $null) {Write-Host "headers do not fit"
break}
#Check if account is enabled
foreach ($user in $users) {
$checkEnable = Get-ADUser $user.SamAccountName | select enabled
if (-not $checkEnable.enabled) {
Write-Host $user.SamAccountName -ForegroundColor Red
}
}
#Main loop
$result = @()
foreach ($user in $users) {
$userQuery = Get-QADUser $user.sAMaccountName -IncludedProperties $Parameters | select $Parameters
Write-Host "...updating $($user.samaccountname)..." -ForegroundColor white
foreach ($param in $Parameters) {
if ($user.$param -eq $userQuery.$param) {
Write-Host "$($user.samaccountname) has correct $param" -ForegroundColor Yellow
}
else {
try {
Write-Host "Updating $param for $($user.samaccountname)" -ForegroundColor Green
Set-QADUser -Identity $user.SamAccountName -ObjectAttributes @{$param=$user.$param} -ErrorVariable ProcessError -ErrorAction SilentlyContinue | Out-Null
If ($ProcessError) {
Write-Host "cannot update $param for $($user.samaccountname) $($error[0])" -ForegroundColor Red
$problem = @{}
$problem.samaccountname = $($user.samaccountname)
$problem.param = $param
$problem.value = $($user.$param)
$problem.error = $($error[0])
$result =[pscustomobject]$problem
}
}
catch { Write-Host "fail, check if the user account is enabled?" -ForegroundColor Red}
}
}
}
$result | Select samaccountname, param, value, error | Export-Csv -Path c:pskrfail.csv -NoTypeInformation -Encoding UTF8 -Append
А также будут оценены любые предложения по моему коду, где я могу улучшить его.
Комментарии:
1.
postoofficebox
похоже на опечатку (два последовательныхo
‘s)2. @MathiasR.Jessen вы правы, но я сделал это только здесь, поскольку я написал это вручную, в терминале все в порядке. Я исправил свою ошибку здесь, спасибо
3. Ваш ручной тест не стоит многого — оба выражения, вероятно, оцениваются
$null
как, поэтому они равны. Вы могли бы добавитьWrite-Host "Testing: $($user.$param) -eq $($userQuery.$param)"
строку надif ($user.$param ...)
инструкцией, чтобы увидеть сравниваемые отдельные значения4. вы правы. Я тоже понял это позже. Спасибо!
Ответ №1:
Подобно тому, что предлагал Матиас Р. Джессен, способ тестирования сравнения выглядит неправильно. По мере приближения к отладке добавьте либо предложенную Write-Host
команду, либо точку останова, чтобы можно было протестировать во время выполнения.
Несмотря на аспект сравнения вопроса, существует неопределенный консультативный запрос, который я попытаюсь рассмотреть.
Почему вы используете QAD вместо встроенного модуля AD. QAD потрясающий и по-прежнему превосходит собственные инструменты в нескольких областях. Но (без глубокого исследования) похоже, что вы можете обойтись здесь с помощью встроенных инструментов.
Я бы отметил, что в командлетах AD есть возможность создания экземпляра, которая позволяет выполнять инкрементные обновления даже без сравнения… т.е. Вы можете запустить Set-ADUser
командлет, и он запишет атрибуты, только если они разные.
Проверьте файл справки для Set-ADUser
Переписывать это было бы неуместно и отнимало много времени. Я бы посоветовал вам ознакомиться с этими концепциями для версии 2.0… Тем не менее, я могу предложить несколько советов, ограниченных текущим подходом.
Структура кода такова, что он будет выполняться Set-QADUser
для каждого атрибута, который нуждается в обновлении, а не для установки всех атрибутов одновременно для каждого пользователя. Вместо этого вы могли бы собрать все изменения и применить их за один запуск Set-QADUser
для каждого пользователя. Это было бы быстрее и, вероятно, имело бы более компактное ведение журнала и т. Д…
Когда вы проверяете, включена ли учетная запись, вы не делаете ничего, кроме Write-Host
. Если вы хотите пропустить этого пользователя, возможно, переместите эту логику в основной цикл и добавьте оператор Continue . Это также избавит вас от повторного выполнения цикла.
Избегайте использования =
, вместо этого вы можете использовать [ArrayList]
. Проблемы с производительностью и масштабируемостью с = хорошо документированы, поэтому вы можете найти дополнительную информацию в Google. [ArrayList]
может выглядеть примерно так:
$result = [Collections.ArrayList]@()
# ...
[Void]$result.Add( [PSCustomObject]$problem )
Я также не уверен, как должен срабатывать блок catch, если вы установили -ErrorAction SilentlyContinue
. Вероятно, вы можете удалить If($ProcessError)...
и и переместить заполнение $Result в Catch{}
блок.
Комментарии:
1. большое вам спасибо. Я проанализирую все ваши предложения и выполню их. Код менялся много раз, поэтому есть устаревшие фрагменты, такие как
Catch{}
, и я все еще новичок в Powershell. Хорошего дня!