Почему $ PSItem не ведет себя должным образом при использовании аргумента -Filter на основе скобок? - PullRequest
0 голосов
/ 02 июля 2018

Я помогал пользователю с этим вопросом, связанным с моим ответом здесь: Скрипт Powershell для добавления пользователей в группу A / D из .csv, используя только адрес электронной почты?

Первоначально я написал сценарий следующим образом, используя для скобок фильтр Get-AdUser, например:

Import-CSV "C:\users\Balbahagw\desktop\test1.csv" | 
  Foreach-Object {

    # Here, $_.EmailAddress refused to resolve
    $aduser = Get-ADUser -Filter { EmailAddress -eq $_.EmailAddress }

    if( $aduser ) {
      Write-Output "Adding user $($aduser.SamAccountName) to groupname"
      Add-ADGroupMember -Identity groupname -Members $aduser
    } else {
      Write-Warning "Could not find user in AD with email address $($_.EmailAddress)"
    }
  }

Однако $_.EmailAddress не удалось заполнить значение. Однако замена фильтра Get-ADUser на строковый фильтр сработала как и предполагалось:

$aduser = Get-ADUser -Filter "EmailAddress -eq '$($_.EmailAddress)'"

Какую странность я испытываю и почему? Это потому, что когда я использую скобки, это рассматривается как новая область видимости и $PSItem не будет следовать?

Ответы [ 2 ]

0 голосов
/ 02 июля 2018
  • -Filter параметры обычно строка параметры (проверьте с помощью
    Get-Help Get-AdUser -Parameter Filter)

    • Как правило, они не принимают код PowerShell - фильтры зависят от поставщика и часто имеют собственный синтаксис, хотя бывает PowerShell- как в случае командлетов AD.
      Кроме того, они обычно не знают о переменных PowerShell (см. Ниже).
  • Таким образом, когда передается блок сценария ({ ... }), он преобразуется в строку , что соответствует его литерал содержимое (все между открытием { и закрытием }):

    • { EmailAddress -eq $_.EmailAddress }.ToString() дает буквальную строку EmailAddress -eq $_.EmailAddress - без какой-либо оценки - и вот что Get-AdUser видит - нет оценка имеет место.

    • Предполагается, что, по-видимому, из лучших побуждений, но ошибочных попыток поддержать широко распространенную, но необдуманную практику передачи блоков сценариев параметру -Filter командлетов AD, кажется, что эти командлеты явно расширяют простые ссылки на переменные, такие как $_ в строковом литерале, который они получают, но это не работает с выражениями , такими как доступ к свойству переменной ($_.EmailAddress)

Следовательно, -Filter аргументы обычно должны передаваться как расширяемые строки ("...") ; в данном случае:

 -Filter  "EmailAddress -eq '$($_.EmailAddress)'"

То есть, единственное надежное решение - это использовать строки с переменными частями , запеченными в , впереди , через расширение строки, как показано выше.

Для значений, которые не являются ни числами, ни строками, например даты , вам может потребоваться использовать литерал строку ('...') и полагаться на поставщика AD возможность оценивать простые ссылки на переменные PowerShell (например, $date) - подробности см. в этом ответе .

Как уже говорилось, синтаксис фильтров AD является только PowerShell- , как и : он поддерживает только подмножество операторов, поддерживаемых PowerShell, и те, которые поддерживаются, слегка отличаются по поведению - см. Get-Help about_ActiveDirectory_Filter.

  • заманчиво использовать блоки скриптов, потому что код внутри не требует экранирования встроенных кавычек / чередования символов кавычек и не использует оператор подвыражения $(...). Однако, кроме того, что использование блоков сценариев в качестве строк в целом неэффективно, проблема здесь заключается в том, что блок сценария дает обещание, что он не может сохранять : он выглядит как будто вы передаете кусок кода PowerShell , но вы этого не сделаете - и он работает только в простых случаях (и то только из-за неправильного размещения, упомянутого выше); как правило, трудно вспомнить, при каких обстоятельствах он не работает и как заставить его работать в случае сбоя.

  • Поэтому очень жаль, что официальная документация использует блоки сценариев в своих примерах.

Для более подробного обсуждения см. этот ответ моего.

0 голосов
/ 02 июля 2018

Вы не ошиблись, это ошибка модуля

Тип полезной нагрузки, которую вы должны использовать с параметром -Filter, отличается в зависимости от того, с каким провайдером вы работаете, решение о дизайне может быть довольно запутанным!

Вывод Get-Help Get-ADUser -Parameter Filter дает вам довольно подробные примеры различных вариантов синтаксиса, которые вы можете использовать с реализацией синтаксиса фильтра в поставщике Active Directory.

Вот пример:

#To get all user objects that have an e-mail message attribute, use one of the following commands:

Get-ADUser -Filter {EmailAddress -like "*"}

Похоже, что поставщик ActiveDirectory устанавливает особые ограничения, которые вы должны заключить в кавычки. Вот что происходит, когда я ищу свою учетную запись, не заключая в кавычки свою электронную почту.

Get-ADUser -Filter {EmailAddress -eq stephen@foxdeploy.com}
Get-ADUser : Error parsing query: 'EmailAddress -eq stephen@foxdeploy.com' 
Error Message: 'syntax error' at position: '18'.

Но добавление кавычек? Это работает!

Get-ADUser -Filter {EmailAddress -eq "stephen@foxdeploy.com"}


DistinguishedName : CN=Stephen,CN=Users,DC=FoxDeploy,DC=local
Enabled           : True
GivenName         : Stephen
Name              : Stephen
ObjectClass       : user
ObjectGUID        : 6428ac3f-8d17-45d6-b615-9965acd9675b
SamAccountName    : Stephen
SID               : S-1-5-21-3818945699-900446794-3716848007-1103
Surname           : 
UserPrincipalName : Stephen@FoxDeploy.local

Как заставить свою работу

Теперь, из-за этой запутанной реализации фильтра, вам нужно изменить поиск пользователя в строке 5 на следующее:

 $aduser = Get-ADUser -Filter "EmailAddress -eq `"$($_.EmailAddress)`""

Мы предоставляем -Filter полезную нагрузку в виде строки. Далее мы хотим использовать String Expansion, чтобы извлечь свойство .EmailAddress, поэтому мы оборачиваем строку в $( ), чтобы сигнализировать о расширении строки. Наконец, поставщик хочет, чтобы наше сравнение фильтров было заключено в кавычки, поэтому мы помещаем двойные кавычки вокруг него, а затем экранируем кавычки с помощью символа обратной галочки.

А теперь должно сработать.

TLDR - обвинять провайдера и обвинять модуль, так как существует много несоответствий с модулем Active Directory.

...