Get-ADUser: сервер вернул следующую ошибку: недопустимый контекст перечисления

#powershell

#powershell

Вопрос:

Я пытаюсь получить всех подрядчиков и сотрудников из нашего AD с включенным true для фильтра. Сам AD очень большой и содержит много данных, что может привести к ограничению времени ожидания при запуске сценария powershell. Я получаю эту ошибку, когда я помещаю ее в переменную, и если я выполняю прямой экспорт, я получаю ограничение по времени ожидания.

Есть ли какой-либо способ собрать все данные подрядчика и сотрудника с включенными сотрудниками с big AD без возникновения этой проблемы? Я получаю вывод, но не уверен, что вывод осуществим, поскольку я получаю сообщение об ошибке.

Спасибо

 Param(
    [Parameter(Mandatory = $true,ValueFromPipeline = $false,HelpMessage = "Specify a output file name and path.")]
    [string]
    $OutputFileNamePath = $null
)
$Storage = @()
Write-Host "**********************************************************" -ForegroundColor Green
Write-Host "*                  On Process                            *" -ForegroundColor Green
Write-Host "**********************************************************" -ForegroundColor Green
$filter = @("CONTRACTOR", "EMPLOYEE")
$Storage = Get-ADUser -Filter * -Properties EmployeeNumber,Name,SamAccountName,employeeType,PasswordLastSet,LastLogonDate | Where {($_.Enabled -eq $True) -and $filter -contains $_.employeeType} | Select EmployeeNumber,Name,SamAccountName,employeeType,PasswordLastSet,LastLogonDate 
$Storage | Export-Csv -Path $OutputFileNamePath".csv" -Force
Write-Host "**********************************************************" -ForegroundColor Green
Write-Host "*                     Done                               *" -ForegroundColor Green
Write-Host "**********************************************************" -ForegroundColor Green
 

Ответ №1:

Эта статья TechNet дает нам подсказку о том, почему может возникнуть эта ошибка, в основном:

  1. Get-ADUser использует подкачку (по умолчанию 256 объектов на страницу)
  2. Запрашивать новые страницы должен клиент
  3. При конвейерной передаче объектов AD чем дольше обрабатывается код в конвейере, тем медленнее мы извлекаем данные из веб-служб Active Directory
  4. Если из-за более медленной обработки время поиска превышает 30 минут, то контекст перечисления истекает

Скорее всего, ваш запрос выполняется в течение 30 минут, что приводит к этому исключению. Решение этой проблемы заключается в создании более эффективного запроса, чтобы он завершался до этого времени или, что не рекомендуется MS:

Увеличьте значение «MaxEnumContextExpiration» для веб-службы Active Directory. Есть много причин не использовать этот подход.


Вы можете использовать LDAPFilter для повышения производительности вашего запроса, Where-Object в этом случае использование не требуется:

 $properties = 'EmployeeNumber', 'employeeType', 'PasswordLastSet', 'LastLogonDate'
$filter = '(amp;(!userAccountControl:1.2.840.113556.1.4.803:=2)(|(employeeType=CONTRACTOR)(employeeType=EMPLOYEE)))'

Get-ADUser -LDAPFilter $filter -Properties $properties
 

Чтобы преобразовать фильтр LDAP во что-то читаемое:

  • amp; — Логический И Операторный
  • | — Логический оператор OR
  • (!userAccountControl:1.2.840.113556.1.4.803:=2) — Включен пользовательский объект
  • (|(employeeType=CONTRACTOR)(employeeType=EMPLOYEE)) employeeType является «Подрядчиком» ИЛИ «сотрудником»
  • (amp;(...)(|(...)(...))) — Все предложения должны быть выполнены. Мы можем прочитать это как:
    (Пользователь включен) И (пользователь employeeType — «Подрядчик» ИЛИ «Сотрудник»)

Для дальнейшего использования Active Directory: фильтры синтаксиса LDAP

Комментарии:

1. Спасибо! Это работает для меня!

2. @Den10102020 рад помочь 😉

Ответ №2:

Я изменил ваш скрипт, но я просто собрал всех пользователей в $Users массив, а затем запустил ForEach цикл для каждого отдельного пользователя. Внутри есть If функция, которая проверяет, включен ли пользователь и что EmployeeType является -like CONTRACTOR или EMPLOYEE . Если они есть, он добавляет их в $Storage массив, а затем экспортирует его после завершения цикла.

У меня это сработало, но дайте мне знать, если у вас возникнут какие-либо вопросы:

 Param(
    [Parameter(Mandatory = $true,ValueFromPipeline = $false,HelpMessage = "Specify a output file name and path.")]
    [string]
    $OutputFileNamePath = $null
)
$Storage = @()
Write-Host "----------------------------------------------------------" -ForegroundColor Green
Write-Host "-                  On Process                            -" -ForegroundColor Green
Write-Host "----------------------------------------------------------" -ForegroundColor Green
$Users = Get-ADUser -Filter * -Properties EmployeeNumber,Name,SamAccountName,employeeType,PasswordLastSet,LastLogonDate 
Foreach($user in $users){
If(($User.Enabled -eq $True) -and (($User.EmployeeType -like "*CONTRACTOR*") -or (($User.EmployeeType -like  "*EMPLOYEE*")))){
    $Storage  = $User  
    }

}
$Storage | Export-Csv -Path $OutputFileNamePath".csv" -NoTypeInformation -Force
Write-Host "----------------------------------------------------------" -ForegroundColor Green
Write-Host "-                     Done                               -" -ForegroundColor Green
Write-Host "----------------------------------------------------------" -ForegroundColor Green
 

Комментарии:

1. Привет, Джош! Спасибо за помощь, но у меня такая же проблема на моей стороне. Решение LDAP работает для меня

2. @Den10102020 Нет проблем! Я видел комментарий выше, рад, что он смог определить, в чем заключалась ошибка, и помочь вам ее устранить.

3. Он отличное соединение! Большинство моих проблем с PowerShell были решены г-ном Скварзоном