Создание локального пользователя и мешающее ничто

Недавно ко мне обратились с вопросом о странном поведении достаточно простой функции. Она создаёт локального пользователя с заданным именем и паролем, и должна возвращать в качестве результата объект с двумя свойствами: UserName и Password (Ну на самом деле функция была чуть сложнее, но нам интересна только эта часть🙂 ). Вот её код:

function  CreateUser ($Name, $Password)            
{            
    trap {"Error creating user!"; break} #Перехват ошибок            
 $computer = [ADSI]"WinNT://$env:computername" #Подключаемся к локальному компьютеру по ADSI            
 $user = $computer.Create("user", $Name) #Создаём объект типа user            
 $user.SetPassword($Password) #Устанавливаем пароль            
 $user.SetInfo() #Записываем изменения            
                
 $UP = New-Object PSObject #Создаём пустой объект            
 $UP | Add-Member NoteProperty Username $Name #Добавляем свойства            
 $UP | Add-Member NoteProperty Password $Password #И ещё            
 $UP #Возвращаем объект            
}

Теперь попробуем создать пользователя с помощью этой функции:
PS C:\Windows\system32> $Result = createUser -name Tester -pass P@ssw0rd
PS C:\Windows\system32> $Result
Username Password
-------- --------
Tester P@ssw0rd

PS C:\Windows\system32> $Result.UserName
PS C:\Windows\system32> $Result.Password
PS C:\Windows\system32>

Странно? Если просто вызываем переменную, то видно 2 свойства: UserName, Password, и их значения. Однако при попытке просто получить значения этих свойств мы получаем… ничего. В чём же дело?
PS C:\Windows\system32> $Result.gettype().name
Object[]
PS C:\Windows\system32> $Result.count
3

Квадратные скобки в конце типа объекта, говорят о том что это не просто объект, а массив. Причем как говорит его свойство .Count — из трех элементов. Зная это можно обратиться к свойствам:
PS C:\Windows\system32> $Result[2].Username
Tester
PS C:\Windows\system32> $Result[2].Password
P@ssw0rd

Нужный нам элемент будет лишь третьим по счёту (массивы индексируются с 0). Что касается первых двух элементов:
PS C:\Windows\system32> $Result[0].gettype().name
You cannot call a method on a null-valued expression.
At line:1 char:19
+ $Result[0].gettype <<< $Result[0] -eq $null
True

Их просто не существует, точнее они равны $null, пустоте. А взялись они благодаря вызовам методов ADSI SetPassword() и SetInfo(). Уж не знаю зачем, но видимо авторы данных методов посчитали это прикольным🙂 А в PowerShell есть одна тонкость: все данные которые не присваиваются переменной, не передаются по конвейеру, и не обрабатываются другим способом — отправляются на вывод. То есть функция function test {Get-process powershell; "Test"; del c:\test.txt; return 2+1; 2} вернёт вам массив состоящий из объекта процесса, строки Test и числа 3. Двойка в конце не вернётся лишь потому что return предотвращает дальнейший вывод данных (возвращает не единственный результат, а лишь последний из ряда).
Короче говоря в нашей ситуации $null’ы возвращённые методами, присоеденились к результату возвращаемому функцией, и всё испортили🙂 Чтобы этого не произошло, можно избавиться от этих $null’ов, например… отправив их в Null🙂
$user.SetPassword($Password) | Out-Null
$user.SetInfo() | Out-Null

Опубликовано в Learn, PowerShell, Scripting, Tips. Метки: . 3 комментария »

комментария 3 to “Создание локального пользователя и мешающее ничто”

  1. shs Says:

    Приветы😉

    Извини за offtop, а как ты код PoSh в блог вставляешь?
    я попробовал через sourcecode, про который ты у меня спрашивал, получается ужасно.
    Help me please

  2. Xaegr Says:

    Это скрипт для PS ISE, но PowerGUI делает примерно так-же.

  3. Alexey Says:

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


Обсуждение закрыто.

%d такие блоггеры, как: