Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Скриптовые языки администрирования Windows (http://forum.oszone.net/forumdisplay.php?f=102)
-   -   [решено] Импорт из CSV в AD с помощью PowerShell (http://forum.oszone.net/showthread.php?t=237817)

rox33 03-07-2012 17:57 1945140

Импорт из CSV в AD с помощью PowerShell
 
Добрый день!
Такая задача стоит:
Из файла .csv (составленного сторонним софтом) импортировать в ActiveDirectory изменения в списоке пользователей, заменяя устаревшую информацию (телефоны, должности) в AD. Новых юзверей создавать не надо. Только менять несоответствующую информацию.
Т.е. есть файл типа:
читать дальше »
displayName;mail;TelephoneNumber;mobile;homephone
Иван Иваныч;ivan.ivanich@test.ru;135;8(921)555-55-55;302

В AD есть пользователь Иван Иваныч, с неправильным или пустым email, телефоном и т.п.
Нужно, чтобы программа меняла данные в AD, при несовпадении с данными из csv.

Долго бьюсь, читал много в интернетах - пока что не получается. Пробовал
вот эту тему , подправим под себя (как умел), не помогло.
Может кто готовое решение показать?

Kazun 03-07-2012 22:00 1945279

Код:

$users = Import-Csv users.csv -Delimiter ";"
$props = $users | Get-Member -MemberType NoteProperty | Select -Expand Name

foreach ($user in $users)
{
        $objuser = ([adsisearcher]"(displayname=$($user.displayName))").FindOne().GetDirectoryEntry()
        $props | Foreach {
                $prop = $_.ToLower()
                if ($user.$prop -ne $objuser.InvokeGet($prop))
                {
                        $objuser.Put("$prop",$user.$prop)
                }
        }
        $objuser.SetInfo()
}


rox33 04-07-2012 10:23 1945529

Спасибо огромное за скрипт. Всё заработало (была ошибка - разобрался - дело было в csv, пропущено поле).

Вопрос теперь вот какой,сработает ли скрипт, если в csv будет 700 пользователей? (на 5-10 пробовал - всё ок, разницы никакой по-идее, но всё же...)
Можно ли сделать, чтобы он, как критерий отбора, выбирал не displayName, а Mail? (т.е. выбирал по полю email и если оно совпадает с полем email в списке - менял всю несоответствующую информацию).
И ещё такой вопрос, если будут пустые поля, будет ли отрабатывать скрипт дальше, или будет останавливаться и дальше юзверя с ошибкой не пойдёт?

так?
читать дальше »

$users = Import-Csv users.csv -Delimiter ";"
$props = $users | Get-Member -MemberType NoteProperty | Select -Expand Name

foreach ($user in $users)
{
$objuser = ([adsisearcher]"(mail=$($user.mail))").FindOne().GetDirectoryEntry()
$props | Foreach {
$prop = $_.ToLower()
if ($user.$prop -ne $objuser.InvokeGet($prop))
{
$objuser.Put("$prop",$user.$prop)
}
}
$objuser.SetInfo()
}

Molchune 04-07-2012 11:47 1945582

Вот смотри.

Код:

Add-PSSnapin Quest.ActiveRoles.ADManagement
# Импортируем пользователей из csv файла, где разделителем является ";"
$userCSV=import-csv -Path d:\user.csv -Delimiter ";"
#$userCSV
# Импортируем пользователей из АД
$userAD = Get-QADUser -SizeLimit 0 -SearchRoot test.ru/OU
#$userAD
#сравниваем Пользователей из АД с пользователями в csv файле по свойству Email и выбираем пользователей которых надо добавить в АД
$compare = Compare-Object -ReferenceObject $userAD -DifferenceObject $userCSV -Property Email | Where-Object {$_.SideIndicator -eq "=>"}
$compare
#Проверяем что есть пользователи которых надо добавить
if ($compare.Count -ge '1' ) {
    foreach ($usercompare in $compare) {
        $user = $userCSV| Where-Object {$_.Email -match $usercompare.email}
        $user
        #Добавляем пользователей
        New-QADUser -name  $user.name -DisplayName DisplayName -UserPassword $user.Password -email $user.email -MobilePhone $user.MobilePhone -Description $user.Description  -ParentContainer test.ru/OU -WhatIf
        }
    } else {
        'Новых пользователей нет'
    }

Примечения:
- в csv файлк поле EmailAddress изменил на Email
- для работы с AD исползуется модуль ActiveRoles Management Shell for Active Directory. Его надо сначало скачать и подключается он второй строчкой Add-PSSnapin Quest.ActiveRoles.ADManagement.
- оставил закоменченные строки с отображением всех перменных. Для просмотра прото раскомменть их.
- в строчке New-QADUser.... для создания пользователей убери -WhatIf
- тут только для новых пользователей. Если надо и для редактирования существующих то надо изменить "Where-Object {$_.SideIndicator -eq "=>"}" на "Where-Object {$_.SideIndicator -eq "=="}" и вместо New-QADUser использовать Set-QADUser -Identity $user.email -DisplayName $user.DisplayName -UserPassword $user.Password -Description $user.Description -MobilePhone $user.MobilePhone . В принципе это можно реализовать все в одном скрипте.

rox33 04-07-2012 12:25 1945600

2 Molchune
Спасибо!
Есть вопрос по скрипту:
Если в списке не будет пароля у существующего пользователя - что произойдёт?
Добавлю в csv поле Password, но нужно ли заполнять его у всех юзверей (в принципе это тот же вопрос ;) )?

Цитата:

- тут только для новых пользователей.
Это про что?


ЗЫ проверил работу скрипта - пользователей создаёт (не совсем корректно - но это моя ошибка, наверное). А вот данные при несоответствии - не меняет. Например не поменял телефон (telephonenumber).
А мне бы нужно именно замена данных пользователей (телефоны, должности и т.п.) с определением пользователя по mail'у. Создание это уже плюшка, но не обязательная ;)

Ещё раз спасибо!

ЗЫЫ после вашего скрипта перестал работать скрипт от Kazun'a

Ошибка вот такая:
читать дальше »
Нельзя вызвать метод для выражения со значением NULL.
C:\1.ps1:6 знак:93
+ $objuser = ([adsisearcher]"(displayname=$($user.displayName))").FindOne().GetDirectoryEntry <<<< ()
+ CategoryInfo : InvalidOperation: (GetDirectoryEntry:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull

Нельзя вызвать метод для выражения со значением NULL.
C:\1.ps1:9 знак:41
+ if ($user.$prop -ne $objuser.InvokeGet <<<< ($prop))
+ CategoryInfo : InvalidOperation: (InvokeGet:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull

Нельзя вызвать метод для выражения со значением NULL.
C:\1.ps1:9 знак:41
+ if ($user.$prop -ne $objuser.InvokeGet <<<< ($prop))
+ CategoryInfo : InvalidOperation: (InvokeGet:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull

Нельзя вызвать метод для выражения со значением NULL.
C:\1.ps1:9 знак:41
+ if ($user.$prop -ne $objuser.InvokeGet <<<< ($prop))
+ CategoryInfo : InvalidOperation: (InvokeGet:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull

Нельзя вызвать метод для выражения со значением NULL.
C:\1.ps1:9 знак:41
+ if ($user.$prop -ne $objuser.InvokeGet <<<< ($prop))
+ CategoryInfo : InvalidOperation: (InvokeGet:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull

Нельзя вызвать метод для выражения со значением NULL.
C:\1.ps1:9 знак:41
+ if ($user.$prop -ne $objuser.InvokeGet <<<< ($prop))
+ CategoryInfo : InvalidOperation: (InvokeGet:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull


Дальше больше.
Возможно ли, чтобы Ваш скрипт поменял имена в AD? Внешне - они не изменились...

ЗЫЫЫ Разобрался, Ваш скрипт поменял displayname у большинства пользователей. Со сдвигом по списку. Буду разбираться дальше.
Скорее всего дело в лишней ;

Molchune 04-07-2012 14:22 1945673

Он только добавляет новых.
Если пользователь был, то он его не трогает.
Я просто изначально не правильно понял, думал надо сравнить списки из csv и AD и добавить новые.
Если надо изменить инфу уже существующих. То вот так вот. (в принципе это же и прошлый скрипт просто изменены условия) и не создается пользователь а обнвляются параметры.
Код:


Add-PSSnapin Quest.ActiveRoles.ADManagement
$userCSV=import-csv -Path d:\user.csv -Delimiter ";"
$userAD = Get-QADUser -SizeLimit 0 -SearchRoot test.ru/OU
$compare = Compare-Object -ReferenceObject $userAD -DifferenceObject $userCSV -Property Email | Where-Object {$_.SideIndicator -eq "=="}
    foreach ($usercompare in $compare) {
        $user = $userCSV| Where-Object {$_.Email -match $usercompare.email}
        Set-QADUser -Identity $user.email -DisplayName $user.displayname -UserPassword $user.Password -MobilePhone $user.MobilePhone -Description $user.Description  -WhatIf
        }

Цитата:

Цитата rox33
Если в списке не будет пароля у существующего пользователя - что произойдёт? »

В случае создания пользователя создаст пользователя но учетка будет отключена.
В случае обновления пользователя просто сбросит пасс.

Цитата:

Цитата rox33
ЗЫЫЫ Разобрался, Ваш скрипт поменял displayname у большинства пользователей. Со сдвигом по списку. Буду разбираться дальше.
Скорее всего дело в лишней ; »

В принципе не должен был ничего менять со сдвигом.
А csv открыть в Exel то можно? и там будет отлично видно что куда могло уехать.

rox33 04-07-2012 14:43 1945686

2 Molchune
Скрипт всё равно пригодится;) создание пользователей в планах ;)
В excel открыть сложно;) автономный сервер, пока офис туда ставить не хотел, когда буду тестить перед боевой машиной - попробую.

В общем, сейчас всё попробую.
Спасибо всем отписавшимся огромнейшее ! =)

rox33 04-07-2012 18:10 1945871

Попробовал.
На QAD скрипт выдаёт такое:
читать дальше »
Set-QADUser : Отсутствует аргумент для параметра "Identity". Укажите параметр типа "Quest.ActiveRoles.ArsPowerShellSnap
In.Data.IdentityParameter" и повторите попытку.
C:\2.ps1:7 знак:30
+ Set-QADUser -Identity <<<< -Email $user.Email -DisplayName $user.displayname -MobilePhone $user.MobilePhone
-Description $user.Description -WhatIf
+ CategoryInfo : InvalidArgument: (:) [Set-QADUser], ParameterBindingException
+ FullyQualifiedErrorId : MissingArgument,Quest.ActiveRoles.ArsPowerShellSnapIn.Powershell.Cmdlets.SetUserCmdlet

Я так понимаю, что он не может считать параметр, который подставляет в Identity. Почему - загадка.

Вот CSV:
читать дальше »
DisplayName;Email;TelephoneNumber;mobile;homephone
Иванов Иван;ivan.ivanov@test.ru;101;495-999-66-99;8-999-999-88-22
Дмитриев Дмитрий;Dmitry.Dmitriev@test.ru;10444;8(921)555-55-55;302
Василий Васильев;vasily.vasiliev@test.ru;11107;+7 (921) 555-8877;+7 (911) 6777777


Список перепроверял миллион раз - не понимаю.
На скрипт, который дал Kazun - всё срабатывает, с изменением на такой скрипт:
читать дальше »
$users = Import-Csv c:\list.csv -Delimiter ";"
$props = $users | Get-Member -MemberType NoteProperty | Select -Expand Name

foreach ($user in $users)
{
$objuser = ([adsisearcher]"(mail=$($user.Email))").FindOne().GetDirectoryEntry()
$props | Foreach {
$prop = $_.ToLower()
if ($user.$prop -ne $objuser.InvokeGet($prop))
{
$objuser.Put("$prop",$user.$prop)
}
}
$objuser.SetInfo()
}


Правда выдаёт ошибку, но делает. Ошибка такая:
читать дальше »
Исключение при вызове "InvokeGet" с "1" аргументами: "Неизвестное имя. (Исключение из HRESULT: 0x80020006 (DISP_E_UNKNO
WNNAME))"
C:\1.ps1:9 знак:41
+ if ($user.$prop -ne $objuser.InvokeGet <<<< ($prop))
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException

Исключение при вызове "InvokeGet" с "1" аргументами: "Неизвестное имя. (Исключение из HRESULT: 0x80020006 (DISP_E_UNKNO
WNNAME))"
C:\1.ps1:9 знак:41
+ if ($user.$prop -ne $objuser.InvokeGet <<<< ($prop))
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException

Исключение при вызове "InvokeGet" с "1" аргументами: "Неизвестное имя. (Исключение из HRESULT: 0x80020006 (DISP_E_UNKNO
WNNAME))"
C:\1.ps1:9 знак:41
+ if ($user.$prop -ne $objuser.InvokeGet <<<< ($prop))
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException

Исключение при вызове "InvokeGet" с "1" аргументами: "Неизвестное имя. (Исключение из HRESULT: 0x80020006 (DISP_E_UNKNO
WNNAME))"
C:\1.ps1:9 знак:41
+ if ($user.$prop -ne $objuser.InvokeGet <<<< ($prop))
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException


Осталось провести более масштабную проверку (до этого проверял на 4-7 пользователях на тестовой машине). Завтра попробую развернуть на большую - посмотрим, что получится.

Kazun 04-07-2012 20:39 1945961

Имена свойств в CSV файле должны быть,такими же,как и аттрибуты в AD(Email должен быть mail). Ограничения на количество пользователей нет в худшем случае упрется в производительность.При возникновении ошибки у конкретного пользователя,скрипт не прерывает своей работы.Можно добавить проверку на пустое свойство в CSV:

Код:

$user.$prop -ne $objuser.InvokeGet($prop)) -and $user.$prop

rox33 05-07-2012 12:30 1946294

были ошибки:
читать дальше »
Поменял, всё равно:
читать дальше »
C:\>.\mod.ps1
Исключение при вызове "SetInfo" с "0" аргументами: "Для службы каталогов указан недопустимый синтаксис атрибута.
"
C:\mod.ps1:14 знак:17
+ $objuser.SetInfo <<<< ()
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : CatchFromBaseAdapterMethodInvokeTI

Исключение при вызове "SetInfo" с "0" аргументами: "Для службы каталогов указан недопустимый синтаксис атрибута.
"
C:\mod.ps1:14 знак:17
+ $objuser.SetInfo <<<< ()
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : CatchFromBaseAdapterMethodInvokeTI

Нельзя вызвать метод для выражения со значением NULL.
C:\mod.ps1:6 знак:78
+ $objuser = ([adsisearcher]"(mail=$($user.mail))").FindOne().GetDirectoryEntry <<<< ()
+ CategoryInfo : InvalidOperation: (GetDirectoryEntry:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull

Исключение при вызове "SetInfo" с "0" аргументами: "Служба каталогов не может выполнить операцию на RDN-атрибуте объект
а.
"
C:\mod.ps1:14 знак:17
+ $objuser.SetInfo <<<< ()
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : CatchFromBaseAdapterMethodInvokeTI

Исключение при вызове "SetInfo" с "0" аргументами: "Для службы каталогов указан недопустимый синтаксис атрибута.
"
C:\mod.ps1:14 знак:17
+ $objuser.SetInfo <<<< ()
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : CatchFromBaseAdapterMethodInvokeTI

Исключение при вызове "SetInfo" с "0" аргументами: "Для службы каталогов указан недопустимый синтаксис атрибута.
"
C:\mod.ps1:14 знак:17
+ $objuser.SetInfo <<<< ()
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : CatchFromBaseAdapterMethodInvokeTI

Исключение при вызове "SetInfo" с "0" аргументами: "Для службы каталогов указан недопустимый синтаксис атрибута.
"
C:\mod.ps1:14 знак:17
+ $objuser.SetInfo <<<< ()
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : CatchFromBaseAdapterMethodInvokeTI

Исключение при вызове "SetInfo" с "0" аргументами: "Для службы каталогов указан недопустимый синтаксис атрибута.
"
C:\mod.ps1:14 знак:17
+ $objuser.SetInfo <<<< ()
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : CatchFromBaseAdapterMethodInvokeTI

Исключение при вызове "SetInfo" с "0" аргументами: "Служба каталогов не может выполнить операцию на RDN-атрибуте объект
а.
"
C:\mod.ps1:14 знак:17
+ $objuser.SetInfo <<<< ()
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : CatchFromBaseAdapterMethodInvokeTI

Исключение при вызове "SetInfo" с "0" аргументами: "Служба каталогов не может выполнить операцию на RDN-атрибуте объект
а.
"
C:\mod.ps1:14 знак:17
+ $objuser.SetInfo <<<< ()
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : CatchFromBaseAdapterMethodInvokeTI

Исключение при вызове "SetInfo" с "0" аргументами: "Служба каталогов не может выполнить операцию на RDN-атрибуте объект
а.
"
C:\mod.ps1:14 знак:17
+ $objuser.SetInfo <<<< ()
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : CatchFromBaseAdapterMethodInvokeTI

Исключение при вызове "SetInfo" с "0" аргументами: "Для службы каталогов указан недопустимый синтаксис атрибута.
"
C:\mod.ps1:14 знак:17
+ $objuser.SetInfo <<<< ()
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : CatchFromBaseAdapterMethodInvokeTI

Исключение при вызове "SetInfo" с "0" аргументами: "Для службы каталогов указан недопустимый синтаксис атрибута.
"
C:\mod.ps1:14 знак:17
+ $objuser.SetInfo <<<< ()
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : CatchFromBaseAdapterMethodInvokeTI

Исключение при вызове "SetInfo" с "0" аргументами: "Служба каталогов не может выполнить операцию на RDN-атрибуте объект
а.
"
C:\mod.ps1:14 знак:17
+ $objuser.SetInfo <<<< ()
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : CatchFromBaseAdapterMethodInvokeTI

Исключение при вызове "SetInfo" с "0" аргументами: "Служба каталогов не может выполнить операцию на RDN-атрибуте объект
а.
"
C:\mod.ps1:14 знак:17
+ $objuser.SetInfo <<<< ()
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : CatchFromBaseAdapterMethodInvokeTI

Исключение при вызове "SetInfo" с "0" аргументами: "Служба каталогов не может выполнить операцию на RDN-атрибуте объект
а.
"
C:\mod.ps1:14 знак:17
+ $objuser.SetInfo <<<< ()
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : CatchFromBaseAdapterMethodInvokeTI

Исключение при вызове "SetInfo" с "0" аргументами: "Служба каталогов не может выполнить операцию на RDN-атрибуте объект
а.
"
C:\mod.ps1:14 знак:17
+ $objuser.SetInfo <<<< ()
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : CatchFromBaseAdapterMethodInvokeTI

Исключение при вызове "SetInfo" с "0" аргументами: "Для службы каталогов указан недопустимый синтаксис атрибута.
"
C:\mod.ps1:14 знак:17
+ $objuser.SetInfo <<<< ()
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : CatchFromBaseAdapterMethodInvokeTI

Исключение при вызове "SetInfo" с "0" аргументами: "Для службы каталогов указан недопустимый синтаксис атрибута.
"
C:\mod.ps1:14 знак:17
+ $objuser.SetInfo <<<< ()
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : CatchFromBaseAdapterMethodInvokeTI

Исключение при вызове "SetInfo" с "0" аргументами: "Служба каталогов не может выполнить операцию на RDN-атрибуте объект
а.
"
C:\mod.ps1:14 знак:17
+ $objuser.SetInfo <<<< ()
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : CatchFromBaseAdapterMethodInvokeTI

Исключение при вызове "SetInfo" с "0" аргументами: "Служба каталогов не может выполнить операцию на RDN-атрибуте объект
а.
"
C:\mod.ps1:14 знак:17
+ $objuser.SetInfo <<<< ()
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : CatchFromBaseAdapterMethodInvokeTI

Исключение при вызове "SetInfo" с "0" аргументами: "Служба каталогов не может выполнить операцию на RDN-атрибуте объект
а.
"
C:\mod.ps1:14 знак:17
+ $objuser.SetInfo <<<< ()
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : CatchFromBaseAdapterMethodInvokeTI

Исключение при вызове "SetInfo" с "0" аргументами: "Для службы каталогов указан недопустимый синтаксис атрибута.
"
C:\mod.ps1:14 знак:17
+ $objuser.SetInfo <<<< ()
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : CatchFromBaseAdapterMethodInvokeTI

Исключение при вызове "SetInfo" с "0" аргументами: "Для службы каталогов указан недопустимый синтаксис атрибута.
"
C:\mod.ps1:14 знак:17
+ $objuser.SetInfo <<<< ()
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : CatchFromBaseAdapterMethodInvokeTI

Исключение при вызове "SetInfo" с "0" аргументами: "Служба каталогов не может выполнить операцию на RDN-атрибуте объект
а.
"
C:\mod.ps1:14 знак:17
+ $objuser.SetInfo <<<< ()
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : CatchFromBaseAdapterMethodInvokeTI

Исключение при вызове "SetInfo" с "0" аргументами: "Служба каталогов не может выполнить операцию на RDN-атрибуте объект
а.
"
C:\mod.ps1:14 знак:17
+ $objuser.SetInfo <<<< ()
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : CatchFromBaseAdapterMethodInvokeTI

CSV несколько модифицировал теперь оно вида:
читать дальше »
name;DisplayName;mail;TelephoneNumber;mobile;homephone;userprincipalname;sn;Givenname
Иванов Иван;Иванов Иван;ivan.ivanov@test.ru;495-999-66-55;8-926-999-99-99;999;ivan.ivanov;Иванов;Иван


С ним скрипт не отрабатывает.

Если убрать поля name, sm, userprincipalname,givenname - скрипт выдаёт ошибки (из-за пустых полей), но отрабатывает.


Разобался - были поля Name и sn, которые по сути - одно и тоже. Убрал Name - всё заработало.

Такой вопрос ещё, возможно ли добавить к скрипту логирование? Что перезаписал скрипт, что нет. Со временем, если можно.

Kazun 06-07-2012 00:10 1946819

Код:

foreach ($user in $users)
{
        $objuser = ([adsisearcher]"(mail=$($user.mail))").FindOne().GetDirectoryEntry()
        $props | Foreach {
                $prop = $_.ToLower()
                $log = New-Object Text.StringBuilder
                $oldprop = $objuser.InvokeGet($prop)
                if ($user.$prop -ne $oldprop)
                {
                        $objuser.Put("$prop",$user.$prop)
                        $text = "{0} : old {1} new {2} - {3}" -f $objuser.name[0],$oldprop,$user.$prop,(Get-Date)
                        $log.AppendLine($text) | Out-Null
                }
        }
        try {
                $objuser.SetInfo()
                $log.ToString() | Out-File result.txt -Append
        }
        catch {
                $_
        }
}


rox33 11-07-2012 16:50 1950045

Спасибо, проблема только в том, что result.txt пустой.
Хотя в АД точно данные менялись из csv.

Вот с такой ошибкой выбивает:
читать дальше »
Цитата:

Нельзя вызвать метод для выражения со значением NULL.
C:\modlog.ps1:6 знак:79
+ $objuser = ([adsisearcher]"(mail=$($user.mail))").FindOne().GetDirectoryEntry <<<< ()
+ CategoryInfo : InvalidOperation: (GetDirectoryEntry:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull

Нельзя вызвать метод для выражения со значением NULL.
C:\modlog.ps1:10 знак:32
+ $oldprop = $objuser.InvokeGet <<<< ($prop)
+ CategoryInfo : InvalidOperation: (InvokeGet:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull

Нельзя вызвать метод для выражения со значением NULL.
C:\modlog.ps1:13 знак:16
+ $objuser.Put <<<< ("$prop",$user.$prop)
+ CategoryInfo : InvalidOperation: (Put:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull

Не удается индексировать в массив NULL.
C:\modlog.ps1:14 знак:59
+ $text = "{0} : old {1} new {2} - {3}" -f $objuser.name[ <<<< 0],$oldprop,$user.$prop,(Get-Date)
+ CategoryInfo : InvalidOperation: (0:Int32) [], RuntimeException
+ FullyQualifiedErrorId : NullArray

Нельзя вызвать метод для выражения со значением NULL.
C:\modlog.ps1:10 знак:32
+ $oldprop = $objuser.InvokeGet <<<< ($prop)
+ CategoryInfo : InvalidOperation: (InvokeGet:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull

Нельзя вызвать метод для выражения со значением NULL.
C:\modlog.ps1:13 знак:16
+ $objuser.Put <<<< ("$prop",$user.$prop)
+ CategoryInfo : InvalidOperation: (Put:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull

Не удается индексировать в массив NULL.
C:\modlog.ps1:14 знак:59
+ $text = "{0} : old {1} new {2} - {3}" -f $objuser.name[ <<<< 0],$oldprop,$user.$prop,(Get-Date)
+ CategoryInfo : InvalidOperation: (0:Int32) [], RuntimeException
+ FullyQualifiedErrorId : NullArray

Нельзя вызвать метод для выражения со значением NULL.
C:\modlog.ps1:10 знак:32
+ $oldprop = $objuser.InvokeGet <<<< ($prop)
+ CategoryInfo : InvalidOperation: (InvokeGet:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull

Нельзя вызвать метод для выражения со значением NULL.
C:\modlog.ps1:13 знак:16
+ $objuser.Put <<<< ("$prop",$user.$prop)
+ CategoryInfo : InvalidOperation: (Put:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull

Не удается индексировать в массив NULL.
C:\modlog.ps1:14 знак:59
+ $text = "{0} : old {1} new {2} - {3}" -f $objuser.name[ <<<< 0],$oldprop,$user.$prop,(Get-Date)
+ CategoryInfo : InvalidOperation: (0:Int32) [], RuntimeException
+ FullyQualifiedErrorId : NullArray

Нельзя вызвать метод для выражения со значением NULL.
C:\modlog.ps1:10 знак:32
+ $oldprop = $objuser.InvokeGet <<<< ($prop)
+ CategoryInfo : InvalidOperation: (InvokeGet:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull

Нельзя вызвать метод для выражения со значением NULL.
C:\modlog.ps1:13 знак:16
+ $objuser.Put <<<< ("$prop",$user.$prop)
+ CategoryInfo : InvalidOperation: (Put:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull

Не удается индексировать в массив NULL.
C:\modlog.ps1:14 знак:59
+ $text = "{0} : old {1} new {2} - {3}" -f $objuser.name[ <<<< 0],$oldprop,$user.$prop,(Get-Date)
+ CategoryInfo : InvalidOperation: (0:Int32) [], RuntimeException
+ FullyQualifiedErrorId : NullArray

Нельзя вызвать метод для выражения со значением NULL.
C:\modlog.ps1:10 знак:32
+ $oldprop = $objuser.InvokeGet <<<< ($prop)
+ CategoryInfo : InvalidOperation: (InvokeGet:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull

Нельзя вызвать метод для выражения со значением NULL.
C:\modlog.ps1:13 знак:16
+ $objuser.Put <<<< ("$prop",$user.$prop)
+ CategoryInfo : InvalidOperation: (Put:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull

rox33 19-07-2012 13:35 1954806

Таки всё равно 2 вопроса:
1. При наличии пустых строк в csv файле (например, у пользователя нет мобильного телефона и в csv получается что-то вроде test.test@test.ru;;;company;1) - скрипт выдаёт миллион ошибок и запарывается на первой же пропущенной строке.
2. Логирование работает, но перестаёт, как только видит пустые строки (опять!;) ), и если по какому-то пользователю он ничего не менял он оставляет знак начала новой строки, т.е. резалт.тхт выглядит так:




Test: old %% new ** - 19.07.2012 13:34:00






User: old ** new && - 19.07.2012 13:34:01


Как же всё-таки избавится от этой проблемы?

Kazun 19-07-2012 14:12 1954818

1. Конкретно в каких строках?
2. Добавить проверку if ($log.ToString()) - имеет не пустое значение.

"скрипт выдаёт миллион ошибок и запарывается на первой же пропущенной строке. " - откуда же миллион ошибок,раз все по вашим словам стопорится на первой строке? =)))

rox33 19-07-2012 15:04 1954847

2 Kazun:
Ошибки выдаёт и в саму АД ничего не пишет. Т.е. отрабатывает с ошибками, АД при этом не меняя.

rox33 19-07-2012 16:19 1954886

Да, и ещё - по какой-то причине, при попытке изменить из большого csv файла (порядка 150 строк) он частенько меняет e-mail у сотрудников.
Видимо где-то он видит знак конца строки и вписывает данные, следующего в списке сотрудника, предыдущему сотруднику.
Получается ПОЛНЫЙ бардак.
Судя по всему происходит это когда он находит в списке сотрудника, которого НЕТ в AD. Можно ли это исправить?

Kazun 19-07-2012 16:55 1954923

Изменить немного на:
Код:

Try {
                $objuser = ([adsisearcher]"(mail=$($user.mail))").FindOne().GetDirectoryEntry()
        }
        catch {
                continue
        }

Еще раз в какой строке ошибка?

rox33 19-07-2012 18:12 1954962

Заработало, спасибо огромное!
И на последок 2 вопроса:
1. как ошибки вставить в файл result.txt (или error.txt, не обязательно в 1 файл вести запись всех событий работы скрипта, можно в 2)
2. как более красиво писать лог, без пропуска строк? (если сложно - не надо).

Спасибо ещё раз огромное!

Kazun 19-07-2012 18:30 1954967

1. В блок catch вставьте нужное логирование
2. Сделать проверку if ($log.ToString()) - что значения является не пустым и заменить AppendLine на Append

rox33 20-07-2012 12:19 1955364

Всё сработало, но опять вопрос =(
Как наладить работу скрипта в случае, если в csv файле есть пустые ячейки, например:
mail;company;title;phone;mobile;displayname
test@test.ru;test;tester;;;tester


При наличии пропусков (нет телефона, должность не указана, отдела (в моём ксв несколько больше полей, чем я тут привёл) - ксв не отрабатывает (в АД замену значений не производит).

Нашел ваш совет, вставить в код:
$user.$prop -ne $objuser.InvokeGet($prop)) -and $user.$prop
Для проверки на пустое свойство в CSV.

Я туповат и не понимаю куда в код с логом это вставить =(

в строку $oldprop = $objuser.InvokeGet($prop)

Так: $oldprop = ($objuser.InvokeGet($prop) - and $user.$prop) ?


И ещё result.txt записывает изменения только если менялась должность. Телефоны, компанию - не записывает. В чём может быть дело?

Kazun 20-07-2012 12:47 1955390

Приведите результат скрипта с тестовым пользователем.

rox33 20-07-2012 13:00 1955402

Код:

Исключеие при вызове "SetInfo" с "0" аргументами: "Для службы каталогов указан недопустимый синтаксис атрибута."
C:\modlog.ps1:28 знак:29
+ $objuser.SetInfo <<<< ()
+CategoryInfo : NotSpecified: (:) [],MethodInvocationException
+FullyQualifiedErrorId:CatchFromBaseAdapterMethodInvokeTI

Скрипт:
читать дальше »
Код:

$users = Import-Csv c:\list10.csv -Delimiter ";"
$props = $users | Get-Member -MemberType NoteProperty | Select -Expand name

foreach ($user in $users)
{
Try{
      $objuser = ([adsisearcher]"(mail=$($user.mail))").FindOne().GetDirectoryEntry()
}
Catch {
continue
}
      $props | Foreach {
            $prop = $_.ToLower()
            $log = New-Object Text.StringBuilder
            $oldprop = $objuser.InvokeGet($prop)
            if ($user.$prop -ne $oldprop)
            {
                  $objuser.Put("$prop",$user.$prop)
                  $text = "{0} : old {1} new {2} - {3}" -f $objuser.displayname[0],$oldprop,$user.$prop,(Get-Date)
                  $log.AppendLine($text) | Out-Null
            }
      }
      try {
            $objuser.SetInfo()
            $log.ToString() | Out-File c:\result.txt -Append
      }
      catch {
            $_
      }
}



csv:
читать дальше »

mail;company;title;physicalDeliveryOfficeName;homephone;Telephonenumber;ipphone;mobile
test@test.ru;test;tester;;133;89999999;;112399

Kazun 20-07-2012 13:29 1955433

Код:

$users = Import-Csv c:\list10.csv -Delimiter ";"
$props = $users | Get-Member -MemberType NoteProperty | Select -Expand name

foreach ($user in $users)
{
        Try{
              $objuser = ([adsisearcher]"(mail=$($user.mail))").FindOne().GetDirectoryEntry()
        }
       
        Catch {
                continue
        }
   
        $log = New-Object Text.StringBuilder
       
        $props | Foreach {
            $prop = $_.ToLower()
            $oldprop = $objuser.InvokeGet($prop)
            if ($user.$prop -ne $oldprop -and $user.$prop)
            {
                $objuser.Put("$prop",$user.$prop)
                $text = "{0} : old {1} new {2} prop {3} - {4}" -f $objuser.name[0],$oldprop,$user.$prop,$prop,(Get-Date)
                $log.AppendLine($text) | Out-Null
            }
      }
   
        Try {
      $objuser.SetInfo()
          if($log.ToString())
          {
                          $log.ToString() | Out-File C:\result.txt -Append
          }
    }
    Catch {
        $_
    }
}


rox33 20-07-2012 15:45 1955539

Всё, теперь код, под мои условия, - ИДЕАЛЕН!!!
ОГРОМНОЕ СПАСИБО!


Время: 02:31.

Время: 02:31.
© OSzone.net 2001-