Заметки о Windows и других программных продуктах Microsoft...

Управляем локальными пользователями с помощью PowerShell

Управляем локальными пользователями с помощью PowerShell

Для работы с доменными пользователями в PowerShell уже давно существует множество командлетов, но если вам потребуется управлять локальными пользователями, то здесь основным инструментом по прежнему остается графическая оснастка (lusrmgr.msc) и старая добрая утилита командной строки net.  Тем не менее, в PowerShell все же есть возможность для управления локальными пользователями на компьютерах, не входящих в домен.

Для этого можно воспользоваться интерфейсом ADSI (Active Directory Services Interface), который может применяться как для работы с Active Directory, так и с отдельно стоящими компьютерами.

Рассмотрим несколько наиболее актуальных ситуаций при работе с локальными пользователями

Создание пользователя

Первое, что необходимо сделать с пользователем — это создать его учетную запись. Для этого сначала получаем объект компьютера и помещаем его в переменную:

[adsi]$computer = ″WinNT://SRV1″

Затем с помощью метода Create создаем пользователя с именем LocalAdmin:

$user = $computer.Create(″User″, ″LocalAdmin″)

Устанавливаем флажок для того, чтобы пользователь сменил пароль при входе:

$user.Put(″PasswordExpired″, 1)

Задаем начальный пароль:

$user.SetPassword(″P@$$word″)

И добавляем описание в поле «Description»:

$user.Put(″Description″, ″Local administrator″)

Чтобы все сделанные изменения были применены, необходимо выполнить команду:

$user.SetInfo()

Для проверки можно вывести список пользователей командой:

$computer.Children | where {$_.Class -eq ″user″} | ft name, description -auto

создание нового пользователя

 

Ну или посмотреть в графической оснастке.

новый пользователь в GUI

 

А теперь представим, что требуется установить флаги «User cannot change password» и\или «Password never expired». Эти настройки хранятся в свойстве пользователя UserFlags, которое представляет из себя битовую маску. Для вычисления необходимого значения используется операция -bor (побитовое ИЛИ), например так мы установим флаг «Password never expired»:

$flag = $user.UserFlags.Value -bor 0x10000
$user.Put(″userflags″,$flag)
$user.SetInfo()

Примечание. Значения, необходимые для установки различных флагов, можно посмотреть на странице http://msdn.microsoft.com/en-us/library/aa772300(VS.85).aspx

Надо иметь в виду, что при установке одного флага остальные сбрасываются. К примеру, если установить флаг «User cannot change password» (значение 0x40), то флаг «Password never expired» будет снят. Для того, чтобы поставить оба флага, необходимо суммировать их значения, например так:

$flag = $user.UserFlags.Value -bor 0x10040
$user.Put(″userflags″,$flag)
$user.SetInfo()

установка флагов пользователя

 

Также необходимо помнить, что флаги «User cannot change password» и «Password never expired» несовместимы с «User must change password at next logon», поэтому при установке любого из них он снимается. Это очень наглядно видно в графической оснастке.

результат установки флагов в GUI

 

И еще одна операция, которая обычно производится при создании пользователя — добавление его в группу. Для примера добавим нашего пользователя в группу локальных администраторов:

[adsi]$group = ″WinNT://SRV1/Administrators, group″
$group.Add($user.Path)

Проверить содержимое группы можно такой несложной 🙂 командой:

$members = @($group.psbase.Invoke(″Members″))
$members | foreach {$_.GetType().InvokeMember(″Name″,″GetProperty″, $null, $_, $null)}

добавление пользователя в группу

Редактирование свойств пользователя

Довольно часто встречается ситуация, когда пользователь уже имеется и его надо отредактировать — сменить пароль, добавить в группу и т.п. Первым делом помещаем объект компьютера в переменную и смотрим список локальных пользователей:

[adsi]$computer = ″WinNT://SRV1″
$computer.Children | where {$_.Class -eq ″user″} | ft name, description -auto

вывод списка локальных пользователей

 

Предположим, требуется сбросить\сменить пароль для пользователя LocalAdmin. Помещаем его в переменную:

[adsi]$user = ″WinNT://SRV1/LocalAdmin,user″

Устанавливаем новый пароль:

$user.SetPassword(″newP@$$w0rd″)

Задаем смену пароля при следующем входе:

$user.Put(″PasswordExpired″,1)

и сохраняем изменения:

$user.SetInfo()

сброс пароля пользователя

 

А теперь передвинем его из группы локальных администраторов (Administrators) в группу пользователей удаленного рабочего стола (Remote Desctop Users). Для этого помещаем обе группы в переменные:

[adsi]$admins = ″WinNT://SRV1/Administrators,group″
[adsi]$rdpusers = ″WinNT://SRV1/Remote Desktop Users,group″

Затем, используя метод Remove, удаляем пользователя из одной группы:

$admins.Remove($user.Path)

и добавляем в другую с помощью метода Add:

$rdpusers.Add($user.Path)

перемещение пользователя в другую группу

Отключение\удаление пользователя

Ну и конечно может потребоваться отключить или удалить учетную запись пользователя. За отключение отвечает флаг «Account is disabled», который также хранится в UserFlags. Сначала помещаем в переменную значение, соответствующее отключенной записи:

$disabled = 0x0002

Затем с помощью операции -band (побитовое И) проверяем, включена ли учетная запись. Результат выводим в логическом (boolean) виде:

($user.UserFlags.Value -band $disabled) -as [bool]

Если команда вернула False, значит учетная запись активна. Задаем новое значение флага:

$flag = $user.UserFlags.Value -bor $disabled

И изменяем текущее значение:

$user.Put(″userflags″, $flag)
$user.SetInfo()

Обновляем кэш и еще раз проверяем, включена ли учетная запись:

$user.RefreshCache()
($user.UserFlags.Value -band $disabled) -as [bool]

Теперь команда возвращает True, что означает успешное выключение. Ну а для обратного включения требуются ровно те-же действия, только вместо операции -bor (включающее ИЛИ) используется операция -bxor (исключающее ИЛИ):

$disabled = 0x0002
$flag = $user.UserFlags.Value -bxor $disabled
$user.Put(″userflags″, $flag)
$user.SetInfo()

выключение учетной записи пользователя

 

Ну и для окончательного удаления пользователя воспользуемся методом Delete:

[adsi]$computer = ″WinNT://SRV1″
$computer.Delete(″user″,$user.Name.Value)

И проверим результат командой:
$computer.Children | where {$_.Class -eq ″user″} | ft name, description -auto

удаление учетной записи пользователя

 

На этом у меня все о PowerShell и локальных пользователях. Если это вам покажется недостаточным, то более подробно свойства и методы локальных пользователей описаны на MSDN.

 
 
Комментарии

Спасибо! Отличное руководство, полезное!
Но я бы посоветовал пользоваться переменными:
вместо [adsi]$computer = ″WinNT://SRV1″ использовать [adsi]$computer = ″WinNT://$env:COMPUTERNAME″.

Также в статье замечена ошибка в переменных:
[adsi]$admins = ″WinNT://SRV1/Administrators,group″
!!![adsi]$admins = ″WinNT://SRV1/Remote Desktop Users,group″

а далее
$admins.Remove($user.Path)
$rdpusers.Add($user.Path)

Про переменные — согласен, скрипт будет более универсален. Просто в примере всего один сервер, поэтому переменные не потребовались.
Ошибку исправил, спасибо.

Михаил

$computer.Delete(″user»,$user.Name.Value) Ошибка «user>> наверное надо было все же «user»

Постоянная проблема с кавычками 🙁

Михаил

Я в системном администрировании плохо разбираюсь. Помогите разобраться.
У меня есть VPS сервер на Windows, домена на нем нет и не нужно.
Задача: создание большого количества локальных учетных записей с правами администратора, с последующим периодическим удалением. Ну то есть создал учетки и спустя допустим 10 дней удалил.
Сейчас я работаю так: захожу на сервер и создаю учетки в ручную через lusrmgr.msc. Хотелось бы автоматизировать этот процесс. Готов заплатить!

Михаил

Кто готов помочь пишите, пожалуйста на почту m.kamenev89@yandex.ru

Джонни

Шикарная статься! Лишь один момент — имена групп в русских версиях Windows Server поименованы на русском (как это ни внезапно).
В виду этого код следует писать так:
$ComputerName = «WinNT://» + $Env:COMPUTERNAME
$GroupName = $ComputerName + «Пользователи удаленного рабочего стола,group»

Подскажите плиз как написать скрипт который на удаленной машине будет залогиненому пользователю менять политику пароле менять на «Мин длинна пароля 9», «Сложный пароль — вкл» и самое главное чтобы юзер принудительно поменял пароль при следующей загрузке.
Все имена юзеров — разные. Никак неполучается у меня решить эту головоломку…

+ можно пприменить эту новую политику паролей ко всем пользователям и админам в общем. Хотябы так чтобы сработало. Дело ведь еще в том, что требуется исполнять этот скрипт от имени админа, соответственно и применяться все будет только к админу. А не к тому кто залогинен на физической машине.

Политики паролей здесь: Конфигурация компьютера\Конфигурация Windows\Параметры безопасности\Политики учетных записей\Политика паролей
Скрипта для этого не надо, просто открыть оснастку gpedit.msc
Применится ко всем пользователям.

Имя текущего пользователя $env:username, соответственно:
$currentuser = $env:username;
[adsi]$user = ″WinNT://computername/$currentuser,user″

Чтоб от имени админа выполнялось, добавить в шедулер, там указать запуск с повышенными привилегиями.

Еще можно воспользоваться модулем для управления локальными пользователями: https://windowsnotes.ru/powershell-2/modul-powershell-dlya-upravleniya-lokalnymi-polzovatelyami/

Спасибо за ответ!
Да, я знаю и пробовал уже secpol.msc но все что там можно сделать так это поменять длинну пароля и настроить его сложность. Нет ни слова про заставить юзера сменить пароль при след логоне. И когда я кстати попробовал этот скрип усполнить он выполнился на моей машине но при выполнении по сети никаких результатов не повлекло, возможно потому что исполнение скриптов запрещено.
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned
Поможет? Или подтверждение будет опять

К сожалению в модуле для управления локальными пользователями нет ничего про изменение этих «флажков»… (
Состряпал вот такой вот скрипт, но чтото весь экран в ошибках теперь )

$currentuser = $env:username;
[adsi]$user = ″WinNT://computername/$currentuser,user″
$user.SetPassword(″newP@$$w0rd″)
$user.Put(″PasswordExpired″,1)
$user.SetInfo()

https://ibb.co/vm1x3qk

Политику выполнения лучше поставить в Bypass, там подтверждение не требуется. А вообще задача то какая? Что требуется получить в результате?

Есть около 20 компов с уникальными именами пользователей и на которых стоят простые пароли, вот нужно поменять политику паролей и заставить при след. логине сменить пароль
На всех стоит клиент для Ninja, это прога для учета и управления клиентскими компами с возможностью выполнения удаленных скриптов и т.п.

Можно сделать финт ушами, в политике выставить срок действия пароля минимальный, и пользователю придется его менять по любому. И без скриптов.
Хотя локальные политики распространять тоже не очень удобно. Тут напрашивается домен, доменные политики самое то.

Благодарю! Я все вокруг да около этого пункта ходил и немог никак сообразить что им можно воспользоваться.
Чтото только команда:
Set-ExecutionPolicy -ExecutionPolicy bypass

Все равно запрос мне выдает

«выставить срок действия пароля минимальный, » — да, но в этом случае, галочку всеравно нужно будет снимать с «Пароль никогда неистекает» в свойствах определенного юзера. ((

Leave a Reply to Kirill