Краткий учебник основ Powershell

Несколько лет назад мною писались заметки по Powershell.

В данном документе я их систематизирую и актуализирую.

На дворе начало 2018 года.

 

Powershell находится здесь:
C:\Windows\System32\WindowsPowerShell\v1.0
или
%SystemRoot%\System32\WindowsPowerShell\v1.0


Так-же имеется средство разработки - ISE (Integrated Script Environment)
powershell_ise.exe

 

Запуск сценариев PowerShell:
По умолчанию выполнение скриптов Windows PowerShell запрещено

Уровень Restricted – запрещает выполнение сценариев
Уровень Unrestricted – все сценарии могут запускаться
Уровень AllSigned – все сценарии должны иметь цифровую подпись
Уровень RemoteSigned – сценарии из сети долны быть подписаны


В реестре по пути: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell
Задается параметр например - "ExecutionPolicy"="AllSigned"
Либо управляем командлетами - Get-ExecutionPolicy и Set-ExecutionPolicy
Пример: Set-ExecutionPolicy RemoteSigned

 

  1. Знакомство

Основная конструкция языка глагол-существительное.

Простые примеры:

Get-Help – вывести справку.

Get-Process – вывести список процессов.

Get-Command – вывести команды.

 

Передача параметров происходит через дефис «-».

Вывод команд с глаголом «Get»:

Get-Command –Verb Get

Вывод команд с существительным «Event»:

Get-Command –Noun event

Неявная передача параметра команде Get-help (справка по команде):

Get-Help Get-Event

Get-Help Get-Event –Detailed

Get-Help Get-Event -Full

Get-Help Get-Event -Examples

Список модулей в Powershell:

Get-Module –ListAvailable

Вывести все команды из модуля «NetTCPIP»:

Get-Command –Module NetTCPIP

Обновить справку(необходимо подключение к интернету и права администратора):

Update-Help

 

#Переменные среды
Get-Childitem env:
Get-Childitem env:
dir env: | sort name

#Вывод имя и значения переменной
Get-Item env:windir
Get-Childitem env:UserName

#Вывод значения переменной
write-host $env:windir
write-host $env:UserName
write-host ([System.Environment]::CurrentDirectory)
write-host ([System.Environment]::UserName)

#Изменение переменных (доступны командлеты Set-Item, Remove-Item, and Copy-Item)
$env:customvar = "Var1"
$env:customvar = $env:customvar + "Var2"
Set-Item -path env:customvar -value ($env:customvar + 'Var3')

 

  1. Конвейер и управление сервисами

Вывод порционно:

Get-Command | more

С сортировкой по столбцу Version:

Get-Command | Sort-Object Version

С сортировкой + вывод первых 50 строк:

Get-Command | Sort-Object Version | Select-Object -First 50

Вывести свойства и методы объектов:

Get-Service | Get-Member

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

Get-Service | Get-Member -MemberType Method

Перенаправление вывода в файл:

Get-Service | Out-File "C:\test.txt"

Управление сервисом(с правами администратора):

Выбрали сервис:

Get-Service -Name AdobeARMservice

Что мы можем с ним делать:

Get-Command -Noun service

Рестартуем сервис:

Restart-Service AdobeARMservice

 

3.Работа с файловой системой

Какие есть команды для работы с файловой системой:

Get-Command -Noun item

Посмотреть содержимое директории(аналогично dir):

Get-ChildItem "C:\Program Files\7-Zip\"

Посмотреть все файлы по маске .exe, Recurse – вернет объекты, Force – покажет скрытые.

Get-ChildItem "C:\Program Files\7-Zip\" -Include *.exe -Recurse –Force

Удалить файл:

Remove-Item "C:\test.txt"

Создать папку:

New-Item -Path 'C:\temp\testfolder' -ItemType "directory"

Создать файл:

New-Item -Path 'C:\temp\testfolder\testfile.txt' -ItemType "file"

Удалить папку и содержимое:

Remove-Item 'C:\temp\testfolder' –Recurse

Работа со столбцами(оба примера равнозначны):

Для обработки используется конструкция @{}.

Ей передается аргумент в виде названия столбца n="Kbytes";

Далее происходит обработка столбца e={$PSItem.Length/1024}

$PSItem и $_ - ссылки на текущий объект.

Get-ChildItem "C:\Program Files\7-Zip\" | Select-Object -Property Name, Length, @{n="Kbytes"; e={$PSItem.Length/1024}}

Get-ChildItem "C:\Program Files\7-Zip\" | Select-Object -Property Name, Length, @{n="Kbytes"; e={$_.Length/1024}}

Вывод по маске в столбце:

Get-ChildItem "C:\Program Files\7-Zip\" | Where-Object Name -Like "7z*"

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

-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 Определение того, что значение слева от оператора не содержит значение справа. Результатом является булево значение

Вывод, где размер больше или равен с поиском по маске:

Get-ChildItem "C:\Program Files\7-Zip\" | Where-Object -FilterScript {$_.Length -ge 150000 -and $_.Name -Like "7z.*"}

Вывод с общего занятого места объектами, с выводом максимального размера файла:

Get-ChildItem "C:\Program Files\7-Zip\" | Measure-Object -Property Length -Sum –Maximum

Вывод в форматированном виде, табуляция после Format-Table покажет варианты:

Get-ChildItem "C:\Program Files\7-Zip\" | Format-Table FullName, Extension, Length, Attributes

 

  1. Программирование

Посмотреть список стандартных переменных:

Get-Variable

Вывести значение переменной:

$PWD

Типы переменных:

[int] - целые числа

[single] - числа одинарной точности

[double] – числа двойной точности

[string] - текст

[char] - символ

[Boolean] – булево значение «Истина» \ «Ложь»

[datetime] - дата или время

Зададим значения переменных и произведем действие:

[int]$a = 10

[int]$b = 5

$a - $b

Конструкция if (elseif и else – необязательные блоки) – проверка условия:

[int]$a = 10

If ($a -eq 10){

    Write-Host "a = 10"

}

ELSEIF ($a -gt 10){

    Write-Host "a > 10"

    }

ELSE {

    Write-Host "a < 10"

}

Конструкция switch – проверяет значение:

[int]$a = 1

SWITCH ($a)

{

 0 {Write-Host "a = 0"}

 1 {Write-Host "a = 1"}

 2 {Write-Host "a = 2"}

 default {Write-Host "a - ?"}

}

Цикл while – выполняется, пока условие верно:

[int]$a = 1

WHILE ($a -lt 3){

    Write-Host $a

    $a = $a + 1

}

Аналогичная задача с while для цикла for:

FOR ([int]$a = 1; $a -lt 3; $a++){

    Write-Host $a

}

Перебор с помощью цикла foreach:

$Process = Get-Process

FOREACH ($proc In $Process){

    $proc.ProcessName + " - " + $proc.Id

}

 

Массивы, создание, обращение, перебор:

[int32[]]$Array = 1, 2, 3, 4

$Array[2]

FOR ([int]$i = 0; $i -lt $Array.count; $i++){

    $Array[$i]

}

Обработка исключений(ошибок), введите число или символ:

Try {

  [int]$num = Read-Host "Enter num"

  6 / $num

} catch {

  Write-Warning "Error"

}

Функции:

Простой пример и вызов:

Function Func{"func is work"}

Func

Пример с аргументами:

Function Func{"this is args: $Args"}

Func arg1 arg2

Еще пример с аргументами:

Function Func ($a, $b) {"this is args: $a $b"}

Func arg1 arg2

Пример с предопределенными значениями:

Function Func ($a="a1", $b="a2") {"this is args: $a $b"}

Func

#Пример функции
Function Func{ Param ([String]$arg1, $arg2) "this is arg1:" + $arg1 + " " + "this is arg2: " + $arg2}
Func arg11 arg22

 

#Классы
#Описание класса
class Writer {
    #Свойства класса
    [String]$OutDisk
    [String]$OutDir = '\scripts\'

    #Конструктор класса
    Writer([String]$FilePath) {
        $This.OutDir += $FilePath
        $this.OutDir = $this.OutDisk + $this.OutDir
    }

    #Методы класса
    [void]Write([String]$Per) {
        '[{0} {1} {2}]' -f $(Get-Date), $Per, '#It Works!' |
            Out-File $This.OutDir -Append -Encoding default
    }

    [int]GetSizeFile() {
        return (Get-Item $This.OutDir).Length
    }    
}

#Создание экземпляра класса
$WriterObj = [Writer]::New('test.txt')
#Присваиваем значение свойству
$WriterObj.OutDisk = 'C:'
#Вызываем методы
$WriterObj.Write('Class Writer, method Write')
$WriterObj.GetSizeFile()

 

#SQL
#С помощью командлета invoke-sqlcmd на самом SQL сервере
$conn = invoke-sqlcmd -ServerInstance 'Адрес_Сервера' -database Имя_БД -Query "SQL_Запрос";
echo $conn >> C:\scripts\out.txt;

#Пример подключения под доменной авторизацией с помощью класса SqlConnection библиотеки классов .NET Framework
$SqlServer = "Адрес_Сервера";
$SqlCatalog = "Имя_БД";
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
$SqlConnection.ConnectionString = "Server=$SqlServer; Database=$SqlCatalog; Integrated Security=True"
$SqlConnection.Open()
$SqlCmd = $SqlConnection.CreateCommand()
$SqlCmd.CommandText = "SQL_Запрос"
$objReader = $SqlCmd.ExecuteReader()
while ($objReader.read()) {
  '[{0} {1}]' -f $objReader.GetValue(0), $objReader.GetValue(1)
}
$objReader.close()
$SqlConnection.Close()

#Пример подключения под SQL авторизацией с помощью класса SqlConnection библиотеки классов .NET Framework
$SqlServer = "Адрес_Сервера";
$SqlCatalog = "Имя_БД";
$SqlLogin = "Логин_Пользователя";
$SqlPassw = "Пароль_Пользователя"
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
$SqlConnection.ConnectionString = "Server=$SqlServer; Database=$SqlCatalog; User ID=$SqlLogin; Password=$SqlPassw;"
$SqlConnection.Open()
$SqlCmd = $SqlConnection.CreateCommand()
$SqlCmd.CommandText = "SQL_Запрос"
$objReader = $SqlCmd.ExecuteReader()
while ($objReader.read()) {
  '[{0} {1}]' -f $objReader.GetValue(0), $objReader.GetValue(1)
}
$objReader.close()
$SqlConnection.Close()

#Пример исполнения SQL запросов с изменением данных ($SqlCmd.ExecuteNonQuery() | Out-Null - подавляет вывод результатов выполнения запроса)
$SqlServer = "Адрес_Сервера";
$SqlCatalog = "Имя_БД";
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
$SqlConnection.ConnectionString = "Server=$SqlServer; Database=$SqlCatalog; Integrated Security=True"
$SqlConnection.Open()
$SqlCmd = $SqlConnection.CreateCommand()
$SqlCmd.CommandText = "delete from [dbo].[tasks]"
$SqlCmd.ExecuteNonQuery() | Out-Null
$SqlConnection.Close()

 

#Работа с почтой по SMTP
#Параметры подключения
$ConstServer = "mail.domain.ru"                                 #Адрес SMTP сервера
$ConstSMTPPort = "25"                                           #Порт SMTP сервера
$ConstFrom = "sender@domain.ru"                                 #Адрес отправителя сообщения
[string[]]$ConstTo = "one@domain.ru","two@domain.ru"            #Адреса получателей сообщения
$ConstMessageTypeHTML = $true                                   #Формат сообщения HTML - true, обычный текст - false
$ConstUserName = "sender"                                       #Имя пользователя (ящика) для авторизации на сервере SMTP
$ConstUserPass = "Пароль_Учетки"                                #Пароль авторизации пользователя на сервере SMTP
$ConstMessageSubject = "Тема сообщения"                         #Тема сообщения
$ConstMessageBody = "Текст сообщения"                           #Тело сообщения
$SourceFile='C:\temp\attach.txt'                                #Прикрепляемый файл

#Создаем подключение:
$SmtpClient = New-Object System.Net.Mail.SmtpClient 
$SmtpClient.Host = $ConstServer
$SmtpClient.Port = $ConstSMTPPort
$SmtpClient.EnableSsl = $false
$SmtpClient.Credentials= New-Object System.Net.NetworkCredential($ConstUserName , $ConstUserPass)

#Создаем сообщение:
$Message = New-Object System.Net.Mail.MailMessage 
$Message.From = $ConstFrom
$Message.To.Add($ConstTo)
$Message.BodyEncoding = [System.Text.Encoding]::UTF8
$Message.SubjectEncoding = [System.Text.Encoding]::UTF8
$Message.IsBodyHtml = $ConstMessageTypeHTML
$Message.Subject = $ConstMessageSubject
$Message.Attachments.Add($SourceFile)
$Message.Body = (get-date).ToString() + "<br>" + $ConstMessageBody"

#Соединение
$SmtpClient.Send($Message) #Отправляем SMTP сообщение
if($?) { write-host "Сообщение успешно отправлено" } else{ write-host "Сообщение небыло отправлено, ошибка:" $Error[0].ToString() }
$Message.Dispose()         #Команда QUIT для SMTP-сервера, завершает TCP-подключение и высвобождает ресурсы, текущего соединения