Проблема Powershell со сравнением значений в ARS — ложное срабатывание

#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. Хорошего дня!