Статья размещена автором Бетке Сергей Сергеевич

PowerShell: загружаем (импортируем) телефонную книгу в AD из .csv

Выполним обратное действие – напишем сценарий для загрузки из .csv телефонного справочника в AD.

Если Вы ранее не использовали командлеты ADpowershell, рекомендую предварительно прочитать статью “Установка и первый опыт ADpowershell на Windows Server 2003”.

Мы уже умеем выгружать телефонный справочник в .csv. Теперь настало время загрузить скорректированный справочник.

<#
    .Synopsis
        Загрузка телефонной книги из .csv файла.
    .Description
        Загружаем телефонную книку из .csv файл в AD. Находим учётную запись по displayName,
        корректируем атрибут telephoneNumber.
    .Parameter searchBase
        OU, с которой будет осуществляться выгрузка телефонной книги в .csv
    .Parameter csvFile
        Полный путь к файлу, из которого будем импортировать
    .Example
        Импортируем 

        .\ImportPhonesBook.ps1 -csvFile 'c:\temp\phoneBook.csv'
#> 

param (
    [Parameter(
        Mandatory=$false,
        Position=0,
        ValueFromPipeline=$false,
        HelpMessage="OU, в которой будут обновляться учётные записи"
    )]
    [string]
    $searchBase = 'OU=Группа Компаний ГАРО,OU=Персонал,OU=Предприятия,OU=iTg,DC=novgaro,DC=ru',
    [Parameter(
        Mandatory=$true,
        Position=1,
        ValueFromPipeline=$false,
        HelpMessage="Полный путь к файлу, из которого будем импортировать."
    )]
    [string]
    $csvFile
) 

import-module ActiveDirectory 

import-csv `
    -path $csvFile `
    -useCulture `
| % {
    $user = Get-ADUser `
        -LDAPFilter "(displayName=$($_.ФИО))" `
        -SearchBase $searchBase `
        -SearchScope Subtree `
        -Properties `
            cn, displayName, telephoneNumber
    if ($user) {
        if ($_.Телефон -eq '') {$_.Телефон=$null;}
        if ($user.telephoneNumber -ne $_.Телефон) {
            $user.telephoneNumber = $_.Телефон
            Set-ADUser -Instance $user
        }
    }
}

Задача также достаточно простая, но наткнулся на несколько проблем в процессе реализации:

  • не смог использовать -Filter в командлете Get-ADUser с выражением {displayName –eq $_.ФИО}, пришлось явно использовать -LDAPFilter;
  • строковый атрибут нельзя писать пустым в AD, вместо этого следует использовать $null (костыль в виде if ($_.телефон –eq ‘’) {$_.телефон = $null;} вставлен в сценарий по этой причине).

Выполняется в момент, даже прогресс бары вставлять смысла нет.

Отзывы » (15)

  1. По результатам реальной загрузки данных из csv, сформированного MS Excel 2003, должен добавить следующее: следует использовать параметр -UseCulture для import-csv (потому как excel выбирает разделитель полей таким же образом), а также перед запуском сценария пересохранить его в UTF-8 (excel его генерирует не в unicode), например — блокнотом. И всё будет в ажуре.

  2. Нашёл ещё один вариант — без пересохранения в UTF:

    get-content `
        -path $csvFile `
    | convertFrom-csv `
        -useCulture `
    | %{...}
    

    В таком варианте читает сценарий сам как из unicode, так и из не unicode файлов.

  3. Сергей:

    спасибо, часть вашего скрипта использовал для ввода в АД некоторых атрибутов пользователей из csv

  4. Михаил:

    Сергей, добрый вечер!

    Выполняю Ваш скрипт на своем OU. Получаю ошибку вида
    Get-ADUser : The search filter cannot be recognized
    At C:\Users\mdanilov\Desktop\import csv-ad.ps1:38 char:19
    + $user = Get-ADUser <<<< -LDAPFilter "(displayName=$($_.ФИО))"

    Хотя поле ФИО соответсвует атрибуту displayname в AD

    • Михаил:

      Лес 2003 + AD WS. Управляется через 2008 R2 RSAT

      • Михаил, приведите пожалуйста целиком переделанный сценарий или хотя бы его существенный кусок. У меня складывается впечатление, что $_ не определён на момент выполнения данной строки Вашего сценария, давайте посмотрим на сценарий в целом.

        • Михаил:
          param ( 
              [Parameter( 
                  Mandatory=$false, 
                  Position=0, 
                  ValueFromPipeline=$false, 
                  HelpMessage="OU, в которой будут обновляться учётные записи"
              )] 
              [string] 
              $searchBase = "OU=market,dc=contoso,dc=local", 
              [Parameter( 
                  Mandatory=$true, 
                  Position=1, 
                  ValueFromPipeline=$false, 
                  HelpMessage="Полный путь к файлу, из которого будем импортировать."
              )] 
              [string] 
              $csvFile
          )  
            
          import-module ActiveDirectory  
            
          import-csv -path $csvFile -useCulture ` 
           % { 
              $user = Get-ADUser -LDAPFilter "(displayName=$($_.ФИО))" -SearchBase $searchBase -SearchScope Subtree `
              -Properties `
               cn, displayName, telephoneNumber 
              if ($user) { 
                  if ($_.Телефон -eq '') {$_.Телефон=$null;} 
                  if ($user.telephoneNumber -ne $_.Телефон) { 
                      $user.telephoneNumber = $_.Телефон 
                      Set-ADUser -Instance $user
                  } 
              } 
          }
          
          • Если Вы не ошиблись при копировании, то не хватает буквальнно одного символа — | в конце строки import-csv. Естественно, в таком варианте не определена $_, отсюда и ошибка.
            Напишите пожалуйста по результатам.

  5. Михаил:

    Сергей, Большое спасибо! Выражаю Большую признательность! Благодаря Вам, мне удалось решить глобальную задачу в моей организации.

    Заработало, так и есть! Добавил символ |
    Добавил также нужные мне атрибуты в цикл

    вот кусок кода для мобильного телефона и факса. Атрибуты оставил без переименований.

          if ($user) { 
            if ($_.mobile -eq '') {$_.mobile=$null;} 
            if ($user.mobile -ne $_.mobile) { 
                $user.mobile = $_.mobile 
                Set-ADUser -Instance $user
            } 
        } 
          if ($user) { 
            if ($_.facsimileTelephoneNumber -eq '') {$_.facsimileTelephoneNumber=$null;} 
            if ($user.facsimileTelephoneNumber -ne $_.facsimileTelephoneNumber) { 
                $user.facsimileTelephoneNumber = $_.facsimileTelephoneNumber 
                Set-ADUser -Instance $user
            } 
        } 
    
  6. Андрей:

    Доброго времени суток!
    Как раз по работе возникла необходимость массого вписания email адресов, скрипты просто спасают. :)
    Только вот возникла проблема при добавлении обратно в AD, при запуске скрипта получаю:

    Set-ADUser : Для выполнения операции права недостаточны

    Хотя запускаю от домен админа.

    • 1. Сценарии Вы запускаете на DC или нет?
      2. В типовом сценарии привелегий Domain Administrators достаточно. Если только у Вас в AD не иные права (например — через делегирование) не даны на OU, в которое Вы хотите внести изменения. Проверьте предварительно возможность внесения изменений через ADUC в то же OU и под той же учётной записью.

      P.S. И ещё — компоненты ADPowerShell должны быть установлены (реплика на всякий случай).

  7. Андрей:

    Запустил скрипты с другой машины, до этого на DC запускал, все заработало. еще раз огромное спасибо за скрипты.

    • Как говорится, всегда пожалуйста. Могу предложить несколько более красивый, но не совсем оптимальный код:

      get-content `
           -path $csvFile `
      | convertFrom-csv `
           -useCulture `
      | % {
          $csvData = $_; 
          Get-ADUser `
               -LDAPFilter "(displayName=$($_.ФИО))" `
               -SearchBase $searchBase `
               -SearchScope Subtree `
               -Properties `
                   cn, displayName, telephoneNumber `
      } `
      | Set-ADUser `
          -telephoneNumber (if ($csvData.Телефон -eq '') {$null} else {$csvData.Телефон} ) `
      ;
      

      Прошу сильно не ругать, написал сходу, не тестировал. Буду благодарен Вам за отзыв по результатам тестирования. «Красота» в данном случае заключается в использовании конвейера при вызове Set-ADUser. Атрибутов может быть задано больше одного.
      Минус данного подхода в том, что он будет обновлять данные объекта в AD даже в том случае, если в нём в действительности ничего не изменилось. Что, естественно, вызовет репликацию. Зато кратко :-).

Опубликовать комментарий

XHTML: Вы можете использовать следующие HTML теги: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Tags Связь с комментариями статьи:
RSS комментарии
Обратная ссылка