Pull to refresh

Comments 34

Добавьте разметку кода. У меня глаза чуть не потекли. :(
А всё потому, что кто-то не читает Get-Help на команды!
Честно говоря, не вяжется «неплохо разбираюсь в powershell» с откровениями про пайп (|). Объектный пайп — самое крутое, что есть в Powershell. И вот это
на выход мы получаем не значение true, а целый набор данных
— ожидаемое поведение для любого Get-Wtf. С ними прикольно другое, если объектов (пользователей) 2 и более, то командлет возвращает массив объектов. А если объект один, то возвращает сам объект (а не массив из одного объекта), ломая к чёртовой бабушке всю последующую логику. Рождаются костыли:
$shrimps = @()
$shrimps += Get-Shrimps
и дальше смело работаем как с массивом.

Можно проще: $shrimps = @(Get-Shrimps)


Или вот так:


Get-Shrimps |% {
    $shrimp = $_

    # ...
}
Честно говоря, не вяжется «неплохо разбираюсь в powershell» с откровениями про пайп (|)
Я знал, что такое конвейер до написания этой статьи. Хотел максимально подробно разъяснить все детали, для тех пользователей, кто недавно начал работать с powershell. Но не учёл высокий уровень читателей Хабра и сейчас откровенно жалею за потраченное мной время на написание статьи.
С ними прикольно другое, если объектов (пользователей) 2
В моих примерах везде явно задан конкретный пользовать. Поэтому возвращать будет либо информацию о конкретном пользователе, либо ошибку если пользователя в системе отсутсвует.
Массив данных можно получить только с помощью команды из дополнения Get-LocalUser | Where-Object {$_.enabled -eq $false}

В любом случае, спасибо за уточнение.
По умолчанию ваш скрипт будет работать только на windows server 2016 и windows 10 версии выше 1607, так как модуль Microsoft.PowerShell.LocalAccounts в котором содержится командлет Get-Localuser есть только на этих системах. Наверное для решения задачи лучше было попробовать использовать wmi.
Спасибо за уточнение. Я действительно забыл уточнить что писал на powershell 5.1
выполнил Get-Localuser в Win7
все получилось
Значит у вас установлен powershell 5.1 либо модуль Microsoft.PowerShell.LocalAccounts.
Проверьте версию powershell на своей системе.
$psversiontable.psversion


Возможно на системе powershell обновлен.
как можно средствами powershell создать почтовые ящики пользователям на exchange 2003
насколько я знаю, Exchange начал поддерживать powershell с версии 2010.
Например, вот так:
Function CreateNewUserMailbox($objUser, $MakeHidden, $mdb) {
	$CreateNewUserMailbox = $False
	$objUser.CreateMailbox($mdb)
	$objUser.Put("msExchUserAccountControl", 0)
	$objUser.SetInfo()
	if ($MakeHidden) {
		$objUser.Put("msExchHideFromAddressLists", $MakeHidden)
		$objUser.SetInfo()
	}
}
$userDN = (get-qaduser $userLogin).directoryentry.distinguishedname
$user = [adsi]"LDAP://$userDN"
$mdbName = "CN=Store1,CN=SG1,CN=InformationStore,CN=EXCH-01,CN=Servers,CN=Org,CN=Administrative Groups,CN=Org,CN=Microsoft Exchange,CN=Services,CN=Configuration,DC=example,DC=com"}
CreateNewUserMailbox $user $false $mdbName

Пусть не смущает командлет Get-QADUser — в те времена я использовал PowerGUI.
<Зануда on>
Зачем проверять значение «срок действия пароля не ограничен», если его всё равно нужно устанавливать? Этим мы сократим код скрипта и время выполнения. :)
То же самое и с группой, а ошибку вторичного добавления юзера в группу можно просто игнорировать.
Если в АД будет необходимость проверить у кого из пользователей стоит смена пароля, а у кого нет, без принудительного изменения этого параметра, мой пример будет полезен.
Не стоит воспринимать готовый скрипт как универсальный и на все случаи жизни. Моя цель была показать несколько примеров, которые можно будет в будущем использовать под свои конкретные задачи.
странные у вас «просторы интернета», наличие/отсуствие объекта элементарно проверяется в if:
if (Get-LocalUser 'admin' -ErrorAction SilentlyContinue) { Write-Host 'Есть пользователь'} else {Write-Host 'Нет пользователя' }
Все таки правильнее обрабатывать ошибки а не скрывать их. В вашем случае скрипт будет выдавать «нет пользователя» если произойдет любая ошибка в Get-LocalUser и он ничего не вернет. Использование try{}catch{}, более оправдано… Правильнее было бы
$user="admin"
try 
{
    Get-LocalUser $user -ErrorAction Stop
    write-host пользователь $user есть -foregroundcolor Green
}
Catch 
{
    if ($_.FullyQualifiedErrorId -eq "UserNotFound,Microsoft.PowerShell.Commands.GetLocalUserCommand")
    {
        write-host "Пользователь $User не найден" -foregroundcolor Red
    }
    else
    {
        Write-Error $_
    }
    
}

Тогда уж проще if (Get-LocalUser |? {$_.Name -eq $user}) написать.

Нуу… нет, все можно было сделать намного проще и понятнее. Вместо try/catch вполне удобно использовать параметр -ErrorAction. А «хэш» пароля не будет корректно декодироваться под другой учетной записью (другом пк). Чтобы он «работал» везде, нужно использовать параметр key. Самый простой вариант, это запросить прямо из консоли новый пароль. И по итогу весь скрипт будет выглядеть примерно так:
$userName = "Admin"

if (-not (Get-LocalUser $userName -ErrorAction SilentlyContinue))
{
    #Если У/З отсутствует, то будет создана
    $pass = Read-Host "Inpur new password for $userName" -AsSecureString
    New-LocalUser -Name $userName -Password $pass -UserMayNotChangePassword -PasswordNeverExpires
}

#Раз У/З есть (а если не было, то уже есть), то можем создать объект аккаунта, с ним удобнее
$Account = Get-LocalUser $userName

#Включаем аккаунт, если отключен
if (-not $Account.Enabled) { Enable-LocalUser $Account }

#Если аккаунт не входит в группу администраторов, то добавим
if (-not (Get-LocalGroupMember -Member $Account -SID S-1-5-32-544 -ErrorAction SilentlyContinue ))
{
    Add-LocalGroupMember -SID S-1-5-32-544 -Member $Account
}

#Задаем параметры «Запретить смену пароля пользователем» и «Срок действия пароля не ограничен»
Set-LocalUser $Account -PasswordNeverExpires $true -UserMayChangePassword $false 
Кажется Вы только что объяснили почему топикстартера не взяли на работу…
Запретить смену пароля текущим членам группы администраторов невозможно — ругается.
Пришлось сначала удалять, прописывать это свойство, а потом заново добавлять. Сделал вообще без проверок и с глобальным игнором ошибок.

$ErrorActionPreference = 'SilentlyContinue'
$username = "Admin"
$AdminGroup = "S-1-5-32-544"
$getuser = Get-LocalUser $username
if ($getuser -eq $null)
    {
    $Password = Read-Host -AsSecureString
    New-LocalUser -Name $username `
    -PasswordNeverExpires `
    -UserMayNotChangePassword  `
    -Password $Password
    Add-LocalGroupMember -SID $AdminGroup -Member $username
    }
else
    {
    Remove-LocalGroupMember -Member $username -SID $AdminGroup
    Set-LocalUser -Name $username `
    -PasswordNeverExpires $true `
    -UserMayChangePassword $false `
    -Password $Password
    Add-LocalGroupMember -SID $AdminGroup -Member $username
    Enable-LocalUser $username
    }
консоль под админом запускаете?
только что перепроверил
set-LocalUser admin -PasswordNeverExpires:$true

галочка по сроку действую пароля устанавливается.
С этим проблем нет, проблемы есть со свойством смены пароля, а не его сроком действия.
попробуйте
Set-LocalUser -Name admin -UserMayChangePassword $false
Да, действительно ругается, на одного администратора в системе.
Попробуйте через конвейер это сделать.
$password = convertto-securestring "P@ssW0rD!" -asplaintext -force
Set-LocalUser -Name admin -Password $Password | Set-LocalUser -UserMayChangePassword $false
А что собственно вы пытаетесь передать по этому пайпу?
PS, не выйдет никак. Даже через GUI он ругается на ограничения. Возможно этот нюанс тоже повлиял на оценку тестового задания.
может сначала ответите, у вас сработало или нет?
Я специально для вас проверил заведомо не рабочее решение и нет, оно не сработало.
да, действительно. даже через консоль этот параметр не изменить, если в системе остался только один администратор.
не работает с любым количеством
Sign up to leave a comment.

Articles