2015-04-22 2 views
0

Надеюсь, вопрос PowerShell noob, но как мне получить доступ к текущему объекту конвейера внутри блока сценария, который также находится в хэш-таблице?PowerShell Pipeline Script Block внутри Hashtable

Вот что я пытаюсь сделать в полном объеме:

Get-ADGroupMember "Group Name" | 
    Where {$_.objectClass -eq "user"} | 
    Get-ADUser -properties extensionAttribute1 | 
    Where {$_.extensionAttribute1 -ne ($_.UserPrincipalName -replace "@ADdomain.com", "@GAdomain.com")} | 
    Set-ADUser -replace @{extensionAttribute1=&{$_.UserPrincipalName -replace "@ADdomain.com", "@GAdomain.com"}} 

У меня все работает на эту последнюю строку, где новый extensionAttribute1 должен быть сформирован из текущих пользователей UserPrincipalName за исключением, заменяющий домен , Запуск этот код приводит к ошибке:

+ Set-ADUser <<<< -replace @{ExtensionAttribute1=&{$_.UserPrincipalName -replace "@ADdomain.com", "@GAdomain.com"}} 
+ CategoryInfo   : InvalidOperation: (CN=Bar\, Fo...ADdomain,DC=com:ADUser) [Set-ADUser], ADInvalidOperationException 
+ FullyQualifiedErrorId : replace,Microsoft.ActiveDirectory.Management.Commands.SetADUser 

Замена кода внутри блока сценария со строкой работает нормально (ниже), так что кажется, что какой-то вопрос доступа к текущему объекту конвейера. $_ не работает в этом случае?

Set-ADUser -replace @{extensionAttribute1=&{"foobar"}} 
+0

Я думаю, что здесь происходит то, что Set-ADUser принимает пакет информации сразу и поэтому похож на вызов '$ MyArrayOfUsers | Set-ADUser ... 'где единственным объектом в конвейере является массив, а не каждый пользователь (я предполагаю). Если вместо этой строки вместо последней строки следует 'Foreach-Object {Set-ADUser $ _ [email protected]{extensionAttribute1=&{$_.UserPrincipalName -replace" @ ADdomain.com "," @ GAdomain.com "}}}' та работа? Это означает, что нужно много индивидуальных вызовов вместо одного большого звонка, но я думаю, что это должно сработать.Я не могу проверить это прямо сейчас, но дайте мне знать, если это сработает. – squid808

+0

@ squid808 Да, это действительно работает. Странно, так что '$ _' действителен только для некоторых команд? – Panman

+0

Я думаю, что это больше о том, как вы его используете, поскольку оно представляет одно значение, 'this'. Я отвечу свои размышления в ответ, чтобы я мог быть немного более подробным. – squid808

ответ

0

Короткий ответ, кажется, используя Еогеасп в вашем трубопроводе, как таковой:

Get-ADGroupMember "Group Name" | 
    Where {$_.objectClass -eq "user"} | 
    Get-ADUser -properties extensionAttribute1 | 
    Where {$_.extensionAttribute1 -ne ($_.UserPrincipalName -replace "@ADdomain.com", "@GAdomain.com")} | 
    foreach-objct {Set-ADUser $_ -replace @{extensionAttribute1=&{$_.UserPrincipalName -replace "@ADdomain.com", "@GAdomain.com"}}} 

А почему, я уверен, что это потому, что Set-ADUser принимает только один объект, будь то это один ADUser или один набор ADUsers. Так как $_ представляет , то, как вы это делали, Set-ADUser отображал $_ как один объект, который вы предоставляли в конвейере - группу пользователей (а не каждого отдельного пользователя).

Примечание: следующие предположения! Если я ошибаюсь, исправьте меня!

Относительно Set-ADUser, принимающего один или несколько объектов ... вот моя догадка. Если вы посмотрите на типы ввода Set-ADUser, он дает типы None или Microsoft.ActiveDirectory.Management.ADUser. Но, как вы видели, вы также можете пройти по коллекции объектов ADUser, и Set-ADUser тоже примет это. Из моего понимания этого командлета, когда вы его вызываете, вы можете запустить ту же команду Set для всех объектов в этой коллекции. Например, вы могли бы сделать, как вы упомянули (предполагая, что $ пользователей содержит все, что в трубопроводе до этого):

$users | Set-ADUser -replace @{extensionAttribute1=&{"foobar"}} 

Я думаю, что под капотом, Set-ADUser принимает $ пользователей в качестве одного значения параметра (путем установки ValueFromPipeline attribute в true в коде) и применения параметров, которые вы предоставили каждому объекту в нем. Поскольку итерация коллекции происходит в коде командлета (который больше не находится в PowerShell, это скомпилированный код .Net), то $_ не будет использовать здесь для представления каждого объекта.

Я не уверен в механизме того, почему трубопровод позволяет вам запускать Get-ADUser в псевдо-foreach-моде, поскольку они имеют одинаковые типы ввода (вы называете это аналогичным образом без использования foreach), но на основе доказательств, Я должен предположить, что это под капотом. Если у кого-то есть дополнительные идеи, мне определенно интересно узнать. Я могу быть полностью вне базы!

+0

Я думаю, что основная причина, по которой он работал, заключается в том, что вы добавили позиционную переменную для -Identity. В этом случае вы установите его в «Set-ADUser $ _ ...». До этого ничто не указывало, какой пользователь должен установить. . В некоторых ситуациях подразумевается PS или более поздняя версия. В основном это перегружено. Код выполняется один раз для каждого объекта в потоке. Я не могу понять, когда вам нужно явно использовать% {} в конвейере, поэтому я использую его явно в любое время, когда может быть более одного объекта. – Xalorous

+0

Я не уверен, что это подразумевается в конвейере или в самом коде командлета. Является ли конвейер предположением, что вы хотите% для Get-ADUser, или он просто принимает коллекцию? – squid808

+0

Я просто пишу, полагая, что мне нужно% {} на однострочных. Поскольку foreach работает, если есть только один объект, он становится последовательным. Я также предпочитаю сценарии для однострочных номеров с комментариями и функциями и форматированием для удобства чтения. – Xalorous

Смежные вопросы