Windows PowerShell - полезные заметки

Windows PowerShell — это оболочка командной строки и скриптовый язык с большими возможностями и красивым синтаксисом, предназначенный для системного администрирования. Windows PowerShell отличное средство для управления и автоматизации администрирования ОС Windows, а также приложений, работающих под управлением Windows.

Я был ярым поклонником vbs-скриптов. Так как заметил, что для тех задач,  для которых ранее использовал Delphi, вполне годится скриптовый язык сценариев vbs. Ведь это намного удобней просто открыть блокнот, накидать туда несколько строк, сохранить файл с нужным расширением и запустить скрипт. Для этого не нужно ничего устанавливать, как например Delphi, который к тому же платный.

Хоть vbs неплох, но его преемник PowerShell имеет куда более широкий функционал.

Содержание

У меня есть vbs-скрипт, который автоматически публикует изображения на одном из блогов. Возникла необходимость выравнивать изображение по ширине или высоте, в зависимости от разрешения добавляемого изображения. И вот я не смог получить разрешение изображений с помощью vbs-скрипта, а вот через PowerShell это делается очень просто.

Если начиная с ОС Windows 7 PowerShell идет в комплекте с самой Windows, то в Windows XP его нужно  скачать и установить - скачать PowerShell V2 для Windows XP SP3.

5-ю версию Powershell можно скачать по ссылке: microsoft.com, там же расписано какой файл для нужной ОС качать и как установить.

Windows Powershell

Как разрешить запуск локальных PowerShell скриптов?

По умолчанию Windows не даст запустить PowerShell-скрипты из-за соображений безопасности. Необходимо разрешить выполнение локальных скриптов. Выполните команду в консоли (она разрешит запускать локальные скрипты и скачанные скрипты подписанные доверенным сертификатом):

powershell -Command Set-ExecutionPolicy RemoteSigned

Иначе при попытке запустить свой скрипт вы увидите вот такой текст:

Не удается загрузить файл C:\ImageSize.ps1, так как выполнение скриптов запрещено для данной системы. Введите "get-help about_signing" для получения дополнительных сведений.
+ CategoryInfo : NotSpecified: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : RuntimeException

Чтобы вернуть эту политику безопасности обратно, напишите:

 powershell -Command Set-ExecutionPolicy Restricted

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

 powershell -Command Set-ExecutionPolicy Unrestricted

Если при запуске скрипта вы наблюдаете такое сообщение:

Security Warning Run only scripts that you trust. While scripts from the Internet can be useful, this script can potentially harm your computer. Do you want to run \server\scripts\my.ps1? [D] Do not run [R] Run once [S] Suspend [?] Help (default is "D"): d

И хотите от него избавиться, то при запуске скрипта используйте параметр -ExecutionPolicy Bypass

Пример:

powershell -ExecutionPolicy Bypass -file "\\server\scripts\my.ps1"

Как запустить PowerShell скрипт?

Введите в командной строке команду

Powershell -File your-script-name.ps1

Где your-script-name.ps1 - имя вашего скрипта. Файлы PowerShell-скриптов имеют расширение *.ps1

Справка или помощь по Windows PowerShell

В PowerShell есть различные командлеты для получения той или иной справки. Но наиболее важный из них это: Get-Help

Введите в консоли команды:

powershell -command Get-Help

powershell -command Get-Help -?

И получите два различных описания, которые дополняют друг-друга, того как пользоваться справкой.

Возможности справки достаточно обширны, с примерами и детальным описанием на русском языке. Потому можно выводить ее в различных форматах.

Например:

  • powershell -command Get-Help Get-Help - общая справка по командлету Get-Help
  • powershell -command get-help Get-Help -examples - примеры того, как можно использовать командлет get-help
  • powershell -command get-help Get-Help -detailed - подробная справка по командлету get-help
  • powershell -command get-help Get-Help -full - наиболее полная справка по командлету get-help

winintro.ru/windowspowershellhelp.ru/ - справка в виде html-книги

Заметки о Windows Powershell:

Операторы сравнения

  • -eq - Equal - Равно
  • -ne - Not equal - Не Равно
  • -ge - Greater than or equal - Больше или Равно
  • -gt - Greater than - Больше
  • -lt - Less than - Меньше
  • -le - Less than or equal - Меньше или Равно
  • -like - Wildcard comparison - Использование символов подстановки для поиска соответствия образцу
  • -notlike - Wildcard comparison - Использование символов подстановки для поиска несоответствия образцу
  • -match - Regular expression comparison - Использование регулярных выражений для поиска соответствия образцу
  • -notmatch - Regular expression comparison - Использование регулярных выражений для поиска несоответствия образцу
  • -replace - Replace operator - Заменяет часть или все значение слева от оператора
  • -contains - Containment operator - Определение, содержит ли значение слева от оператора значение справа. Результатом является булево значение
  • -notcontains - Containment operator - Определение того, что значение слева от оператора не содержит значение справа. Результатом является булево значение

По умолчанию операторы сравнения не являются чувствительными к регистру.
Для сравнения с учетом регистра к команде подставляется префикс "c". Для примера, оператор -eq с зависимостью от регистра изменяется на "-ceq".
Для явно заданного независящего от регистра сравнения к команде подставляется префикс "i". Пример: оператор -replace без зависимости от регистра будет -ireplace

Типы:

  • -is - Является типом
  • -isnot - Не является типом
  • -as - Как тип, без ошибки если возникает неудача преобразования

Логические операторы PowerShell:

  • -and - Оба условия должны быть истины, чтобы выражение было истинно
  • -or - Одно или оба условия должны быть истины, чтобы выражение было истинно
  • -xor - Одно условие должно быть истинно, а второе должно иметь значение "ложь", чтобы выражение было истинно
  • -not - Указанные условия должны иметь значение "ложь", чтобы выражение было истинно
  • ! - Указанное условие должно иметь значение "ложь", чтобы выражение было истинно

Примеры:

$myVar -is "String"
$myVar -eq 123
$myVar -ceq $myVar2
"abcdef" -like "abc*"
"abcdef" -replace "dEf","xyz"
$myVar1 -is "String" -and $myVar2 -is "Int"
(1 -eq 1) -and -not (2 -gt 2)

Операции со строками

#Разбить строку по пробелам:
$string = "Test string"
$string.split(" ")

$string.IndexOf(" ") #Ищем в $string первый пробел

# Возвращает отсчитываемый от нуля индекс первого вхождения
PS> "abcdeabcde".indexOf("cde")
2
# Возвращает позицию индекса с отсчетом от последнего вхождения указанного символа
PS> "abcdeabcde".lastIndexOf("c")
7
# Возвращает подстроку начиная с 1 позиции
PS> "abcdefgh".Substring(1) 
bcdefgh
# Возвращает подстроку начиная с 1 позиции и длиной в 4 символа
PS> "abcdefgh".Substring(1,4) 
bcde
# Вставка подстроки с позиции 0
PS> "abcdefgh".insert(0,"X")
Xabcdeabcde
# Удаление с позиции 0 длиной 2 
PS> "abcdefgh".remove(0,2)
cdeabcde
# Свойство объекта - длина строки
PS> "abcdefgh".length
8
# Возвращает True, если строка содержит подстроку "cde"
PS> "abcdefgh" .Contains("cde")
True
# Возвращает True, если строка начинается с подстроки "abc"
PS> "abcdefgh".startsWith("abc")
True
# Возвращает True, если строка заканчивается подстрокой "fgh"
PS> "abcdefgh".endsWith("fgh") 
True
# Возвращает True, если строка содержит подстроку "cde"
PS> $"abcdefgh" -like "*cde*"
True
# Возвращает массив , где "d" - разделитель
PS> "abcdefgh" -split "d" 
abc
efgh
# Возвращает строку , объединенную из двух ":" - разделитель
PS> "abcdefgh", "xyz"-join ";" 
abcdefgh;xyz
# Возвращает строку где "abc" будут заменены на "XYZ"
PS> "abcdefgh".replace("abc","XYZ") 
XYZdefgh
# Возвращает строку где символы приводятся к ВЕРХНЕМУ регистру
PS> "abcdefgh".ToUpper() 
ABCDEFGH
# Возвращает строку где символы приводятся к нижнему регистру
PS> "ABCDEFGH".ToLower()
abcdefgh

Предопределенные переменные

$home – каталог пользователя
$NULL – пусто
$true – истина
$false – лож
$DebugPreference – “Continue” выводить отладку, “SilentlyContinue” не выводить отладочную информацию. См. команду Write-Debug

Работа с файлами

$string | Out-File $file -Append #Дописать $string новой строкой в файл $file
$string = get-content -Path $file #Получить в $string содержимое файла $file
$jokes = [io.file]::ReadAllText($file) #читаем весь файл в одну строку
Test-Path "C:\test.txt" #Проверить существование файла

Найти все файлы с определенным расширением расширением в каталоге и подкаталогах.
Затем скопировать эти файлы в другой каталог.

$flist = get-childitem e:\doc\* -include *.pdf -recurse
$flist | ForEach-Object{$_.CopyTo("e:\doc\all_pdf\" + $_.PSChildName)}
ls d:\ | ?{$_.psiscontainer} | select fullname #Показать только каталоги
ls d:\ | ?{!$_.psiscontainer} | select fullname #Показать только файлы
$local = Get-Location #Текущий каталог
$local.Path # Рабочий каталог
$local.Drive.Root # Корень
$local.Drive.Name # Буква диска
$local.Drive.Used # Использовано диска
$local.Drive.Free # Свободно на диске

Вывод полных имен файлов на диске D: которые изменялись в промежутке времени от 1 июня 2014-го года до 20 сентября 2014-го года :

ls d:\ -recurse | ?{!$_.psiscontainer} | select fullname,LastWriteTime | Where-Object { $_.LastWriteTime -ge "06/01/2014" -and $_.LastWriteTime -le "09/20/2014"}

Вывод текста на экран

# текст на который надо обратить внимание. Выделяется желтым.
Write-Warning("Текст требующий внимания")
# Просто выводит текст
Write-Host("Просто текст")
#включили вывод отладочной информации
$DebugPreference = "Continue"
# вывели отладочную информацию
Write-Debug "Cannot open file."
# отключили отладочную вывод отладочной информации
$DebugPreference = "SilentlyContinue"

Сделать паузу на несколько секунд

Start-Sleep -s 15 # Пауза на 15 секунд

Пауза в консоли, до нажатия Enter

Read-Host "Нажмите Enter"

Работа с процессами

#Задача: убить все процессы с именем Notepad
# Способ №1
get-process Notepad | Stop-Process
# Способ №2 (Работает только с одним процессом)
$plist = get-process Notepad
$plist.Kill()
# Способ №3 (то же что и 2, но все процессы)
$plist = get-process Notepad
$plist | ForEach-Object {$_.Kill()}

#Получить процессы и даты их запуска:
Get-Process| Format-Table Name,StartTime -AutoSize

Инкремент

$i++ - в момент вызова i имеет старое значение, но после увеличивается на 1++

++$i - в момент вызова i увеличивается на 1

Массивы

$array = 17,15,160 #создали масив из трех элементов
$array -contains $element #содержит ли массив элемент
$file1[0] #0-й элемент массива
$file1.count #размер масива

#удаление элемента "asdf" из массива
$array = @("adsf","adf","erge") 
$array = $array |? {$_ -ne "adf"}

#получаем только уникальные элементы массива
$a = @(1,2,3,4,5,5,6,7,8,9,0,0)
$a = $a | select -uniq

#индекс первого вхождения элемента в массив
$array.indexOf("cde")

Конструкция If Elseif Else

if ( $i -eq 0 ) { Write-Host("i равно нулю") }
     ElseIf ( $i -eq 1 ) { Write-Host("i равно одинице") }
Else { Write-Host("i не равно нулю или одинице") }

Цикл ForEach

$services = Get-Service
ForEach ($service in $services) {
   $service.Stop()
}
[char]65 #конвертация ASCII-кода в символ
[int][char]'A' #конвертация символа в ASCII-код
[int[]][char[]]'Hello' #конвертация строки в ASCII-коды

Ждем нажатия любой клавишы:

$HOST.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") | OUT-NULL
$HOST.UI.RawUI.Flushinputbuffer()

$host.ui.RawUI.WindowTitle = "elimS Window Title" #задаем заголовок окна

Типы данных в PowerShell

Наиболее распространенные типы:

 [string]    Fixed-length string of Unicode characters
 [char]      A Unicode 16-bit character
 [byte]      An 8-bit unsigned character

 [int]       32-bit signed integer
 [long]      64-bit signed integer
 [bool]      Boolean True/False value

 [decimal]   A 128-bit decimal value
 [single]    Single-precision 32-bit floating point number
 [double]    Double-precision 64-bit floating point number
 [DateTime]  Date and Time

 [xml]       Xml object
 [array]     An array of values
 [hashtable] Hashtable object

Еще есть такие встроенные константы: $true, $false, $null

Unicode: To encode a Unicode character in a PowerShell string, prefix the unicode with 0x and cast it to System.Char:

PS > [char]0x263a
☺

Преобразование типов данных

To force a conversion to a specific datatype, prefix the value or variable with the type in square brackets, this is known as a Cast Operator and forces the chosen datatype:

PS C:\> [int]"0064"
64

PS C:\> [int]$false
0

PS C:\> [byte]('0x' + 'FF')
255

 

Testing DataTypes

PS C:\> 32 -is [int]
True PS C:\> $true -is [bool]
True

Функции в Powershell

function elimS { #функция имеющая несколько входных параметров
 param([string]$string = "значение по умолчанию", [int]$integer = 7) #входящие параметры
 write-host "string = " $string " | integer = " $integer
}
elimS #вызов функции без определения параметров, параметры примут значение по умолчанию
$string = "test string"
$integer = 911
elimS $string $integer #так вызывать функцию правильно - разделяем параметры пробелом
elimS -integer $integer -string $string #так тоже правильно

$global:var1 = "test" - глобальная переменная, таким образом можно передавать значение переменных из функций.

Остальное

get-host #показать версию powershell
Clear-RecycleBin c: -Force #очистка корзины
Compress-Archive -Path C:\test\* -DestinationPath C:\archive\test1.zip #архивируем папку
Expand-Archive -Path C:\temp\test1.zip 'C:\test\New folder\' #рапаковуем архив
(Get-CimInstance Win32_operatingSystem).lastbootuptime #показать время загрузки системы

write-host $sleep_array.GetType().FullName #показать тип переменной

switch ($a) { #case - множественный if
 1 {$b = $b+10 }
 2 {$b = $b+20 }
 3 {$b = $b+30 }
 4 {$b = $b+40 }
 default {$b = $b+50}
} 

Get-Content -Path "C:\scripts\test.txt" -Wait #аналог tail в linux

Командлеты powershell

Sort-Object - сортирует объекты по возрастанию или по убыванию на основе значений свойств объектов. Можно задать одно свойство или несколько свойств (сортировка по нескольким ключам), а также выбрать сортировку с учетом или без учета регистра. Кроме того, можно сделать так, чтобы командлет Sort-Object выводил только объекты с уникальными значениями того или иного свойства.

Copy-Item - копирует элемент из одного местоположения в пространстве имен в другое. Командлет Copy-Item не удаляет копируемые элементы. Типы элементов, которые может копировать командлет, определяются наличием поставщиков Windows PowerShell. Например, при использовании командлета с поставщиком FileSystem копируются файлы и папки, а при работе с поставщиком реестра копируются разделы и записи реестра.

Move-Item - перемещает элемент, включая его свойства, содержимое и дочерние элементы, из одного местоположения в другое. Оба заданных местоположения должны поддерживаться одним и тем же поставщиком. Например, можно переместить файл или вложенный каталог из одного каталога в другой либо переместить подраздел реестра из одного раздела в другой. При перемещении элемента он удаляется в исходном местоположении и создается в новом.

Remove-Item - удаляет один и более элементов. Данный командлет поддерживается многими поставщиками, поэтому он может удалять элементы различных типов, включая файлы, каталоги, разделы реестра, переменные, псевдонимы и функции.

Get-ChildItem - получает элементы из заданных местоположений. Если элемент является контейнером, данный командлет получает из контейнера элементы, которые называются дочерними элементами. Для извлечения элементов из всех дочерних контейнеров можно использовать параметр Recurse. Местоположение может являться расположением в файловой системе, например каталогом, либо расположением, предоставляемым другим поставщиком, например кустом реестра или хранилищем сертификатов.

Параметры командлетов powershell

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

  • Continue - вывести сообщение об ошибке и продолжить выполнение
  • SilentlyContinue - проигнорировать ошибку и продолжить
  • Stop - при первой же ошибке прервать выполнение
  • Inquire - при возникновении ошибки вывести запрос что делать дальше

Пример: Copy-Item "d:\test1\klbackup*" "d:\test2\" -ErrorAction stop

-WhatIf - отображает сообщение, в котором описан результат команды, без фактического ее выполнения.  Присутствует во всех командлетах.

get-help about_CommonParameters - описание параметров, которые могут использоваться с любым командлетом.

Копирование файлов между сессиями

Copy-Item - копирование файлов на удаленный ПК. На целевой машине должна работать служба удаленного управления WinRM, которая конфигурируется одной командой:

Enable-PSRemoting

Для подключения к машине в доверенном домене больше ничего не требуется.

В рабочей группе надо на своем ПК добавить целевой компьютер в доверенные узлы по имени ПК или IP-адресу:

#добавить ПК в доверенные узлы
Set-Item wsman:localhost\client\trustedhosts -value "192.168.1.113"
#убрать ПК из доверенных узлов
#Set-Item wsman:localhost\client\trustedhosts -value ""
Дальше вы создаете новую сессию, указывая имя пользователя для подключения к удаленному ПК, и вводите учетные данные. В созданную сессию можно копировать файлы.
$rs = New-PSSession -ComputerName 192.168.1.113 -Credential test-pc\vadim
Copy-Item -Path "C:\temp\my.csv" -Destination "C:\temp\" -ToSession $rs

Ссылки по теме PowerShell Remoting:

Управление пакетами (автоустановка программ)

Модуль: PackageManagement

В Windows 10 встроено управление поставщиками пакетов (оно же OneGet), с помощью которого можно тихо установить сразу несколько приложений одной командой! Это похоже на Apt-Get в Linux, но можно провести и параллели с Ninite или InstallPack

Примечание. Можно использовать этот модуль, не устанавливая WMF 5.0. Предварительная версия модуля для PS 4.0 и 3.0 доступна отдельно — март 2016 тут, а более свежие ищите поиском в центре загрузки по запросу PackageManagement PowerShell Modules Preview.

Установка программ

В этом примере из репозитория Chocolatey устанавливаются четыре программы и полный набор утилит Sysinternals. Первые три команды выполняются однократно, причем смену политики надо подтвердить. Четвертая команда тихо устанавливает перечисленные программы, а пятая просто экономит время.

#Разрешить установку подписанных пакетов из Интернета
Set-ExecutionPolicy RemoteSigned
#Установить поставщик Chocolatey
Get-PackageProvider –Name Chocolatey -ForceBootstrap
#Сделать Chocolatey доверенным
Set-PackageSource -Name Chocolatey -Trusted
#Установить программы
Install-Package NotepadPlusPlus, vlc, firefox, filezilla, sysinternals -Verbose -Force -ProviderName chocolatey
#Добавить путь к исполняемым файлам (sysinternals) в PATH
setx PATH "$env:path;C:\Chocolatey\bin" -m

Поставщик скачивает в C:\Chocolatey\lib пакет, в основе которого лежит скрипт chocolateyInstall.ps1. Он загружает установщик программы с официального сайта в папку %temp%\Chocolatey и запускает его в режиме тихой установки. Простейший пример – Notepad++.

Install-ChocolateyPackage 'notepadplusplus' 'exe' '/S' 'https://notepad-plus-plus.org/repository/6.x/6.9/npp.6.9.Installer.exe'

Поиск программ

В репозиториях много программ, все самые популярные точно есть.

Find-Package '*zip*','*commander*' -ProviderName Chocolatey

Удаление программ

Uninstall-Package -name filezilla

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

Ссылки по теме OneGet и тихой установки:

Установка обновлений Windows через Powershell

  • Качаем модуль Windows Update PowerShell Module с сайта microsoft.
  • Распаковываем архив в папку %WINDIR%\System32\WindowsPowerShell\v1.0\Modules
  • Если еще не разрешали запускать локальные скрипты, то разрешаем это делать: "Set-ExecutionPolicy RemoteSigned".
    • Проверить можно при помощи команды "Get-ExecutionPolicy": должно быть "RemoteSigned" вместо "Restricted"
  • Импортируем скачанный модуль командой: "Import-Module PSWindowsUpdate"
  • Готово. Теперь можно использовать команды:
    • Посмотреть список доступных обновлений: Get-WUInstall -ListOnly
    • Установить все обновления не спрашивая подтверждения: Get-WUInstall -AcceptAll
    • Установить все обновления не спрашивая подтверждения и отложить перезагрузку: Get-WUInstall -AcceptAll -IgnoreReboot
    • Установить определенные обновления зная их номер: "Get-WUInstall -KBArticleID KB3066441, KB3078676 -AcceptAll -IgnoreReboot" - теперь не нужно заходить на сайт microsoft и выкачивать их вручную
    • Подробная справка по модулю: get-help Get-WUInstall  -detailed
    • Посмотреть список доступных обновлений исключив категорию "Language packs", заголовки "Skype" и обновление KB3012973: Get-WUInstall -NotCategory "Language packs" -NotTitle Skype -NotKBArticleID KB3012973 -ListOnly
    • Установить обновления исключив категорию "Language packs", заголовки "Skype" и обновление KB3012973: Get-WUInstall -NotCategory "Language packs" -NotTitle Skype -NotKBArticleID KB3012973 -AcceptAll -IgnoreReboot

Примеры PowerShell скриптов

Используемые источники и полезные ссылки

Понравилось? =) Поделись с друзьями:

Обсуждение записи “Windows PowerShell - полезные заметки”

  1. alkash says:

    Спасибо! Полезная, замечательная статья.

  2. Val says:

    Добрый день! А подскажите пож-та как все таки отключить безопасность на OS Win 7-XP? пишет: «Set-Execution Policy: Отказано в доступе к разделу реестра «HKEY_LOCAL_MASHINE\SOFTWARE… строка 1 знак 20″» после выполнения команды: powershell -Command Set-ExecutionPolicy RemoteSigned

    Подскажие вообще можно сделать на PS такое: добавить/удалить/переименовать польз-ля, добавить его в нужную группу, создать каталоги, пересети профиль польз-в нужные созданные каталоги? откобчить аэро тему вин7? Заранее благодарен.

  3. Владимир Демянович (elims.org.ua) says:

    Добрый день, с такой проблемой не сталкивался. А касательно того что можно сделать на PS: на нем можно сделать все, а особенно такие стандартные операции администрирования, которые Вы упомянули, именно для этого и был создан PS.

  4. Владимир says:

    Командную строку запускайте от имени администратора

  5. spy686 says:

    Помучился с установкой PowerShell 5.0 на Win7 x64.

    Ни в какую не хотел ставиться:
    Windows Management Framework 5.0 Preview April 2015
    Windows6.1-KB2908075-x64.msu
    https://www.microsoft.com/en-us/download/details.aspx?id=46889

    Выдавал ошибку:
    Установщик обнаружил ошибку: 0x800b0101
    Истек/не наступил срок действия требуемого сертификата при проверке по системным часам или по отметке времени в подписанном файле.

    Fix MicrosoftFixit50531 и обновление kb947821 не помогли.

    Решилось установкой:
    1. Windows Management Framework 4.0
    Windows6.1-KB2819745-x64-MultiPkg.msu
    https://www.microsoft.com/en-us/download/details.aspx?id=40855
    2. Windows Management Framework 5.0 Production Preview
    Win7AndW2K8R2-KB3066439-x64.msu
    https://www.microsoft.com/en-us/download/details.aspx?id=48729

    Возможно шаг 1 лишний, но у меня в такой последовательности встало.
    Может и не в этом дело было, может звезды повернулись как надо, но как то так.
    Возможно комуто поможет сократит путь мучений)

  6. Владимир Демянович (elims.org.ua) says:

    Спасибо =)

  7. spy686 says:

    Добавьте, пожалуйста, команду получения пути исполняемого скрипта .ps1

  8. spy686 says:

    $MyInvocation.MyCommand.Path

Обсудить