Windows 11, 10, etc - Вадим Стеркин
13.8K subscribers
279 photos
5 videos
8 files
1.04K links
Авторский канал. Windows, безопасность, мобильный мир:
• тайное знание
• профессиональный ликбез
• гадание по логам
• срыв покровов
• доставка пруфов

Чат: @winsiders
Блог: outsidethebox.ms
Oбратная связь: @vsterkin
Поддержать ₽: boosty.to/sterkin
Download Telegram
▶️ Управление локальными пользователями и группами вне зависимости от языка ОС

Вчера в чате в ходе дискуссии о нестыковках локализации Windows товарищ Ника привел простой пример со встроенными администраторами - аккаунтом и группой, которые по-разному называются в русской и английской ОС.

Поэтому в русской ОС не сработает, например:
net user Administrator /active:yes
А в английской - кириллический Администратор.

Та же проблема и с добавлением пользователя в группу администраторов.

Я заметил, что несложно будет написать не зависящий от языка ванлайнер #PowerShell. Действительно, Get-Help *user* быстро выводит на нужные командлеты, а языковой вопрос решается с помощью известных SID.

Get-LocalUser | Where-Object {$_.SID -Like '*-500'} | Enable-LocalUser

Можно вводить поменьше символов, если использовать автодополнение (Tab) и отбросить синтаксический пуризм:

Get-LocalUser | ? SID -Like '*-500' | Enable-LocalUser

Для добавления пользователя в группу администраторов надо знать весь SID группы:

Add-LocalGroupMember -Member User -Group $(Get-LocalGroup -SID S-1-5-32-544)
или даже так
Add-LocalGroupMember -Member 'User' -SID 'S-1-5-32-544'

PowerShell не проигрывает в сравнении с более привычными командами net. На практике, если не знать SID, при ручном вводе все равно придется сначала смотреть названия аккаунтов или групп, а Get-LocalUser и Get-LocalGroup не длиннее net user и net localgroup.

А в скриптах или при пересылке команды для выполнения другому человеку разница в количестве символов роли не играет ✌️

#PowerShellvsCMD
▶️ PowerShell vs. CMD: автоматизация задач с датами

В форуме скриптов я регулярно вижу людей, пытающихся решать разнообразные задачи с датами с помощью CMD. Точнее, они приходят в форум, чтобы кто-то за них решал :)

Я понимаю, что далеко не все такие задачи формируются с нуля. Нередко люди пытаются модифицировать имеющиеся или найденные в сети скрипты для решения насущной проблемы. И тем не менее...

В #PowerShell вывод Get-Date варьируется в зависимости от региональных настроек ОС, как и %date% в CMD. Но в CMD это заканчивается тупиком или немыслимыми костылями, а в PowerShell все только начинается 👌

К дате элементарно добавляются или вычитаются из нее дни, часы, минуты и секунды:
(Get-Date).AddDays(-1)

А формат даты легко приводится к желаемому виду:
"{0:dd.MM.yyyy}" -f (Get-Date)

Знания этих двух моментов может быть достаточно для решения разнообразных задач. Вот человек в форуме хочет с помощью CMD каждый день копировать из одной папки в другую вчерашний файл с именем вида ДД.ММ.ГГГГ.doc.

Опытный скриптовик решит задачу и на CMD - зацените его код 👀 Мне до него как до Луны, я могу написать лишь корявенький ванлайнер на PowerShell
copy C:\1\$(-join("$("{0:dd.MM.yyyy}" -f (Get-Date).AddDays(-1))", ".doc")) C:\2

Он же в более наглядном виде:
$source = "C:\source"
$target = "C:\target"
$format = "{0:dd.MM.yyyy}" #10.09.2020
$filename = -join("$($format -f (Get-Date).AddDays(-1))", ".doc")
Copy-Item -Path $source\$filename -Destination $target


Кстати, сегодня 333й день года:
(Get-Date -Year 2020 -Month 11 -Day 28).DayOfYear
✌️

#PowerShellvsCMD
▶️ PowerShell vs. CMD: выборка по неполному значению

В предыдущем эпизоде была работа с датами. А на этот раз в форуме скриптов один участник создал две схожие темы в категории CMD/BAT.

1. Как отключить задание в планировщике, если часть названия варьируется. В качестве примера он привел:
Yandex.Stroka.User.S-1-5-21-3347023001-...

2. Как удалить из реестра параметр, у которого часть имени варьируется. Например, случайный набор символов в:
GoogleChromeAutoLaunch_1405EDE48...

👉 Обе задачи легко решаются ванлайнерами #PowerShell.

1. Участник честно попытался решить на CMD с помощью подстановочного символа *, но это не прокатило:
schtasks /Change /TN "\Yandex.Stroka*" /Disable

А на PowerShell такая логика сработает:
Get-ScheduledTask -TaskName '*yandex.stroka*' | Disable-ScheduledTask

2. С REG DELETE у товарища не получилось. В PowerShell другой командлет, но тот же принцип:
$mypath = "HKCU:SOFTWARE\Microsoft\Windows\CurrentVersion\Run"
Remove-ItemProperty -Path $mypath -Name 'GoogleChromeAutoLaunch*'

Здесь я сделал две строки из одной ради более приличного вида в Telegram.

Участник, однако, все равно возжелал CMD, потому что "они как-то привычнее". Стандартный подход:
powershell -ex bypass -noprofile -command "команда"
powershell -ex bypass -noprofile -file "путь к ps1"


📢 Василий Гусев в чате доставил, что подстановочный символ * поддерживает большинство командлетов, но не все. Это не беда, в таком случае его можно задействовать в Where-Object:
Get-ScheduledTask | where TaskName -like '*Yandex.Stroka*'

Конечно, обе задачи можно решить и на CMD, если вы владеете FOR (и любите писать больше строк нежели меньше). Но PowerShell здесь значительно проще и даже логичнее.

Да, к работе с реестром в PowerShell надо привыкнуть, но это частный случай. А выборка по неполному значению с помощью * - общий. И этот прием вы будете часто применять в разнообразных задачах ✌️

#PowerShellvsCMD
▶️ PowerShell vs. CMD: управление пользователями и группами

Читателям канала со стажем этот пост покажется знакомым, потому что я уже поднимал похожую тему в рубрике #PowerShellvsCMD. Однако там лейтмотивом была независимость команд от языка интерфейса ОС. А здесь в форум пришёл человек с просьбой помочь ему написать батник для отключения всех локальных юзеров, входящих в группу "Пользователи удаленного рабочего стола".

Он знал, как вывести всех пользователей и отключить отдельного:

net localgroup "Пользователи удаленного рабочего стола"
net user "Username" /active:no


И хотел связать это воедино. Впрочем, в течение часа он сам опубликовал решение, уложившись всего в 8 строк с помощью FOR и FINDSTR - классика жанра!

Между тем, на #PowerShell задача легко и надежно решается в одну строку:

Get-LocalGroupMember -SID S-1-5-32-555 | ForEach-Object {Disable-LocalUser -SID $_.SID}

Здесь S-1-5-32-555 - известный идентификатор группы пользователей удаленного рабочего стола. Выборка по SID в первой части конвейера позволяет не зависеть от языка системы, а во второй - исключает любые неожиданности с именами пользователей ✌️