Ускоренное продвижение PowerShell: хакерство для не- программистов

Викас Сухиджа

Copyright © 2022 Викас Сухиджа

Данный документ предоставляется по лицензии Creative Commons Attribution 3.0 License, за исключением разделов со специальными оговорками.

http://creativecommons.org/licenses/by/3.0/legalcode

Первая публикация на английском языке: 25 Ноября 2021

Опубликовано Apress, Berkeley, CA

North Richland Hills, TX, USA

ISBN 1-4842-7758-9

ISBN 978-1-4842-7758-4

eBook ISBN 978-1-4842-7759-1

https://doi.org/10.1007/978-1-4842-6873-5

www.apress.com

2022-03-28

 Состав исполнителей

Издания на английском языке

Автор

Хайден Барнс

Директор- распорядитель, Apress Media LLC

Велмоуид Спахр

Редактор приобретения

Смрити Шривастэйв

Редактор по разработке

Джеймс Маркхам

Координирующий редактор

Марк Пауэрс

Редактор текста

Мэри Вер

Разработка обложки

eStudioCalamar

www.freepik.com

Изображение обложки

Джошуа Коттен

www.unsplash.com

 Об авторе

Хайден Барнс обладает более чем десятилетним опытом работы с ИТ инфраструктурой, а также имеет знания в области обмена сообщениями, совместной работы и автоматизации ИТ с применением PowerShell, PowerApps, Power Automate и прочих инструментов. В настоящее время он работает Глобальным директором Golden Five Consulting в Канаде. Также он является блогером, архитектором и Microsoft MVP. Он известен под именем TechWizard. В качестве опытного специалиста он помогает малым и крупным предприятиям разрабатывать, внедрять и автоматизировать Microsoft 365 и Azure.

 О техническом рецензенте

Арун Шарма является лидером в области технологий и стратегии и обладает большим опытом в области консультаций по вопросам разработки, облачных вычислений, искусственного интеллекта и IoT. В настоящее время он связан с Fresh & Pure, агротехническим стартапом, в должности директора программы управления автоматизацией и искусственного интеллекта. Он обладает опытом работы с различными технологиями (Microsoft Azure, AWS, Ali Cloud), IoT, ML, микрослужбами, ботами, Dynamics 365, PowerPlatform, SAP Crystal Reports, DevOps, Docker и контейнеризацией. Он имеет более чем 20-летний опыт работы на самых разных должностях, таких как Генеральный управляющий Paytm, менеджер по доставке в Microsoft, менеджер по продуктам в Icertis, ведущий и ассоциированный архитектор в Infosys, исполнительный тренер в Aptech и консультант по развитию в CMC. Он управлял отношениями на уровне Главного специалиста по практике на стратегических уровнях, продажах, использовании облачных технологий, консультационных услугах и внедрении со средними и крупными глобальными клиентами.

 Введение

Эта маленькая книга наполнена небольшими сценариями, которые можно применять системными администраторами для улучшения своей эффективности в их повседневных операциях ИТ. Ускоренное продвижение PowerShell служит для опытных администраторов ИТ, которые хотят применять сценарии и реализовывать автоматизацию ИТ. Просто скопируйте/ вставьте блок кода из книги/ ссылок чтобы превратить в простые сложные сценарии. Вы можете рассматривать её как свою персональную книгу шпаргалок сценариев, подобно кодам шпаргалок, которые геймеры применяют для электронных игр. Однако на самом деле это практическое руководство, потому как оно поможет вам начать автоматизировать бо́льшую часть вашей работы.

 Содержание

О книге

Об авторе

О техническом рецензенте

Введение

Глава 1. Основы PowerShell

Переменные и вывод на печать

Переключатель If/Else

Операторы условия/ логики

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

Циклы

Цикл For и цикл While

Цикл For

Цикл While

Функции

Выводы

Глава 2. Даты и журналы

Манипуляция датами

Создание папок на основе даты

Готовые функции даты и журнала

Выводы

Глава 3. Входные данные вашего сценария

Import-CSV

Импорт из текстового файла

Ввод из массива

Выводы

Глава 4. Интерактивный ввод

Read-host

Параметры

Кнопка графического интерфейса

Приглашение на ввод (Yes или No)

Выводы

Глава 5. Добавление оснасток/ модулей

Оснастки PowerShell

Модули

Модуль шпаргалки (vsadmin)

Шифрование пароля (vsadmin)

Выводы

Глава 6. Отправка электронной почты

Форматирование тела письма

Отправка HTML

Выводы

Глава 7. Отчёты об ошибках

Отчёты об ошибках по электронной почте

Регистрация всего содержащего ошибки

Регистрация ошибок в текстовый файл

Выводы

Глава 8. Отчёты

Отчёт CSV

Отчёт Excel

Отчёт HTML

Выводы

Глава 9. Различные ключевые слова

Split

Replace

Select-String

Compare-Object

Выводы

Глава 10. Склеиваем всё это воедино

Примеры продуктов (ежедневного применения)

Microsoft Exchange

Очистка базы данных с тем, чтобы Почтовые ящики появлялись в отключённом состоянии

Поиск отключённых Почтовых ящиков

Выделение Сообщение получено от

Активные синхронизации статистик

Отслеживание сообщений

Поиск сообщений Почтовый ящик/ Удалённые

Отчёт о квотах Exchange

Настройка квот

Active Directory

Экспорт Участников группы

Установка значения для атрибутов AD

Экспорт атрибутов AD

Добавление участников в группу из текстового файла

Удаление участников в группу из текстового файла

Office 365

Отчёт Почтового ящика Exchange Online

Отслеживание сообщения Exchange Online

Поиск унифицированного журнала

Azure AD

Добавление пользователей в группу Azure AD из текстового файла UPN

Удаление пользователей в группе Azure AD из текстового файла UPN

Проверка является ли пользователь участником группы

Добавление в роль Администраторов

Проверка ошибок предоставления пользователей Azure AD

Операции с файлом Text/CSV

Regex

Выводы

Указатель

Глава 1. Основы PowerShell

Содержание

Глава 1. Основы PowerShell

Переменные и вывод на печать

Переключатель If/Else

Операторы условия/ логики

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

Циклы

Цикл For и цикл While

Цикл For

Цикл While

Функции

Выводы

Давайте начнём с базовых элементов и быстро просмотрим переменные, циклы, операторы if/else, переключатели и функции. Все они являются сердцем любого языка сценариев и поспособствуют вам в создании сценариев от простых до сложных.

Я не погружаюсь в версии PowerShell или в то чем является PowerShell (но вот вам быстрое для понимания определение без особого углубления: PowerShell это решение автоматизации задач составленных в командной строке оболочки и язык сценариев {Прим. пер.: подробнее в нашем переводе 4 издания Книга рецептов автоматизации Windows Server при помощи PowerShell Томаса Ли, Packt Publishing, 2021}). Я также не хочу говорить о том в каких платформах он может применяться или получать и устанавливать команды, потому как это не всеобъемлющая книга для изучения данного языка.

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

Не все обладают опытом программирования, и не все умеют создавать код. Однако, следуя описанному в этой книге подходу, вы сможете быстро создавать собственные сценарии и автоматизировать ИТ системы/ процессы.

[Замечание]
Замечание

Ко всем применяемым в данной книге кодам можно получить доступ кликнув по кнопке Download Source Code, расположенной на www.apress.com/9781484277584 (следите за номерами листингов).

Переменные и вывод на печать

Для начала нам необходимо разобраться с основами, которые включают переменные и массивы. Всякая переменная в PowerShell начинается с символа доллара ($), например:

$a = "1"
$b = "Vikas"

Когда вы набираете $a и $b, будут отображены значения, как это показано на Рисунке 1-1.

Рисунок 1-1

Переменные в PowerShell

Теперь для вывода на свой экран вы можете применить Write-host:

Input: PS C:\> Write-host $a
Output: 1
Input: PS C:\> Write-host $b
Output: vikas

[Совет]
Совет

Возьмите за правило применять кавычки при присвоении значений переменным, как это показано в предыдущих двух примерах.

Давайте изменим значение фонового цвета того, что отображается через Write-host:

Input: PS C:\& Write-host $b -ForegroundColor Green
Output: vikas
Input: PS C:\& Write-host "processing .........." -ForegroundColor Green
Output: processing ..........
PS C:\&

Рисунок 1-2 отображает получаемый результат:

Рисунок 1-2

Применение Write-host переменная

Давайте по- быстрому проиллюстрируем массивы. В PowerShell массивы могут определяться аналогичным переменным способом. Вот некоторые образцы:

$b = "A","B","C","D","E"

Если вы определите это как переменную и разделяете все элементы запятой, PowerShell автоматически распознаёт что это массив, как то отображено на Рисунке 1-3.

Рисунок 1-3

Иллюстрация массива

Надлежащим способом определения массива выступает показанный ниже, потому как это показано самим синтаксисом, именно это представляет массив (что показано на Рисунке 1-4):

$c= @("server1","server2")

Рисунок 1-4

Синтаксис массива

Динамический массив может определяться как @(). Вы будете применять этот тип в примерах данной книги для добавления элементов в свой массив и выработки отчётов:

$d= @()

Переключатель If/Else

If else является обработкой на основе условия. Это основа любого языка программирования сценариев. Если некоторое условие истинно, вам необходимо обработать нечто; в противном случае обрабатывается нечто иное.

Листинг 1-1 показывает два примера. Во- первых, вы определяете значение переменной как 10 и затем вы пользуетесь соответствующим условными операторами и предложениями if else для проверки больше ли это чем 9 или меньше. На основании полученного результата вы применяете Write-host для вывода на экран, как это показано на Рисунке 1-5.

Обратите внимание, что -gt означает больше чем, а -lt меньше чем. Не беспокойтесь; я быстро пробегусь по ним в своём следующем подразделе.

Листинг 1-1. Пример кода для применения оператора больше чем в If/Else

[int]$a= "10"

if($a -gt "9")
{
write-host "True" -foregroundcolor Green
}else {
Write-host "False" -foregroundcolor Red
}

И да, [int] означает целое. Если вы применяете префикс перед самой переменной, он означает что вы исключительно определяете её как целое. Определять всегда лучше, но если вы не хотите, PowerShell достаточно сообразителен чтобы выполнить это неявно. Существуют именуемые типы данных и они содержат [string], [char], [int], [array] и так далее.

Рисунок 1-5

Отображение применения -gt в if/else

Листинг 1-2 и Рисунок 1-6 показывают фрагмент кода применения оператора меньше чем.

Листинг 1-2. Пример кода для применения оператора меньше чем в If/Else

[int]$a= "10"

if($a -lt "9"){
write-host "True" -foregroundcolor Green
}else {
Write-host "False" -foregroundcolor Red
}

Рисунок 1-6

Отображение применения -lt в if/else

Операторы условия/ логики

Ниже приводится перечень операторов условия/ логики, которые вы можете применять в своих повседневных сценариях. Без них многие операции сценариев были бы невозможны. Они всегда используются в предложениях сравнения if else, как это показано выше в родительском разделе.

-eq Равно

-ne Не равно

-ge Больше чем или равно

-gt Больше чем

-lt Меньше чем

-le Меньше чем или равно

-like     Сопоставление с символами подстановки

-notlike  Сопоставление с символами подстановки

-match   Сопоставление регулярным выражением

-notmatch Сопоставление регулярным выражением

-replace  Оператор замены

-contains Оператор включения

-notcontains Оператор включения

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

-and Логическое И

-or  Логическое ИЛИ

-not Логическое ОТРИЦАНИЕ

-!   Логическое ОТРИЦАНИЕ

Логические операторы применяются когда вы желаете комбинировать свои условия. Давайте обновим приводимый ранее пример в отображаемый в Листинге 1-3 пример. Вы выводите на печать true когда значение переменной $a меньшем чем 9 или равно 10. Здесь вы сочетаете два условия. Поскольку это оператор OR, TRUE будет возвращаться при одном из совпадений. Здесь наше второе условие, $a -eq "10", совпадает если значение равно 10. Посмотрите на полученный на Рисунке 1-7 результат.

Листинг 1-3. Пример кода, отображающего логический оператор -or

[int]$a= "10"

If(($a -lt "9") -or ($a -eq "10")){
write-host "True" -foregroundcolor Green
}else {
Write-host "False" -foregroundcolor Red}

Рисунок 1-7

Отображение логического оператора -or

Когда вы применяете оператор OR, тогда должны совпадать оба условия если вы желаете получить TRUE, что не происходит в обоих случаях. Смотрите Листинге 1-4 и Рисунок 1-8.

Листинг 1-4. Пример кода, отображающего логический оператор -and

[int]$a= "10"

If(($a -lt "9") -and ($a -eq "10")){
write-host "True" -foregroundcolor Green
}else {
Write-host "False" -foregroundcolor Red}

Рисунок 1-8

Отображение логического оператора -and

Not служит для отрицания. В целом, я не пользуюсь им часто. По моему опыту, это приводит к человеческой ошибке когда вы спешите и недостаточно всё обдумаете.

Циклы

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

Цикл For и цикл While

Цикл For

В PowerShell существуют три повтора для циклов for:

foreach

foreach-object

for

Давайте проведём различия между этими тремя циклами for рассмотрев их на примерах.

foreach: Вам требуется определить foreach $variable в $collection: foreach ($i in $x).

[Замечание]
Замечание

В Листинге 1-5 вы сочетаете операторы if else и сравнения. На Рисунке 1-9 вы можете наблюдать получаемые результаты.

Листинг 1-5. Код, отображающий цикл foreach

$x=@("1","2","3",,"4")

foreach ($i in $x) {
      if ($i -lt 2) { write-host "$i is Green" -foregroundcolor Green
      }
         else{ write-host "$i is yellow" -foregroundcolor yellow
      }
 }

Рисунок 1-9

Отображение оператора foreach

foreach-object: Вы пользуетесь конвейером (PIPE) с его коллекцией для достижения тех же самых моментов (смотрите Листинг 1-6 и Рисунок 1-10):

$x | foreach-object

Листинг 1-6. Код, отображающий цикл foreach-object

$x=@("1","2","3",,"4")

$x | foreach-object{
        if ($_ -lt 2) { write-host "$_ is Green" -foregroundcolor Green
		}
        else{ write-host "$_ is yellow" -foregroundcolor yellow
		}
     }

Рисунок 1-10

Отображение оператора foreach-object

for: Это именно то, что вы могли запомнить в свои школьные годы. Я почти не применяю его вовсе и вижу меньше применений по всему сообществу. Посмотрите на его код в Листинге 1-7 и получаемые результаты на Рисунке 1-11.

Листинг 1-7. Код, отображающий цикл for

for($x=1; $x -le 5; $x++){
    if($x -lt 2){write-host "$x is Green" -foregroundcolor Green
    }
    else{ write-host "$x is yellow" -foregroundcolor yellow
    }
}

Рисунок 1-11

Отображение оператора for

Цикл While

Цикл while является совсем другим, потому как он продолжается пока его условие истинно. Давайте пройдёмся по некоторым образцам чтобы получить больше ясности.

Цикл while также обладает двумя повторами:

do-while

while

Для do-while вы выполняете нечто пока выполняется соответствие какого- то условия. В Листинге 1-8 переменная x = 0 и внутри вы наращиваете значение этой переменной, пока оно не станет равным 4. Для получаемых результатов посмотрите на Рисунок 1-12.

[Замечание]
Замечание

Сначала вы делаете что- то, а потом проверяете соответствие условия.

Листинг 1-8. Код, отображающий цикл do-while

$x= 0

Do {$x++
if($x -lt 2){write-host "$x is Green" -foregroundcolor Green
              }
             else{ write-host "$x is yellow" -foregroundcolor yellow
}
 }while($x -ne 4)

Рисунок 1-12

Отображение оператора do-while

Для while вы также выполняете нечто пока выполняется соответствие какого- то условия. В Листинге 1-9 переменная x = 0 и внутри вы наращиваете значение этой переменной, пока оно не станет равным 4.

[Замечание]
Замечание

Сначала вы осуществляете проверку и после этого выполняете свои дела.

Основное отличие между этими двумя, как вы можете видеть, состоит в том, что цикл while (пример, который показан на Листинге 1-9) проверяет своё условие перед самим циклом (повтором), а do-while осуществляет проверку после своего выполнения. Для получаемых результатов взгляните на Рисунок 1-13.

Листинг 1-9. Код, отображающий цикл while

$x= 0

while($x -ne 4) {$x++
if($x -lt 2){write-host "$x is Green" -foregroundcolor Green
       }
       else{ write-host "$x is yellow" -foregroundcolor yellow
      }
}

Рисунок 1-13

Отображение оператора while

Функции

Функции это такие предметы, которые после определения могут вызываться в любом месте сценария. Применение функций позволяет избегать повторов длинного кода. Это намёк для лучшего понимания. Я не буду вдаваться в подробности задания параметров и расширенных функциональных возможностей функции, так как мой главный мотив здесь - слегка разобраться и объединить свой код для выполнения необходимой работы. В Листинге 1-10 вы создаёте функцию Add для сложения двух чисел. Получаемый результат показан на Рисунке 1-14.

Листинг 1-10. Пример кода, отображающего функцию сложения двух чисел

Function Add ($a1, $b1)
{
$a1 + $b1
}

Add 5 6 # Вызов функции

Рисунок 1-14

Отображение функции Add сложения двух чисел

Аналогично, вы можете создать её для трёх и более чисел. Отсылаем вас к Листингу 1-11 и Рисунку 1-15.

Листинг 1-11. Пример кода, отображающего функцию сложения трёх чисел

Function Add ($a1, $b1, $c1)
{
$a1 + $b1 +$c1
}

Add 5 6 9 # Вызов функции

Рисунок 1-15

Отображение функции Add сложения трёх чисел

Выводы

В этой главе мы ознакомились с основами PowerShell, такими как переменные, массивы, операторы if/else и циклами, которые выступают основными строительными блоками для создания мощных сценариев в промышленной среде. Эти основы будут применяться и дальше в наших последующих главах.

Глава 2. Даты и журналы

Содержание

Глава 2. Даты и журналы

Манипуляция датами

Создание папок на основе даты

Готовые функции даты и журнала

Выводы

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

Давайте пройдёмся по некоторым иллюстрациям даты и времени прежде чем применять свою функцию Write-Log, которую я уже создал для вас. (Это самый первый реальный код шпаргалки, которым вы можете пользоваться в своих сценариях!)

Команда get-date снабжает вас значениями текущих даты и времени, как это показано на Рисунке 2-1.

Рисунок 2-1

Отображение командлета get-date

Для форматирования его таким образом, чтобы они позволяли нам применять их в названиях файлов и прочих экземплярах, может применяться команда format, как это показано на Рисунке 2-2.

get-date -format d

Рисунок 2-2

Отображение отформатированной даты

Листинг 2-1 показывает применение в имени файла даты и времени.

Листинг 2-1. Код для использования даты и времени в имени файла

$date = get-date -format d                  # форматирование
$date = $date.ToString().Replace("/", "-")  # замена / на -
$time = get-date -format t    # only show time
$time = $time.ToString().Replace(":", "-") # замена : на -
$time = $time.ToString().Replace(" ", "")

$m = get-date
$month = $m.month  #получение месяца
$year = $m.year    #получение года

Примеры:- (теперь склеиваем всё это воедино)

#на основе даты
$log1 = ".\Processed\Logs" + "\" + "skipcsv_" + $date + "_.log"

#на основе месяца и года
$log2 = ".\Processed\Logs" + "\" + "Created_" + $month +"_" + $year +"_.log"

#на основе даты и времени
$output1 = ".\" + "G_Testlog_" + $date + "_" + $time + "_.csv"

[Замечание]
Замечание

Всегда определяйте свою текущую рабочую папку.

Манипуляция датами

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

Для получения первого и последнего дней месяца мы можем воспользоваться своим кодом из Листинга 2-2. За результатами обращайтесь к Рисунку 2-3.

Листинг 2-2. Код для извлечения первого и последнего дней месяца

$date= Get-Date -Day 01
$lastday = ((Get-Date -day 01).AddMonths(1)).AddDays(-1)

$start = $date
$end  = $lastday

Рисунок 2-4

Получение первого и последнего дней соответствующего месяца

Для получения штампа полуночи просто воспользуйтесь этой строкой кода (и посмотрите на Рисунок 2-4):

Get-Date -Hour 0 -Minute 0 -Second 0

Рисунок 2-4

Отображение того как получать отметку даты и времени полуночи

Создание папок на основе даты

В реальной жизни могут иметься случаи, при которых вы пожелаете создавать папки на основе текущей даты, например для создания ежедневной резервной копии конфигурации SharePoint и помещения её в папке с отметкой даты. Листинг 2-3 отображает тот код, которым можно воспользоваться для выполнения такой задачи, а Рисунок 2-5 отображает получаемые результаты.

Листинг 2-3. Код для создания структуры папок на основе даты

$Dname = ((get-date).AddDays(0).toString('yyyyMMdd')) #манипуляция с датой
$dirName = "ConfigBackup_$Dname"  #префикс для соответствующей папки

New-Item -Path c:\temp -Name $dirName -ItemType directory

Рисунок 2-5

Создание структуры папок на основе даты

Готовые функции даты и журнала

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

Функция Write-Log: Она пользуется другой функцией с названием New-FolderCreation, которую, если потребуется, можно применять отдельно. Просмотрите Листинг 2-4.

Листинг 2-4. Код функции Write-Log

function New-FolderCreation
{
  [CmdletBinding()]
  param
  (
    [Parameter(Mandatory = $true)]
    [string]$foldername
  )
  $logpath  = (Get-Location).path + "\" + "$foldername"
  $testlogpath = Test-Path -Path $logpath
  if($testlogpath -eq $false)
  {
    #Start-ProgressBar -Title "Creating $foldername folder" -Timer 10
    $null = New-Item -Path (Get-Location).path -Name $foldername -Type directory
  }
}#New-FolderCreation

function Write-Log
{
  [CmdletBinding()]
  param
  (
    [Parameter(Mandatory = $true,ParameterSetName = 'Create')]
    [array]$Name,
    [Parameter(Mandatory = $true,ParameterSetName = 'Create')]
    [string]$Ext,
    [Parameter(Mandatory = $true,ParameterSetName = 'Create')]
    [string]$folder,
    [Parameter(ParameterSetName = 'Create',Position = 0)][switch]$Create,
    [Parameter(Mandatory = $true,ParameterSetName = 'Message')]
    [String]$message,
    [Parameter(Mandatory = $true,ParameterSetName = 'Message')]
    [String]$path,
    [Parameter(Mandatory = $false,ParameterSetName = 'Message')]
    [ValidateSet('Information','Warning','Error')]
    [string]$Severity = 'Information',
    [Parameter(ParameterSetName = 'Message',Position = 0)][Switch]$MSG
  )
  switch ($PsCmdlet.ParameterSetName) {
    "Create"
    {
      $log = @()
      $date1 = Get-Date -Format d
      $date1 = $date1.ToString().Replace("/", "-")
      $time = Get-Date -Format t
      $time = $time.ToString().Replace(":", "-")
      $time = $time.ToString().Replace(" ", "")
      New-FolderCreation -foldername $folder
      foreach ($n in $Name)
      {$log += (Get-Location).Path + "\" + $folder + "\" + $n + "_" + $date1 + "_" + $time + "_.$Ext"}
      return $log
    }
    "Message"
    {
      $date = Get-Date
      $concatmessage = "|$date" + "|   |" + $message +"|  |" + "$Severity|"
      switch($Severity){
        "Information"{Write-Host -Object $concatmessage -ForegroundColor Green}
        "Warning"{Write-Host -Object $concatmessage -ForegroundColor Yellow}
        "Error"{Write-Host -Object $concatmessage -ForegroundColor Red}
      }
      Add-Content -Path $path -Value $concatmessage
    }
  }
} #Function Write-Log

Для создания файла журнала вы можете просто воспользоваться тем как это показано ниже (это автоматически создаст необходимые папки):

$log = Write-Log -Name "Name-Log" -folder "logs" -Ext "log"

Для создания файла CSV с целью отчётов вы можете применять его так:

$Report1 = Write-Log -Name "MAM-Report" -folder "Report" -Ext "csv"

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

Write-log -Message "Connect to Intune" -path $log

Для записи предостережений в файл журнала можно применять следующее:

Write-log -Message "Connect to Intune" -path $log -Severity Warning

Для записи ошибки в файл журнала вы можете воспользоваться этим:

Write-Log -Message "Error loading Modules" -path $log -Severity Error

Рисунок 2-6 показывает работу Write-Log в консоли PowerShell.

Рисунок 2-6

Операция Write-Log

Необходимый файл журнала создаётся в папке logs и будет создавать структурированный текстовый журнал, как это показано на Рисунке 2-7.

Рисунок 2-7

Созданный после применения функции Write-Log файл журнала

Функция Set-Recyclelogs: Будет удалять соответствующие файлы на основании числа дней в качестве входных данных. По мере накопления журналов со временем, имеется потребность для их отработки после определённого периода времени во избежание переполнения накопителей сервера. Это важно для любых сценариев, которым вы разрешили журналирование. Воспользуйтесь кодом из Листинга 2-5.

Листинг 2-5. Код для функции Set-Recyclelogs

function Set-Recyclelogs
{
  [CmdletBinding(
      SupportsShouldProcess = $true,
  ConfirmImpact = 'High')]
  param
  (
    [Parameter(Mandatory = $true,ParameterSetName = 'Local')]
    [string]$foldername,
    [Parameter(Mandatory = $true,ParameterSetName = 'Local')]
    [Parameter(Mandatory = $true,ParameterSetName = 'Path')]
    [Parameter(Mandatory = $true,ParameterSetName = 'Remote')]
    [int]$limit,

    [Parameter(ParameterSetName = 'Local',Position = 0)][switch]$local,

    [Parameter(Mandatory = $true,ParameterSetName = 'Remote')]
    [string]$ComputerName,
    [Parameter(Mandatory = $true,ParameterSetName = 'Remote')]
    [string]$DriveName,
    [Parameter(Mandatory = $true,ParameterSetName = 'Remote')]
    [string]$folderpath,

    [Parameter(ParameterSetName = 'Remote',Position = 0)][switch]$Remote,

    [Parameter(Mandatory = $true,ParameterSetName = 'Path')]
    [ValidateScript({
          if(-Not ($_ | Test-Path) ){throw "File or folder does not exist"}
          return $true
    })]
    [string]$folderlocation,

    [Parameter(ParameterSetName = 'Path',Position = 0)][switch]$Path

  )

  switch ($PsCmdlet.ParameterSetName) {
    "Local"
    {
      $path1 = (Get-Location).path + "\" + "$foldername"
      if ($PsCmdlet.ShouldProcess($path1 , "Delete"))
      {
        Write-Host "Path Recycle - $path1 Limit - $limit" -ForegroundColor Green
        $limit1 = (Get-Date).AddDays(-"$limit") #for report recycling
        $getitems = Get-ChildItem -Path $path1 -recurse -file | Where-Object {$_.CreationTime -lt $limit1}
        ForEach($item in $getitems){
          Write-Verbose -Message "Deleting item $($item.FullName)"
          Remove-Item $item.FullName -Force
        }
      }
    }

    "Remote"
    {
      $path1 = "\\" + $ComputerName + "\" + $DriveName + "$" + "\" + $folderpath
      if ($PsCmdlet.ShouldProcess($path1 , "Delete"))
      {
        Write-Host "Recycle Path - $path1 Limit - $limit" -ForegroundColor Green
        $limit1 = (Get-Date).AddDays(-"$limit") #for report recycling
        $getitems = Get-ChildItem -Path $path1 -recurse -file | Where-Object {$_.CreationTime -lt $limit1}
        ForEach($item in $getitems){
          Write-Verbose -Message "Deleting item $($item.FullName)"
          Remove-Item $item.FullName -Force
        }
      }
    }

   "Path"
    {
      $path1 = $folderlocation
      if ($PsCmdlet.ShouldProcess($path1 , "Delete"))
      {
        Write-Host "Path Recycle - $path1 Limit - $limit" -ForegroundColor Green
        $limit1 = (Get-Date).AddDays(-"$limit") #for report recycling
        $getitems = Get-ChildItem -Path $path1 -recurse -file | Where-Object {$_.CreationTime -lt $limit1}
        ForEach($item in $getitems){
          Write-Verbose -Message "Deleting item $($item.FullName)"
          Remove-Item $item.FullName -Force
        }
      }
    }
  }
}# Set-Recycle logs

Для отработки журналов старше 10 дней внутри вашей папки logs в текущем каталоге:

Set-Recyclelogs -foldername logs -limit 10

Воспользуйтесь confirm:$false во избежание подтверждений если вы уверены что вы хотите удалить эти файлы:

Set-Recyclelogs -foldername logs -limit 10 -confirm:$false

Для проверки того какие файлы удаляются применяйте verbose:

Set-Recyclelogs -foldername logs -limit 10 -confirm:$false -verbose

Когда ваш сценарий в другом каталоге, а вы хотите удалять журналы в иной структуре папок, вы можете задать значение пути:

Set-Recyclelogs -foldername logs -limit 10 -confirm:$false -verbose

Для отработки журналов в удалённой машине воспользуйтесь следующим синтаксисом:

Set-Recyclelogs -ComputerName testmachine -DriveName c -folderpath data\logs -limit 10

Функция Set-ProgressBar: Эта функция просто отображает планку исполнения, когда ы желаете установить паузу на некоторое время. Взгляните на Листинга 2-6 и Рисунок 2-8.

Листинг 2-6. Код для функции Start-ProgressBar

function Start-ProgressBar
{
  [CmdletBinding()]
  param
  (
    [Parameter(Mandatory = $true)]
    $Title,
    [Parameter(Mandatory = $true)]
    [int]$Timer
  )
  For ($i = 1; $i -le $Timer; $i++)
  {
    Start-Sleep -Seconds 1;
    Write-Progress -Activity $Title -Status "$i" -PercentComplete ($i /100 * 100)
  }
} #Function Start-ProgressBar

Start-ProgressBar -Title "Test timeout" -Timer 30

Рисунок 2-8

Полоска Start-ProgressBar с таймером в 30 секунд

Вы также можете применить простой таймаут, который является встроенным (смотрите Рисунок 2-9).

timeout 10

Рисунок 2-9

Встроенный командлет таймаута

Выводы

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

Глава 3. Входные данные вашего сценария

Содержание

Глава 3. Входные данные вашего сценария

Import-CSV

Импорт из текстового файла

Ввод из массива

Выводы

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

Import-CSV

Import-CSV является наиболее применяемым методом для предоставления сценария со считыванием файла CSV и он в дальнейшем будет применяться для выполнения пакетных операций при помощи цикла.

Для демонстрации давайте создадим небольшой файл CSV (сохраните его как samplecsv.csv) в показанном на Рисунке 3-1 формате и затем выведите на печать его содержимого. Для этого кода отсылаем вас к Листингу 3-1.

Рисунок 3-1

Пример файла CSV

Листинг 3-1. Код для Import-CSV

$data = import-csv c:\temp\samplecsv.csv    #Импорт CSV в переменную data
foreach ($i in $data) {
Write-host  $i.user -foregroundcolor green #вывод на печать столбца user
Write-host  $i.email -foregroundcolor yellow #вывод на печать столбца email
Write-host  $i.title -foregroundcolor magenta #вывод на печать столбца title
         }

Рисунок 3-2 отображает операцию Import-CSV в PowerShell. Если вы находитесь в той же самой папке, вы можете воспользоваться источником с точкой вместо полного пути, показанного в этом снимке экрана:

$data = import-csv .\samplecsv.csv # .\ обозначает текущий каталог

Рисунок 3-2

Демонстрация операции Import-CSV через источник с точкой (.\)

Импорт из текстового файла

Существуют ситуации при которых вы получаете данные в текстовом файле, таком как список серверов или перечень пользователей, по одному за раз, а вы хотите осуществить с этими данными определённую операцию.

Рисунок 3-3 показывает вывод на печать вашего экрана каждого сервера из файла с названием servers.txt. (Для считывания текстовых файлов применяется командлет Get-content; подробности в Листинге 3-2).

Рисунок 3-3

Пример содержимого текстового файла

Листинг 3-2. Код для считывания из текстового файла

$servers = Get-content .\servers.txt
$servers | foreach-object {
Write-host $_
}

Сохраните этот код в файле .ps1 и запустите его ил просто вставьте его в свою консоль PowerShell. Обратите внимание на Рисунок 3-4.

Рисунок 3-4

Операция считывания текстового файла в PowerShell

Ввод из массива

Вы можете выполнять те же самые вещи с массивом, которые вы совершили с текстовым файлом. Скажем, у вас есть массив серверов и вы хотите вывести их на печать в своём экране. Отсылаем вас к Листингу 3-3.

Листинг 3-3. Код для считывания из массива и вывод его на печать

$servers = @("server01","server02","server03","server04")
#array of servers
$servers | foreach-object {
Write-host $_ -foregroundcolor yellow
}

Выполнение этого сценария показывает результаты на Рисунке 3-5.

Рисунок 3-5

Отображение печати массива

Выводы

В этой главе вы изучили как запитывать сценарии входными данными либо из текстового файла, либо из файла CSV, или из массива. Имеются современные способы для ввода в ваши сценарии, однако те способы, которые упомянуты в этой главе распространены и применяются повседневно в мире системного администрирования.

Глава 4. Интерактивный ввод

Содержание

Глава 4. Интерактивный ввод

Read-host

Параметры

Кнопка графического интерфейса

Приглашение на ввод (Yes или No)

Выводы

Данная глава снабдит вас примерами, в которых вы можете добавлять в свои сценарии интерактивный ввод (то есть сам сценарий запросит ввод, например, набор пароля или иного атрибута, такого как путь к файлу CSV или текста).

Read-host

Вы уже применяли Write-host для вывода на печать в своём экране значения. Теперь вы можете воспользоваться Read-host для получения значений, которые пребывают во вводе пользователя с его экрана:

$x =Read-host "input your Name"

Получаемое из вашего ввода значение сохраняется в переменной $x с тем, чтобы вы могли применять его в своём сценарии для дальнейшей обработки, как это показано на Рисунке 4-1.

Рисунок 4-1

Операция Read-host

Другим вариантом является определение использования параметра -prompt. Нет никакой разницы в том как вы применяете это. Посмотрите на Рисунок 4-2.

$x =Read-host "input your Name"

Рисунок 4-2

Операция Read-host, предписывающая -prompt

Когда вы хотите безопасно вводить пароль, применяется -assecurestring:

$Password = Read-Host -assecurestring "Enter your password"

Здесь значение введённого пароля также сохраняется в переменной $Password, которую вы можете применять в своём сценарии для последующей обработки, например, для аутентификации в какой- либо службе, скажем в Office 365. Смотрите на Рисунок 4-3.

Рисунок 4-3

Операция Read-host для пароля в качестве входного параметра

Параметры

В команде PowerShell функции это сценарии, которые полагаются на параметры с тем, чтобы пользователь мог либо вводить значения или выбирать варианты. Я кратко затрону основы параметризации (Расширенные параметры выходят за рамки этой книги). Обратитесь к Листингу 4-1.

Листинг 4-1. Пример кода, показывающий применение параметров

Param(
  [string]$firstname,
  [string]$lastname,
  [string]$title
)
Write-host "First Name: $firstname" -ForegroundColor Yellow
Write-host "Last Name: $lastname" -ForegroundColor Yellow
Write-host "Title: $Title" -ForegroundColor green

Сохраните это в неком файле .ps1 и запустите его следующим образом (и посмотрите на Рисунок 4-4):

.\script.ps1 -firstname Vikas -lastname sukhija -title blogger

Рисунок 4-4

Исполнение сценария с параметрами

[Совет]
Совет

Убедитесь что вы определили параметры в самом начале своего сценария.

Кнопка графического интерфейса

Здесь приводится код шпаргалки (функцию) для того случая, когда вы желаете интерактивно выполнять ввод в определённой форме графического интерфейса пользователя. Я рассматриваю это причудливым вариантом получения сведений от пользователя. Функция кнопки из Листинга 4-2 может получать входные данные из формы Windows, которые вы можете отображать на экране или выполнять другие необходимые операции в своём сценарии.

Листинг 4-2. Код для ввода из кнопки графического интерфейса

function button ($title,$mailbx, $WF, $TF)
{
  ###################Загружаем сборку для создания формы и кнопки######
  [void][System.Reflection.Assembly]::LoadWithPartialName( "System.Windows.Forms")
  [void][System.Reflection.Assembly]::LoadWithPartialName( "Microsoft.VisualBasic")
  #####Определяем размер и положение формы
  $form = New-Object "System.Windows.Forms.Form";
  $form.Width = 500;
  $form.Height = 150;
  $form.Text = $title;
  $form.StartPosition = [System.Windows.Forms.FormStartPosition]::CenterScreen;
  ##############Определяем текст label1
  $textLabel1 = New-Object "System.Windows.Forms.Label";
  $textLabel1.Left = 25;
  $textLabel1.Top = 15;
  $textLabel1.Text = $mailbx;
  ##############Определяем текст label2
  $textLabel2 = New-Object "System.Windows.Forms.Label";
  $textLabel2.Left = 25;
  $textLabel2.Top = 50;
  $textLabel2.Text = $WF;
  ##############Определяем текст label3
  $textLabel3 = New-Object "System.Windows.Forms.Label";
  $textLabel3.Left = 25;
  $textLabel3.Top = 85;
  $textLabel3.Text = $TF;
  ############Определяем текст box1 для ввода
  $textBox1 = New-Object "System.Windows.Forms.TextBox";
  $textBox1.Left = 150;
  $textBox1.Top = 10;
  $textBox1.width = 200;
  ############Определяем текст box2 для ввода
  $textBox2 = New-Object "System.Windows.Forms.TextBox";
  $textBox2.Left = 150;
  $textBox2.Top = 50;
  $textBox2.width = 200;
  ############Определяем текст box3 для ввода
  $textBox3 = New-Object "System.Windows.Forms.TextBox";
  $textBox3.Left = 150;
  $textBox3.Top = 90;
  $textBox3.width = 200;
  #############Определяем значения по умолчанию для блоков ввода
  $defaultValue = ""
  $textBox1.Text = $defaultValue;
  $textBox2.Text = $defaultValue;
  $textBox3.Text = $defaultValue;
  #############Определяем кнопку OK
  $button = New-Object "System.Windows.Forms.Button";
  $button.Left = 360;
  $button.Top = 85;
  $button.Width = 100;
  $button.Text = "Ok";
  ############# Именно здесь мы закрываем форму после получения значений
  $eventHandler = [System.EventHandler]{
    $textBox1.Text;
    $textBox2.Text;
    $textBox3.Text;
    $form.Close();
  };
  $button.Add_Click($eventHandler) ;
  #############Добавляем управление для всех определённых выше объектов
  $form.Controls.Add($button);
  $form.Controls.Add($textLabel1);
  $form.Controls.Add($textLabel2);
  $form.Controls.Add($textLabel3);
  $form.Controls.Add($textBox1);
  $form.Controls.Add($textBox2);
  $form.Controls.Add($textBox3);
  $ret = $form.ShowDialog();
  #################возвращаем значения
  return $textBox1.Text, $textBox2.Text, $textBox3.Text
} #button

Загружаем эту функцию в ваш сценарий и затем вы можете выполнять необходимые свои операции по вводу как показано здесь:

$return= button "Enter Folders" "Enter mailbox" "Working Folder" "Target Folder"

Вы можете выбирать различные названия для своих требований. Обратите внимание на Рисунок 4-5.

Рисунок 4-5

Ввод кнопкой графического интерфейса

После того как вы нажмёте кнопку OK, ваша переменная $return содержит все эти значения в своём массиве (смотрите Рисунок 4-6):

$return[0] → Enter mailbox value
$return[1] → Working folder value
$return[2] → Target Folder value

Рисунок 4-6

Отображение значений, возвращённых из ввода пользователя

Вы также можете вывести на печать своего экрана точно также как это показано ранее (смотрите Рисунок 4-7):

Write-host "Enter mailbox : $($return[0])" -ForegroundColor Yellow
Write-host "Working folder : $($return[1])" -ForegroundColor Yellow
Write-host "Target Folder : $($return[2])" -ForegroundColor green

Рисунок 4-7

Вывода на печать значений с применением Write-host

Приглашение на ввод (Yes или No)

Встречаются практические ситуации когда вам в качестве системного администратора желательно построить симпатичный способ получения отклика Yes/No от своих пользователей. Вы можете запросто выполнять это в PowerShell применяя код шпаргалки из Листинга 4-3.

Листинг 4-3. Код для операции Yes/No

$overwrite = New-Object -comobject wscript.shell

$Answer = $overwrite.popup("Do you want to Overwrite AD Attributes?",0,"Overwrite Attributes",4)

If ($Answer -eq 6) {Write-Host "you pressed Yes" -ForegroundColor Green}
else{Write-Host "you pressed Yes" -ForegroundColor Red}

Скопируйте этот код и вставьте его в свою консоль PowerShell или сохраните этот сценарий в качестве файла .ps1и исполните его. Смотрите Рисунок 4-8.

Рисунок 4-8

Отображение операции Yes/No в PowerShell

Когда вы наживаете Yes, вы получаете результат, отображаемый на Рисунке 4-9.

Рисунок 4-9

Отображение значения Yes операции

Если вы наживаете No, вы получаете результат, показанный на Рисунке 4-10.

Рисунок 4-10

Отображение значения No операции

Вместо простого Write-host вы можете внутри своего сценария выполнять другие операции на основании получаемого отклика, выбираемого вашим пользователем.

Выводы

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

Глава 5. Добавление оснасток/ модулей

Содержание

Глава 5. Добавление оснасток/ модулей

Оснастки PowerShell

Модули

Модуль шпаргалки (vsadmin)

Шифрование пароля (vsadmin)

Выводы

Microsoft и прочие сторонние построили оснастки или модули PowerShell для своих собственных разнообразных продуктов. Для применения командлетов PowerShell с этими технологиями вам придётся в свои сценарии либо добавлять их оснастки, либо импортировать их модули.

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

Хотя оснастки и наследуются, давайте кратко затронем и их, отобразив те продукты, которые применяют (применяли) их.

Оснастки PowerShell

Exchange Sever сам по себе является наилучшим примером демонстрации оснасток PowerShell. Exchange 2007 и 2010, оба, пользуются оснастками.

Для добавления оснастки Exchange в свои сценарии, вы можете применять приводимый ниже код. (Примеры оснасток Exchange 2007 и 2010 находятся, соответственно, в Листинге 5-1 и в Листинге 5-2). Поскольку эти продукты официально завершили состояние своего срока поддержки, их применение достаточно редкое (они применимы лишь для организаций, которые ещё пока не обновились).

[Замечание]
Замечание

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

Листинг 5-1. Код для добавления оболочки управления Exchange 2007

If ((Get-PSSnapin | where {$_.Name -match "Exchange.Management"}) -eq $null)
{
       Add-PSSnapin Microsoft.Exchange.Management.PowerShell.Admin
}

Листинг 5-2. Код для добавления оболочки управления Exchange 2010

If ((Get-PSSnapin | Where-Object { $_.Name -match "Microsoft.Exchange.Management.PowerShell.E2010" }) -eq $null) {
    Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010
}

После того как оснастка была добавлена в ваши сеанс или сценарий, она способна исполнять команды Exchange внутри своего окна, как это показано на Рисунке 5-1.

Рисунок 5-1

Оболочка управления Exchange

Вы также можете воспользоваться в своём окне PowerShell get-pssnapin для проверки того, какие оснастки доступны.

На Рисунке 5-2 я хочу воспользоваться имеющимся преимуществом оболочки Quest, поэтому я применяю get-pssnapin в оболочке Quest AD для выявления названия соответствующей оснастки.

Рисунок 5-2

Оболочка управления Quest AD

Листинг 5-3 показывает как добавлять соответствующую оснастку в ваш сценарий PowerShell или в сеанс при помощи той же самой технологии что и для продукта Exchange.

Листинг 5-3. Код для добавления оболочки управления Quest AD

If ((Get-PSSnapin | where {$_.Name -match "Quest.ActiveRoles"}) -eq $null)
{
    Add-PSSnapin Quest.ActiveRoles.ADManagement
}

[Замечание]
Замечание

Приведённый выше код добавления оснастки сначала проверяет не имеется ли уже эта оснастка. Если это так, он ничего не выполняет. В противном случае он добавляет необходимую оснастку.

Модули

Теперь давайте рассмотрим модули, поскольку именно с ними мы будем иметь дело в своей повседневной работе. Согласно Microsoft, "модуль это пакет, который содержит участников PowerShell, таких как, командлеты, поставщиков, рабочие потоки, переменные и синонимы. Все участники этого пакета могут реализовываться в неком сценарии PowerShell, скомпилированном DLL или в комбинации обоих. Эти файлы обычно совместно группируются в неком отдельном каталоге."

В языке программирования PowerShell нам требуются модули для взаимодействия с различными продуктами, такими как Azure, Office 365, Exchange Online и тому подобными.

Gallery PowerShell по- существу это репозиторий, который содержит почти все модули, которые может применять всякий.

Для установки модуля в вашей машине из Gallery PowerShell, воспользуйтесь таким кодом:

Install-Module -Name AzureAD

Введите yes (как это показано на Рисунке 5-3), когда получите приглашение на установку необходимого модуля.

Рисунок 5-3

Установка из модуля PowerShell Gallery

После установки этого модуля в вашей машине, он сохранится в C:\Program Files\WindowsPowerShell\Modules, как это отображено на Рисунке 5-4.

Рисунок 5-4

Путь к модулям в вашем компьютере

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

Update-Module -Name AzureAD

или

Install-Module -Name AzureAD -force #(она также обновит ваш модуль до последней версии)

При помощи update вы можете к тому же обновлять свой модуль до определённой версии:

Update-Module -Name AzureAD -RequiredVersion 1.0.1

Удаление соответствующего модуля это простая операция и она может выполняться как показывает следующий командлет:

Remove-Module AzureAD

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

[Замечание]
Замечание

После powerShell V3 модули загружаются автоматически после того как в вашем сценарии запускается самый первый командлет из этого модуля.

Вы всё ещё можете практиковать импорт необходимых модулей в своём сценарии перед исполнением команды:

Import-Module AzureAD

Для получения всех установленных в вашей машине модулей вы можете воспользоваться приводимым ниже кодом (его результаты отображены на Рисунке 5-5):

Get-Module -ListAvailable

Рисунок 5-5

Отображение списка модулей, доступных в вашем компьютере

Модуль шпаргалки (vsadmin)

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

   Название модуля: vsadmin
   Установка модуля (см. Рисунок 5-6:
Install-Module -Name vsadmin

Рисунок 5-6

Установка модуля vsadmin

После его установки вы обнаружите файлы, созданные внутри вашего каталога модуля (C:\Program Files\WindowsPowerShell\Modules), как это отображено на Рисунке 5-7.

Рисунок 5-7

Отображение файлов внутри модуля vsadmin

Как постулировалось, вы можете импортировать этот модуль в свой сеанс при помощи import-module как- то так:

import-module vsadmin

Рисунок 5-8 показывает доступные внутри полученного модуля vsadmin команды. Вы можете пользоваться приводимой ниже командой для проверки функций и командлетов в любом модуле:

Рисунок 5-8

Доступные команды модуля vsadmin

Давайте изучим функции Office 365, а затем вы переместитесь к прочим функциям системного администратора, которые вы можете применять ежедневно.

LaunchEOL/RemoveEOL (Exchange Online)

LaunchSOL/RemoveSOL (Skype Online)

LaunchSPO/RemoveSPO (SharePoint Online)

LaunchCOL/RemoveCOL (Security и Compliance)

LaunchMSOL/RemoveMSOL (MSonline Azure Active Directory)

LaunchEXOnprem/RemoveEXOnprem (для сервера Exchange на площадке)

Три функции из office 365 снабжены префиксом с тем, чтобы они не конфликтовали с командами на площадке и быстро применялись/ распознавались в неком гибридном сценарии. Например, команда Exchange Online get-mailbox это get-EOLmailbox, если вы применяете этот модуль для её запуска, как это показано позднее.

[Замечание]
Замечание

Для функций office 365 необходимы следующие естественные модули office 365 в модуле vsadmin, чтобы он заработал, или же он запросит их установку.

ExchangeOnlineManagement

Sharepoint Online

MSOnline Module

Все командлеты пребывают в модуле команды Skype Online (Retired)

Например, когда вы хотите подключиться к Office 365 Exchange online, вы можете воспользоваться LaunchEOL, она выдаст приглашение для авторизации и, после таковой, вы получите подключение. Здесь также выполнится проверка установлена ли в вашем компьютере или нет оболочка управления Exchange Online. Если её нет, вы получите подсказку. Обратите внимание на Рисунок 5-9.

Рисунок 5-9

Приглашение на аутентификацию из Office 365

Рисунок 5-10 показывает вам что вы подключены и можете применять команды Exchange.

Рисунок 5-10

Оболочка управления Exchange Online с командой Get-MailBox в префиксе

Если вы хотите воспользоваться этими командами а сценарии без ввода всякий раз пароля (техника, которой вы обучитесь по завершению данной книги), можно воспользоваться LaunchEOL -Credential передавая полномочия PS.

Аналогичным образом вы можете применять прочие функции, потому как они разработаны подобно. Например, воспользуйтесь этим кодом и просмотрите его результаты на Рисунке 5-11.

LaunchSPO –orgName techwizard

Рисунок 5-11

Отображение подключения к SharePoint Online при помощи LaunchSPO

[Совет]
Совет

Нажатие Tab на клавиатуре после нажатия дефиса отобразит вам те параметры, которые требуются для любой функции в PowerShell.

Для отключения от сеанса вы можете применять следующие функции: RemoveEOL/ RemoveSOL/ RemoveSPO и т.д..

Другими хорошими функциями, которые на самом деле нравятся системным администраторам выступают функции LaunchEXOnprem/ RemoveEXOnprem, поскольку они предназначены для серверов Exchange на площадке. Для подключения к некому серверу Exchange с площадки в своей сетевой среде воспользуйтесь таким кодом:

LaunchEXOnprem -psurl http://exchangeserver.techwizard.cloud/Powershell

или

LaunchEXOnprem -ComputerName exchangeserver.techwizard.cloud

Для отключения воспользуйтесь той же самой техникой что и для функций Office 365:

RemoveEXOnprem -computername exchangeserver.techwizard.cloud

Давайте теперь обсудим общие функции внутри данного модуля. В Главе 2 мы уже делились функциями Write-Log, Set-recyclelogs и start-progressbar, а также прочими. Эти функции также выступают частью данного модуля, а потому вам не следует копировать их и вставлять в свои сценарии когда вы импортировали данный модуль в свой сценарий. Просмотрите Листинг 5-4 и Рисунок 5-12.

Листинг 5-4. Импорт vsadmin и применение функции Write-Log

Import-Module vsadmin
$log = Write-Log -Name "log_file" -folder logs -Ext log
Write-Log -Message "Information..........Script" -path $log  #default  will log as information
Write-Log -Message "warning.........Message" -path $log -Severity Warning #you can display warning using the severity
Write-Log -Message "error.........Error" -path $log -Severity error #you can display error using the severity

Рисунок 5-12

Отображение результатов исполнения Листинга 5-4

Аналогичным образом вы можете создавать файл CSV:

$report = Write-Log -Name "log_Enable" -folder reports -Ext csv

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

Шифрование пароля (vsadmin)

Вы можете применять пароль и позднее применять его в своём сценарии для подключения к интернет службам, таким как Office 365 и Azure следующим образом (для результатов этого обратитесь к Рисунку 5-13):

Save-EncryptedPassword -password "testpassword" -path c:\temp\password1.txt

Рисунок 5-13

Шифрование пароля с применением команды save-encrypted

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

$cred = get-auth -userId sukhija@techwizard.cloud -passwordfile c:\temp\password1.txt
$pwd = $cred[0] ### полномочия, которые могут применяться внутри вызовов csom /api.
$pscredential = $cred[1] ###полномочия, которые могут применяться для функций, которые поддерживают полномочия ps.

или

$cred = get-auth -userId sukhija@techwizard.cloud -password  "encryptedpassword"
$pwd = $cred[0] ### полномочия, которые могут применяться внутри вызовов csom /api.
$pscredential = $cred[1] ###полномочия, которые могут применяться для функций, которые поддерживают полномочия ps.

Давайте воспользуемся фрагментом кода шпаргалки для подключения к Office 365 при помощи сохранённых в вашем файле полномочий PS и экспорту отчёта CSV в почтовые ящики. (Его можно видоизменить и запускать по расписанию по мере необходимости). Смотрите Листинг 5-5 и Рисунок 5-14.

Листинг 5-5. Код отображения применения полномочий PS

Import-Module vsadmin

$cred = get-auth -userId sukhija@techwizard.cloud -passwordfile "c:\temp\password1.txt"  #getcredentials that you created using Save-EncryptedPassword
$pscredential = $cred[1] ###полномочия, которые могут применяться для функций, которые поддерживают полномочия ps.

LaunchEOL -Credential $pscredential
$data = Get-EOLMailbox -ResultSize unlimited | Select Name,WindowsEmailAddress,IssueWarningQuota, ProhibitSendQuota,ProhibitSendReceiveQuota #fetch the required data from exchange online

$data | Export-Csv "c:\temp\mailboxes.csv" -NoTypeInformation #export the data in csv format
RemoveEOL #отключаем свой обмен интернет сеанса

Рисунок 5-14

Экспорт данных соответствующих почтовых ящиков в файл CSV

Для считывания файлов ini пользуйтесь Get-IniContent , а затем применяйте в сценариях полученные значения. Смотрите Рисунок 5-15.

Рисунок 5-15

Пример файла INI

На Рисунке 5-16 вы можете разглядеть пример следующего кода:

$inifile = "c:\temp\config.ini"
$readini = Get-IniContent $inifile
$User = $readini["ServiceAccount"].UserID

Рисунок 5-16

Отображение того, как считывать файл INI при помощи команды GetIniContent

Другой полезной функцией для ежедневного применения является Save-CSV2Excel. Как можно догадаться из её названия, она преобразовывает файл CSV в форматированный Excel:

Save-CSV2Excel -CSVPath C:\data\auditmbx.csv -Exceloutputpath c:\data\audit.xlsx

Существенными в мире системного администратора являются случайным образом вырабатываемые сложные пароли. Итак, зачем применять Web или некий инструмент для их выработки когда вы можете выполнить это при помощи своей функции New-RandomPassword из нашего модуля vsadmin? Рассмотрите это пример на Рисунке 5-17:

New-RandomPassword – NumberofChars 9

Он кодируется при помощи 5, 9, 14 и 20.

Рисунок 5-17

Отображение выработки пароля случайным образом

И последнее, но не по степени значимости, я делюсь некоторыми функциями Active Directory, которые не доступны сразу после установки модуля Active Directory.

Get-ADGroupMembersRecursive способна рекурсивно выделять участников групп, однако требуется и сам модуль AD:

Get-ADGroupMembersRecursive -Groups "Test Nested Group"

Дополнительно с этой функцией вы можете ознакомиться на https://techwizard.cloud/2020/10/24/get-ad-group-members-recursively/.

Get-ADUserMemberOf способна проверять является ли некий пользователь участником группы или нет, но при этом требуется сам модуль AD:

Get-ADUserMemberOf -User "User" -Group "Group"

Она возвращает true когда указанный пользователь участник группы или в противном случае она возвращает false. Дополнительно с этой функцией вы можете ознакомиться на https://techwizard.cloud/2020/12/31/check-if-ad-user-is-member-of-group/.

Выводы

В данной главе вы изучили как применять модули в PowerShell. Модули, они как батарейки. Без их сложно составлять сценарий любого продукта при помощи PowerShell. Я также поделился модулем шпаргалки системного администратора (vsadmin), который обладает большим числом ежедневно применяемых функций/ командлетов.

Глава 6. Отправка электронной почты

Содержание

Глава 6. Отправка электронной почты

Форматирование тела письма

Отправка HTML

Выводы

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

PowerShell обладает простым и действенным командлетом после своей установки для такой цели прямо начиная с версии PowerShell v2. Ниже приводится образец Send-MailMessage, который преобладает в PowerShell:

Send-MailMessage -SmtpServer "smtpserver" -From "DoNotReply@labtest.com" -To "sukhija@techwizard.cloud " -Subject "Error exception occured " -Body "body of the message"

Если вы всё ещё пользуетесь PowerShell 1.0 (что крайне маловероятно), вы можете воспользоваться приводимым в Листинге 6-1 кодом, который работает во всех версиях PowerShell.

Листинг 6-1. Отправка сообщения при помощи Powershell v1

$smtpserver = "smtp.lab.com"
$to = "sukhija@techwizard.cloud"
$from = "DonotReply@labtest.com"
$file = "c:\file.txt" #for attachment
$subject = "Test Subject"

$message = new-object Net.Mail.MailMessage
$smtp = new-object Net.Mail.SmtpClient($smtpserver)
$message.From = $from
$message.To.Add($to)

$att = new-object Net.Mail.Attachment($file)
$message.IsBodyHtml = $False
$message.Subject = $subject
$message.Attachments.Add($att)
$smtp.Send($message)

Форматирование тела письма

Существуют обстоятельства, при которых вы желаете отправлять должным образом отформатированное тело электронного письма вместо простого электронного письма в одну строчку. Для этой цели вы можете воспользоваться кодом шпаргалки из Листинга 6-2. Полученный результат вы можете обнаружить на Рисунке 6-1.

Листинг 6-1. Отправка сообщения при помощи Powershell v1

$smtpserver = "smtp.lab.com"
$to = "sukhija@techwizard.cloud"
$from = "DonotReply@labtest.com"
$subject = "Test Subject"

$message = @"
Hello,

Line............................1

Line............................2

Line............................3

"@
Send-MailMessage -SmtpServer $smtpserver -From $from -To $to -Subject $subject -Body $message

Рисунок 6-1

Результат Листинга 6-1

Отправка HTML

Если вы воспользуетесь другой шпаргалкой подсказки при помощи PowerShell вы способны отправлять симпатичные электронные письма HTML, даже когда вы не знакомы с HTML. Для создания необходимого HTML зарегистрируйтесь в интернет редакторе HTML (показанном на Рисунке 6-2): https://html-online.com/editor/.

Рисунок 6-2

Интернет редактор HTML

Создайте некое содержимое HTML и воспользуйтесь кодом из Листинга 6-2. Вы можете рассмотреть получаемые результаты на на Рисунке 6-3

Листинг 6-2. Отправка отформатированного HTML электронного сообщения

$smtpserver = "smtp.lab.com"
$to = "sukhija@techwizard.cloud"
$from = "DonotReply@labtest.com"
$subject = "Test Subject"

$message = @"
<!-- #######  YAY, I AM THE SOURCE EDITOR! #########-->
<h1 style="color: #5e9ca0;">You can edit <span style="color: #2b2301;">this demo</span> text!</h1>
<h2 style="color: #2e6c80;">How to use the editor:</h2>
<p>Paste your documents in the visual editor on the left or your HTML code in the source editor in the right. <br />Edit any of the two areas and see the other changing in real time.&nbsp;</p>
<p>&nbsp;</p>
"@

Send-MailMessage -SmtpServer $smtpserver -From $from -To $to -Subject $subject -Body $message -BodyAsHtml

Рисунок 6-3

Результат Листинга 6-2

Выводы

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

Глава 7. Отчёты об ошибках

Содержание

Глава 7. Отчёты об ошибках

Отчёты об ошибках по электронной почте

Регистрация всего содержащего ошибки

Регистрация ошибок в текстовый файл

Выводы

для успешного составления сценариев обработка ошибок это то, что необходимо иметь. Когда имеется некая ошибка, вы желаете получить по ней отчёт для своего администратора или владельца соответствующими процессом/ автоматизацией. PowerShell обладает различными способами выполнения отчётов об ошибках. Наиболее распространённым выступает переменная $error, поскольку она содержит все те ошибки, которые произошли в вашем сеансе. Давайте рассмотрим некие образцы шпаргалок кода, которыми вы можете воспользоваться. Вы можете заносить ошибки в журнал, либо отправлять их электронной почтой.

Отчёты об ошибках по электронной почте

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

$error это переменная по умолчанию в PowerShell, которая содержит имеющуюся ошибку в случае её возникновения при исполнении вашего кода. В Листинге 7-1 вы проверяете что $error не равняется нулю и затем отправляете свою ошибку электронным письмом.

После отправки электронного письма об этой ошибке, если вы желаете очистить свои ошибки, вы можете воспользоваться $error.clear() с тем, чтобы если у вас применяются итерации, эта ошибка не отправлялась бы снова, когда она не происходит при вашем следующем повторе.

Листинг 7-1. Отправка ошибок электронным письмом

$from = "donotreply@lab.com"
$to="vikas@lab.com"
$subject = "Error has occured"
$smtpServer="smtp.lab.com"

if ($error)
      {
Send-MailMessage -SmtpServer $smtpserver -From $from -To $to -Subject $subject -Body $error[0].ToString()
$error.clear()
       }

Листинг 7-1 упускает один важный момент. Он просто отправляет самую последнюю ошибку, однако что если вы хотите отправить всю ошибку целиком, которая на самом деле это некий массив и send-mailmessage не способен отправить её действенным образом? Вы можете воспользоваться функцией Send-Email из Листинга 7-2, которая также является частью модуля vsadmin, которым мы поделились в своей главе о модулях.

Листинг 7-2. Функция Send-Email для отправки массива $error

function Send-Email
{
  [CmdletBinding()]
  param
  (
    [Parameter(Mandatory = $true)]
    $From,
    [Parameter(Mandatory = $true)]
    [array]$To,
    [array]$bcc,
    [array]$cc,
    $body,
    $subject,
    $attachment,
    [Parameter(Mandatory = $true)]
    $smtpserver
  )
  $message = New-Object System.Net.Mail.MailMessage
  $message.From = $From
  if ($To -ne $null)
  {
    $To | ForEach-Object{
      $to1 = $_
      $to1
      $message.To.Add($to1)
    }
  }
  if ($cc -ne $null)
  {
    $cc | ForEach-Object{
      $cc1 = $_
      $cc1
      $message.CC.Add($cc1)
    }
  }
  if ($bcc -ne $null)
  {
    $bcc | ForEach-Object{
      $bcc1 = $_
      $bcc1
      $message.bcc.Add($bcc1)
    }
  }
  $message.IsBodyHtml = $true
  if ($subject -ne $null)
  {$message.Subject = $subject}
  if ($attachment -ne $null)
  {
    $attach = New-Object Net.Mail.Attachment($attachment)
    $message.Attachments.Add($attach)
  }
  if ($body -ne $null)
  {$message.body = $body}
  $smtp = New-Object Net.Mail.SmtpClient($smtpserver)
  $smtp.Send($message)

После того как вы импортировали необходимую функцию из Листинга 7-2, вы можете воспользоваться кодом из Листинга 7-3, который аналогичен коду в Листинге 7-1. Единственным изменением является применение Send-Email вместо встроенного Send-MailMessage.

Листинг 7-3. Отправка массива $error электронным письмом

$from = "donotreply@lab.com"
$to="vikas@lab.com"
$subject = "Error has occured"
$smtpServer="smtp.lab.com"

if ($error)
      {
  Send-Email -smtpserver $smtpServer -From $from -To $to -subject $subject -body $error
  $error.clear()
       }

Регистрация всего содержащего ошибки

Существует некий встроенный командлет PowerShell, которым вы можете воспользоваться в самом начале своего сценария и остановить его в самом конце этого сценария. Это часто носит название журналирования интерпретации (transcript).

Start-transcript # в самом начале вашего сценария
Stop-transcript # в самом конце вашего сценария

Данный журнал будет по умолчанию сохраняться в папке My Documents учётной записи исполнения. Для сохранения этой интерпретации в ином месте вы можете определить значение пути, как это показано на Рисунке 7-1.

$log = "c:\data\log.txt"
Start-transcript -path $log # в самом начале вашего сценария
Stop-transcript # в самом конце вашего сценария

Рисунок 7-1

Отображение журнала интерпретации в PowerShell

Регистрация ошибок в текстовый файл

Вы также можете регистрировать ошибки в неких текстовых файлах. Это шпаргалочное руководство описывает функцию Write-Log; то же самое можно применять для регистрации ошибок в текстовых файлах. Получаемые результаты отображаются на Рисунке 7-2.

$log = Write-Log -Name "Errorlog" -folder "logs" -Ext "log"
write-log -message "error is $error" -path $log -Severity error

Рисунок 7-2

Отображение регистрируемых в текстовом файле ошибок

Выводы

В этой главе мы изучили как выдавать отчёт об ошибках при их возникновении, как их записывать в файлы регистрации, как их отправлять при помощи электронных писем и как перехватывать весь сеанс PowerShell целиком при помощи командлета start-transcript.

Глава 8. Отчёты

Содержание

Глава 8. Отчёты

Отчёт CSV

Отчёт Excel

Отчёт HTML

Выводы

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

Отчёты могут предоставляться в виде CSV, HTML, Excel и прочего. Наиболее распространённой формой отчёта выступает отчёт CSV по причине своей универсальности и способности преобразования в иные виды, например в Excel из самого приложения.

Отчёт CSV

Export-CSV это встроенный командлет PowerShell, которым можно пользоваться для экспорта необходимых сведений в файл CSV. Вы можете просто выбрать конвейер и затем экспортировать, как это показано в приводимом далее коде, который отображает экспорт определённых атрибутов почтовых ящиков пользователя из Exchange Server (что следует исполнять в оболочке Exchange):

Get-Mailbox -ResultSize unlimited | Select Name,identity, WindowsEmailAddress,Database,ProhibitSendQuota,ProhibitSendReceiveQuota,IssueWarningQuota | export-csv c:\mailboxes.csv -notypeinfo

Имеется множество сложных обстоятельств, при которых вам требуется записывать код сценария в формате необходимых данных правильным образом. Листинг 8-1 и Рисунок 8-1 отображают ту, когда у вас имеется перечень пользователей в неком текстовом файле и вы желаете экспортировать их атрибуты Active Directory и некоторые из атрибутов Exchange в файл CSV. В таком случае, не возможны get, select и export. Данный код может применяться во всех тех случаях, когда вы хотите экспортировать необходимые данные в соответствующую форму CSV, но простая операция не возможна.

Вы желаете воспользоваться атрибутами Name, identity, WindowsEmailAddress, Database, ProhibitSendQuota, ProhibitSendReceiveQuota и IssueWarningQuota, а также атрибутами employeeid, l, C из Active Directory.

[Замечание]
Замечание

Требуются оба модуля, и Exchange, и AD. Вам необходимо соединение с ними. Если они не загружены, этот сценарий завершится неудачей.

Для их загрузки воспользуйтесь познаниями из предыдущих глав.

Загрузите оболочку Exchange площадки при помощи vsadmin launchexonprem:

LaunchEXOnprem -ComputerName ExchangeServer

Для Active Directory вы можете применить

Import-Module Activedirectory

Листинг 8-1. Экспорт в CSV при выборке из множества источников

$collection=@() #массив для сборки данных отчёта
$data = get-content .\users.txt #read samaccountname from text file
$data | foreach-object{
  $coll = "" | Select Name,identity,WindowsEmailAddress,Database,ProhibitSendQuota,ProhibitSendReceiveQuota,IssueWarningQuota,employeeid, l,C  #необходимые в отчёте значения

  $getmbx = get-mailbox -identity $_
  $getaduser = get-aduser -identity $_ -properties employeeid, l,C
  $coll.Name = $getmbx.Name
  $coll.identity = $getmbx.identity
  $coll.WindowsEmailAddress = $getmbx.WindowsEmailAddress
  $coll.Database= $getmbx.Database
  $coll.ProhibitSendQuota = $getmbx.ProhibitSendQuota
  $coll.ProhibitSendReceiveQuota = $getmbx.ProhibitSendReceiveQuota
  $coll.IssueWarningQuota = $getmbx.IssueWarningQuota
  $coll.employeeid = $getaduser.employeeid #note difference here
  $coll.l = $getaduser.l
  $coll.c = $getaduser.c
  $collection+=$coll #add the collected values to the collecttion array
}
#теперь выполняем экспорт в файл CSV
$collection | Export-Csv .\report.csv -NoTypeInformation

Рисунок 8-1

Отображение результатов выполнения Листинга 8-1

Другой важной стороной отчёта CSV выступает экспорт атрибутов со множеством значений. Вот некий образец выделения получателя (который является атрибутом со множеством значений) в журналах отслеживания Exchange:

@{Name="Recipents";Expression={$_.recipients}}

Относительно образца выделения значений получателя из журнала транспорта Exchange обратитесь к Листингу 8-2.

Листинг 8-2. Пример кода, отображающего как экспортировать атрибуты со множеством значений

Get-transportserver | Get-MessageTrackingLog -Start"03/09/2015 00:00:00 AM" -End"03/09/2015 11:59:59 PM" -sender "vikas@lab.com" -resultsize unlimited | `
select-object Timestamp,clientip,ClientHostname,ServerIp,ServerHostname,sender,EventId,MessageSubject, TotalBytes , SourceContext,ConnectorId,Source, `
InternalMessageId , MessageId ,@{Name="Recipents";Expression={$_.recipients}} | `
export-csv c:\track.csv

Отчёт Excel

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

Первый метод имеется в нашем модуле vsadmin, которым я поделился в главе о модулях.

[Замечание]
Замечание

Для применения данного метода в вашей машине должен иметься установленным Excel.

Листинг 8-3 отображает код нашей функции Save-CSV2Excel в случае, когда вы не обладаете установленным модулем vsadmin или не желаете его устанавливать.

Листинг 8-3. Шпаргалка кода для функции Save-CSV2Excel

Function Save-CSV2Excel
{
  [CmdletBinding()]
  Param(
    [Parameter(Mandatory = $true,Position = 1)]
    [ValidateScript({
          if(-Not ($_ | Test-Path) ){throw "File or folder does not exist"}
          if(-Not ($_ | Test-Path -PathType Leaf) ){throw "The Path argument must be a file. Folder paths are not allowed."}
          if($_ -notmatch "(\.csv)"){throw "The file specified in the path argument must be either of type csv"}
          return $true
    })]
    [System.IO.FileInfo]$CSVPath,
    [Parameter(Mandatory = $true)]
    [ValidateScript({
          if($_ -notmatch "(\.xlsx)"){throw "The file specified in the path argument must be either of type xlsx"}
          return $true
    })]
    [System.IO.FileInfo]$Exceloutputpath
  )
  ####### Заимствованная у Lloyd Watkinson из галереи сценариев функция##
  Function Convert-NumberToA1
  {
    Param([parameter(Mandatory = $true)]
    [int]$number)
    $a1Value = $null
    While ($number -gt 0)
    {
      $multiplier = [int][system.math]::Floor(($number / 26))
      $charNumber = $number - ($multiplier * 26)
      If ($charNumber -eq 0) { $multiplier-- ; $charNumber = 26 }
      $a1Value = [char]($charNumber + 64) + $a1Value
      $number = $multiplier
    }
    Return $a1Value
  }
  ##################Начинаем преобразовывать excel#######################
  $importcsv = Import-Csv $CSVPath
  $countcolumns = ($importcsv |
    Get-Member |
  Where-Object{$_.membertype -eq "Noteproperty"}).count
  #################вызов объекта com Excel ##############
  $xl = New-Object -comobject excel.application
  $xl.visible = $false
  $Workbook = $xl.workbooks.open($CSVPath)
  $Workbook.SaveAs($Exceloutputpath, 51)
  $Workbook.Saved = $true
  $xl.Quit()
  #############Теперь форматируем свой Excel###################
  timeout.exe 10 #wait for 10 seconds before saving
  $xl = New-Object -comobject excel.application
  $xl.visible = $false
  $Workbook = $xl.workbooks.open($Exceloutputpath)
  $worksheet1 = $Workbook.worksheets.Item(1)
  for ($c = 1; $c -le $countcolumns; $c++) {$worksheet1.Cells.Item(1, $c).Interior.ColorIndex = 39}
  $colvalue = (Convert-NumberToA1 $countcolumns) + "1"
  $headerRange = $worksheet1.Range("a1", $colvalue)
  $null = $headerRange.AutoFilter()
  $null = $headerRange.entirecolumn.AutoFit()
  $worksheet1.rows.item(1).Font.Bold = $true
  $Workbook.Save()
  $Workbook.Close()
  $xl.Quit()
  $Null = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($xl)
  #######################################################################
}#Write-CSV2Excel

Давайте воспользуемся отчётом CSV из Листинга 8-1 и преобразуем его в Excel при помощи Save-CSV2Excel. Смотрите на Рисунок 8-2.

Save-CSV2Excel -CSVPath c:\temp\report.csv -Exceloutputpath c:\temp\report.xlsx

Рисунок 8-2

Отображение преобразования CSV в Excel

Имеется модуль с названием ImportExcel. Это один из наиболее популярных модулей из Галереи PowerShell. Вы можете воспользоваться этим модулем непосредственно преобразовывая переменные в Excel. Получите его из http://www.powershellgallery.com/packages/ImportExcel. Установите этот модуль в своей машине и затем импортируйте его для применения:

Install-Module -Name ImportExcel

Давайте воспользуемся тем же самым отчётом, который мы применяли в этом новом модуле для его преобразования в Excel. Основное преимущество применения данного модуля состоит в том, что он не требует установленного Excel в вашей машине. Обращаем ваше внимание на Рисунок 8-3.

Import-Module -Name ImportExcel

$data = Import-Csv .\report.csv
$data | Export-Excel -Path c:\temp\report.xlsx

Рисунок 8-3

Применение модуля Import-Excel

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

Отчёт HTML

Было бы замечательно если бы вы могли создавать информационные панели HTML при помощи PowerShell ☺, которые были бы способны отображать сигналы светофора. Например, когда служба не работает, она отображается красным цветом. В противном случае она показана зелёным цветом. Обратитесь к Рисунку 8-4.

Рисунок 8-4

Отчёт таблицы HTML

Листинг 8-4 представляет шаблон для кодирования HTML, которым вы можете пользоваться внутри сценариев и выполнять операции подсветки светофора на основе условий.

Листинг 8-4. Шаблон для кодирования HTML

$report = $reportpath
Clear-Content $report
#################Содержимое отчётаHTml############################
Add-Content $report "<html>"
Add-Content $report "<head>"
Add-Content $report "<meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'>"
Add-Content $report '<title>Exchange Status Report</title>'
add-content $report '<STYLE TYPE="text/css">'
add-content $report  "<!--"
add-content $report  "td {"
add-content $report  "font-family: Tahoma;"
add-content $report  "font-size: 11px;"
add-content $report  "border-top: 1px solid #999999;"
add-content $report  "border-right: 1px solid #999999;"
add-content $report  "border-bottom: 1px solid #999999;"
add-content $report  "border-left: 1px solid #999999;"
add-content $report  "padding-top: 0px;"
add-content $report  "padding-right: 0px;"
add-content $report  "padding-bottom: 0px;"
add-content $report  "padding-left: 0px;"
add-content $report  "}"
add-content $report  "body {"
add-content $report  "margin-left: 5px;"
add-content $report  "margin-top: 5px;"
add-content $report  "margin-right: 0px;"
add-content $report  "margin-bottom: 10px;"
add-content $report  ""
add-content $report  "table {"
add-content $report  "border: thin solid #000000;"
add-content $report  "}"
add-content $report  "-->"
add-content $report  "</style>"
Add-Content $report "</head>"
Add-Content $report "<body>"
add-content $report  "<table width='100%'>"
add-content $report  "<tr bgcolor='Lavender'>"
add-content $report  "<td colspan='7' height='25' align='center'>"
add-content $report  "<font face='tahoma' color='#003399' size='4'><strong>DAG Active Manager</strong></font>"
add-content $report  "</td>"
add-content $report  "</tr>"
add-content $report  "</table>"
add-content $report  "<table width='100%'>"
Add-Content $report  "<tr bgcolor='IndianRed'>"
Add-Content $report  "<td width='10%' align='center'><B>Identity</B></td>"
Add-Content $report  "<td width='5%' align='center'><B>PrimaryActiveManager</B></td>"
Add-Content $report  "<td width='20%' align='center'><B>OperationalMachines</B></td>"
Add-Content $report "</tr>"
##############################Шаблон отчёта##################################
add-content $report  "<tr bgcolor='Lavender'>"
add-content $report  "<td colspan='7' height='25' align='center'>"
add-content $report  "<font face='tahoma' color='#003399' size='4'><strong>DAG Database Backup Status</strong></font>"
add-content $report  "</td>"
add-content $report  "</tr>"
add-content $report  "</tr>"
add-content $report  "</table>"
add-content $report  "<table width='100%'>"
Add-Content $report "<tr bgcolor='IndianRed'>"
Add-Content $report  "<td width='10%' align='center'><B>Database</B></td>"
Add-Content $report  "<td width='5%' align='center'><B>BackupInProgress</B></td>"
Add-Content $report  "<td width='10%' align='center'><B>SnapshotLastFullBackup</B></td>"
Add-Content $report  "<td width='5%' align='center'><B>SnapshotLastCopyBackup</B></td>"
Add-Content $report  "<td width='10%' align='center'><B>LastFullBackup</B></td>"
Add-Content $report  "<td width='5%' align='center'><B>RetainDeletedItemsUntilBackup</B></td>"
$dbst= Get-MailboxDatabase | where{$_.MasterType -like "DatabaseAvailabilityGroup"}

$dbst | foreach{$st=Get-MailboxDatabase $_ -status
  $dbname =  $st.Name
  $dbbkprg = $st.BackupInProgress
  $dbsnpl = $st.SnapshotLastFullBackup
  $dbsnplc= $st.SnapshotLastCopyBackup
  $dblfb = $st.LastFullBackup
  $dbrd = $st.RetainDeletedItemsUntilBackup
    Add-Content $report "<tr>"
    Add-Content $report "<td bgcolor= 'GainsBoro' align=center>  <B>$dbname</B></td>"
          Add-Content $report "<td bgcolor= 'GainsBoro' align=center>  <B>$dbbkprg</B></td>"
    Add-Content $report "<td bgcolor= 'GainsBoro' align=center>  <B>$dbsnpl</B></td>"
          Add-Content $report "<td bgcolor= 'GainsBoro' align=center>  <B>$dbsnplc</B></td>"
  if($dblfb -lt $hrs)
  {
    Add-Content $report "<td bgcolor= 'Red' align=center>  <B>$dblfb</B></td>"
  }
  else
  {
      Add-Content $report "<td bgcolor= 'Aquamarine' align=center>  <B>$dblfb</B></td>"
  }
    Add-Content $report "<td bgcolor= 'GainsBoro' align=center>  <B>$dbrd</B></td>"
    Add-Content $report "</tr>"
}
##############################################################
Add-content $report  "</table>"
Add-Content $report "</body>"
Add-Content $report "</html>"

по приводимым далее ссылкам вы можете увидеть примеры, в которых этот шаблон успешно применялся для служб Exchange Health Check, AD Health Check и Monitor Remote:

https://techwizard.cloud/exchange-2010-health-check/

https://techwizard.cloud/adhealthcheck/

https://techwizard.cloud/monitor-windows-services-status-remotely/

Как уже упоминалось, для создания HTML и его применения в сценариях PowerShell, вы можете воспользоваться Интернет редактором HTML.

Выводы

В этой главе вы изучили составление отчётов. Наиболее распространёнными и применяемыми во всех системах типами отчётов выступают CSV, HTML и Excel. Изучив как выполнять такие отчёты, вы можете запросто впечатлять управляющих сведениями, которые им необходимы, причём в понятном им формате.

Глава 9. Различные ключевые слова

Содержание

Глава 9. Различные ключевые слова

Split

Replace

Select-String

Compare-Object

Выводы

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

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

Split

Ключевое слово split может применяться для извлечения данных из строки. Допустим, внутри какой- то строки имеется некий адрес электронной почты, который вы бы хотели получить, либо вы бы хотели выделить некие полезные сведения из какой- то текстовой строки.

Чтобы подробнее разобраться с этим, давайте пройдёмся по какому- то примеру. Давайте выделим имя и фамилию из строки адреса электронной почты. Вы воспользуетесь split, потому как оно способно расщеплять вашу строку по любому символу и преобразовывать её в массив. Вы можете расщепить адрес своей электронной почты по точке (.). После этого в элементе 0 полученного массива вы получаете имя, однако для фамилии вы должны снова выполнить расщепление по символу @.

$email = "Vikas.Sukhija@labtest.com"
$emsplit = $email.split(".")
$firstname = $emsplit[0]
$lastname = ($emsplit[1] -split "@")
$lastn = $lastname[0]
$emsplit[0] and $lastname[0]

На Рисунке 9-1 просмотрите пошаговые действия расщепления чтобы лучше разобраться как им пользоваться.

Рисунок 9-1

Отображение операции расщепления

Replace

Другим ключевым словом выступает replace. Вместо расщепления своей строки, вы можете заменить определённое содержимое этой строки иным содержимым.

Вы можете применять replace когда вы хотите заменять данные в строке. Допустим, вы желаете добавлять подчёркивание вместо точки, потому как вы хотите обновлять вторичный адрес. Вы можете применить такой код и просмотреть полученный результат на Рисунке 9-2:

$email = "Vikas.Sukhija@labtest.com"
$emreplace = $email.replace(".","_")

Рисунок 9-2

Отображение операции замены

Select-String

Select-String способен творить чудеса, поскольку вы можете пользоваться им для поиска строк внутри файлов. Вот практическое применение этого, которым я многократно пользовался (в то время как прочие боролись и тратили множество часов пытаясь это решить): поиск верной даты и времени операции в большом количестве файлов журналов.

Допустим, у вас имеется большое число файлов внутри папки logs и вы желаете отыскать те файлы, в которых присутствует строка error:

Get-ChildItem c:\data\logs | Select-String -Pattern "Error"

Этот простой код в одну стоку отыщет вхождения строки error во всех имеющихся файлах журналов из папки logs. Рисунок 9-3 показывает как выделяются имена файлов в тех файлах, которые содержат error.

Рисунок 9-3

Отображение операции Select-String

Compare-Object

Compare-Object с синонимом Compare многократно применяется для сравнения двух файлов или двух массивов. Это быстрее чем сопоставление массивов или файлов при помощи циклов for. Я неоднократно применял его для выборки участников из групп и сопоставления их с текстовым файлом, который обладает идентификаторами пользователей. Такой подход выполняет выборку лишь тех участников, которые уже часть соответствующей группы и добавляет их, вместо обработки всех участников.

Листинг 9-1 добавляет участников из одной группы в другую.

[Замечание]
Замечание

Для такой работы требуется модуль Active Directory.

Листинг 9-1. Код шпаргалки для добавления участников при помощи Compare-Object

##########################выборка из group1 ##################
 $collgroup1 = Get-ADGroup -id "group1" -Properties member |
  Select-Object -ExpandProperty member |
  Get-ADUser |
  Select-Object -ExpandProperty samaccountname
##########################выборка из group2 ##################
 $collgroup2 = Get-ADGroup -id "group2" -Properties member |
  Select-Object -ExpandProperty member |
  Get-ADUser |
  Select-Object -ExpandProperty samaccountname
####################сопоставление двух групп#####################
 $change = Compare-Object -ReferenceObject $collgroup1 -DifferenceObject $collgroup2
 $Addition = $change |
 Where-Object -FilterScript {$_.SideIndicator -eq "<="} |
 Select-Object -ExpandProperty InputObject
#######добавление лишь тех участников, которые пропущены в group2##############
 $Addition | ForEach-Object{
      $sam = $_
      Add-ADGroupMember -identity "group2" -Members $sam
 }
##############################################################

Аналогично, вы можете осуществлять операцию удаления при помощи Compare-Object, как это показано в Листинге 9-2.

Листинг 9-2. Код шпаргалки для удаления участников при помощи Compare-Object

##########################выборка из group1 ##################
 $collgroup1 = Get-ADGroup -id "group1" -Properties member |
  Select-Object -ExpandProperty member |
  Get-ADUser |
  Select-Object -ExpandProperty samaccountname
##########################выборка из group2 ##################
 $collgroup2 = Get-ADGroup -id "group2" -Properties member |
  Select-Object -ExpandProperty member |
  Get-ADUser |
  Select-Object -ExpandProperty samaccountname
####################сравнение двух групп####################
 $change = Compare-Object -ReferenceObject $collgroup1 -DifferenceObject $collgroup2
 $Removal = $change |
 Where-Object -FilterScript {$_.SideIndicator -eq "=>"} |
 Select-Object -ExpandProperty InputObject
####Удаление участников, которые имеются в group2, но отсутствуют в group1########
 $Removal | ForEach-Object{
      $sam = $_
      Remove-ADGroupMember -identity "group2" -Members $sam -confirm:$false
 }
##############################################################

Вы можете соединить обе операции в одном сценарии и осуществить синхронизацию двух групп на основе group1 как соответствующего якоря. Эту операцию отображает Листинг 9-3.

Листинг 9-3. Код шпаргалки для для синхронизации двух групп при помощи Compare-Object (на основе group1 в качестве якорной)

##########################выборка из group1 ##################
 $collgroup1 = Get-ADGroup -id "group1" -Properties member |
  Select-Object -ExpandProperty member |
  Get-ADUser |
  Select-Object -ExpandProperty samaccountname
##########################выборка из group2 ##################
 $collgroup2 = Get-ADGroup -id "group2" -Properties member |
  Select-Object -ExpandProperty member |
  Get-ADUser |
  Select-Object -ExpandProperty samaccountname
####################сравнение двух групп####################
 $change = Compare-Object -ReferenceObject $collgroup1 -DifferenceObject $collgroup2
$Addition = $change |
 Where-Object -FilterScript {$_.SideIndicator -eq "<="} |
 Select-Object -ExpandProperty InputObject
 $Removal = $change |
 Where-Object -FilterScript {$_.SideIndicator -eq "=>"} |
 Select-Object -ExpandProperty InputObject
#######добавление лишь тех участников, которые пропущены в group2########
 $Addition | ForEach-Object{
      $sam = $_
      Add-ADGroupMember -identity "group2" -Members $sam
 }
 ####Удаление присутствующих в group2, но отсутствующих в group1 участников########
 $Removal | ForEach-Object{
      $sam = $_
      Remove-ADGroupMember -identity "group2" -Members $sam -confirm:$false
 }
##############################################################

Вы также можете воспользоваться иным подходом чтобы вместо удаления из group2 вы просто применили ADD-Groupmember для group1 с тем, чтобы вы могли и в самом деле выполнить синхронизацию обеих групп. Все объекты пользователей, которые не присутствуют в group2, но имеются в group1, должны быть добавлены в group2, а все объекты пользователей, которые отсутствуют в group1, но имеются в group2, должны быть добавлены в group1:

ADD-ADGroupMember -identity "group1" -Members $sam

вместо

Remove-ADGroupMember -identity "group2" -Members $sam -confirm:$false

Имеются две примечательные уловки, которыми вы можете пользоваться при помощи Compare-Object. Скажем, у вас имеются два файла CSV. Один это просто адреса электронной почты пользователей; другой обладает адресами электронной почты и прочими свойствами. Вам нужны все подробности из второго файла CSV для пользователей, имеющихся в первом файле CSV.

Листинг 9-4 отображает пример для свойств OneDrive. Имеются два файла CSV. Один содержит адреса электронной почты пользователей, а другой содержит адреса электронной почты и в прочих столбцах иные свойства.

Листинг 9-3. Код шпаргалки для для синхронизации двух групп при помощи Compare-Object (на основе group1 в качестве якорной)

$importallonedrivesites = import-csv "c:\importonedrives.csv" # onedrive file with other attributes
$importspofile = import-csv "c:\users.csv" #адреса электронной почты пользователей
$change = Compare-Object -ReferenceObject $importallonedrivesites   -DifferenceObject $importspofile -Property owner -IncludeEqual -PassThru  #владельцы это названия колонок для пользователей с адресами электронной почты
$change | where{$_.SideIndicator -eq "==" -or $_.SideIndicator -eq "=>"} |
select Owner, Title, url, StorageUsageCurrent, StorageQuota, StorageQuotaWarningLevel |
Export-Csv "c:\newfile.csv" -NoTypeInformation

Выводы

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

Глава 10. Склеиваем всё это воедино

Содержание

Глава 10. Склеиваем всё это воедино

Примеры продуктов (ежедневного применения)

Microsoft Exchange

Очистка базы данных с тем, чтобы Почтовые ящики появлялись в отключённом состоянии

Поиск отключённых Почтовых ящиков

Выделение Сообщение получено от

Активные синхронизации статистик

Отслеживание сообщений

Поиск сообщений Почтовый ящик/ Удалённые

Отчёт о квотах Exchange

Настройка квот

Active Directory

Экспорт Участников группы

Установка значения для атрибутов AD

Экспорт атрибутов AD

Добавление участников в группу из текстового файла

Удаление участников в группу из текстового файла

Office 365

Отчёт Почтового ящика Exchange Online

Отслеживание сообщения Exchange Online

Поиск унифицированного журнала

Azure AD

Добавление пользователей в группу Azure AD из текстового файла UPN

Удаление пользователей в группе Azure AD из текстового файла UPN

Проверка является ли пользователь участником группы

Добавление в роль Администраторов

Проверка ошибок предоставления пользователей Azure AD

Операции с файлом Text/CSV

Regex

Выводы

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

Вот соответствующая ситуация: Вы получили текстовый файл из своей системы персонала, который содержит список имён учётных записей (Рисунок 10-1), который вы хотите добавить в некую группу Active Directory с тем, чтобы они имели возможность доступа к определённому совместному ресурсу файлов, для которого данная группа AD обладает полномочиями или получить некое прикладное приложение, которое помещается в их устройства на основе их участия в данной группе AD.

Рисунок 10-1

Отображение примера текстового файла пользователей

Шаг 1: добавляем заголовок своего сценария (см. Рисунок 10-2):

<#
    .NOTES
    ===========================================================
    Created with:     ISE
    Created on:       9/6/2021 1:46 PM
    Created by:       Vikas Sukhija
    Organization:
    Filename:         ADDUserstoGroupfromText.ps1
    ===========================================================
    .DESCRIPTION
    Добавляет всех пользователей из текстового файла в группу AD
#>

Рисунок 10-2

Отображение заголовков в ISE

Шаг 2: импорт всех модулей, которые вы будете применять для данного сценария:

Модуль vsadmin упростит вашу жизнь для необходимых операций составления сценария.

Модули Active Directory

Если вы не желаете пользоваться модулем vsadmin, тогда просто воспользуйтесь вместо этого необходимыми функциями.

import-module vsadmin
import-module Activedirectory

Шаг 3: добавляем для вашего сценария некие переменные и журналы:

$log = Write-Log -Name "ADDUser2Group-Log" -folder "logs" -Ext "log"
$users = get-content "c:\temp\users.txt"
$Adgroup = "ADgroup1"
$logrecyclelimit = "60" #для отправки в корзину по истечению 60 дней

Шаг 4: приступаем к реальному действию:

Write-Log -Message "Start...............script" -path $log
$users | foreach-object{
  $user = $_.trim() #triming fro any whitespace
  Write-Log -Message "Processing..........$user" -path $log
  $getusermemberof = Get-ADUserMemberOf -User $user -Group $Adgroup #checking if user si already member
  if($getusermemberof -eq $true){ #if users is already mebe rjust write it to log
    Write-Log -Message "$user is already member of $Adgroup" -path $log
  }
  else{
    Write-Log -Message "ADD $user to $Adgroup" -path $log
    Add-ADGroupMember -identity $Adgroup -members $user
    if($error){ #error checking, if error occurs add in log
      Write-Log -Message "Error - ADD $user to $Adgroup" -path $log
     $error.clear() # clearing the error as it has already been captuire for this iteration
    }
    else{
      Write-Log -Message "Success - ADD $user to $Adgroup" -path $log
    }
  }
}

Шаг 5: Отправка в корзину журналов или очистка соответствующих сеансов (см. Листинг 10-1):

#####################Очистка журналов#############################
Set-Recyclelogs -foldername "logs" -limit $logrecyclelimit -Confirm:$false

Write-Log -Message "Script Finished" -path $log

Склеиваем всё воедино для формирования привлекательного сценария, которым делимся в Листинге 10.1

Листинг 10-1. Код шпаргалки примера шаблона сценария

<#
    .NOTES
    ==========================================================
    Created with:     ISE
    Created on:       9/6/2021 1:46 PM
    Created by:       Vikas Sukhija
    Organization:
    Filename:         ADDUserstoGroupfromText.ps1
    ==========================================================
    .DESCRIPTION
    Это добавляет всех пользователей из текстового файла в группу AD
#>
###############Импорт модулей и функций#####################
import-module vsadmin
import-module Activedirectory
##############Добавляем журналы и переменные############################
$log = Write-Log -Name "ADDUser2Group-Log" -folder "logs" -Ext "log"
$users = get-content "c:\temp\users.txt"
$Adgroup = "ADgroup1"
$logrecyclelimit = "60" #to recycle the logs after 60 days
################################################################
Write-Log -Message "Start...............script" -path $log
$users | foreach-object{
  $user = $_.trim() #отсекаем все пробельные символы
  Write-Log -Message "Processing..........$user" -path $log
  $getusermemberof = Get-ADUserMemberOf -User $user -Group $Adgroup #проверяем является ли уже участником пользователь si
  if($getusermemberof -eq $true){ #когда пользователь уже участник, просто заносим его в журнал
    Write-Log -Message "$user is already member of $Adgroup" -path $log
  }
  else{
    Write-Log -Message "ADD $user to $Adgroup" -path $log
    Add-ADGroupMember -identity $Adgroup -member $user
    if($error){ #error checking, if error occurs add in log
      Write-Log -Message "Error - ADD $user to $Adgroup" -path $log
      $error.clear() # создаём ошибку когда он был уже перехвачен для повтора
    }
    else{
      Write-Log -Message "Success - ADD $user to $Adgroup" -path $log
    }
  }
}
#####################Очищаем журналы#############################
Set-Recyclelogs -foldername "logs" -limit $logrecyclelimit -Confirm:$false
Write-Log -Message "Script Finished" -path $log

Давайте выполним этот код шпаргалки изменив значение переменной adgroup и добавив в свой текстовый файл пользователей, якобы для промышленной среды. Смотрите Рисунок 10-3).

Рисунок 10-3

Отображение исполнения сценария ADDUserstoGroupFromText.ps1

Аналогичным образом вы можете создавать множество сценариев для различных промышленных применений. За последние 10 лет я поделился с сообществом сотнями сценариев, к которым вы можете получить доступ через приводимую ниже ссылку и которые можете изменять под свои потребности. Большинство этих сценариев разделяют те же самые принципы, которые описаны в данной книге: https://techwizard.cloud/downloads/.

Примеры продуктов (ежедневного применения)

В данной главе я делюсь фрагментами кода, которые вы можете применять как есть или сочетать со своими сценариями для ежедневных административных задач. По причине своего обожания Exchange, я пользуюсь Microsoft Exchange☺. Здесь выдержки сценария Exchange, которые вы можете применять на ежедневной основе.

Microsoft Exchange

Очистка базы данных с тем, чтобы Почтовые ящики появлялись в отключённом состоянии

Get-MailboxServer | Get-MailboxDatabase | Clean-MailboxDatabase

Поиск отключённых Почтовых ящиков

Get-ExchangeServer | Where-Object {$_.IsMailboxServer -eq $true} | ForEach-Object { Get-MailboxStatistics -Server $_.Name | Where-Object {$_.DisconnectDate -notlike ''}}

Выделение Сообщение получено от

Get-distributiongroup "dl name" | foreach {$_.AcceptMessagesonlyFrom} | add-content "c:/output/abc.txt"

Активные синхронизации статистик

Get-CASMailbox -ResultSize unlimited | where {$_.ActiveSyncEnabled -eq "true"} | ForEach-Object {GetActiveSyncDeviceStatistics -Mailbox:$_.identity} | select Devicetype, DeviceID,DeviceUserAgent, FirstSyncTime, LastSuccessSync, Identity, DeviceModel, DeviceFriendlyName, DeviceOS | Export-Csv c:\activesync.csv

Отслеживание сообщений

Get-transportserver | Get-MessageTrackingLog -Start "03/09/2015 00:00:00 AM" -End "03/09/2015 11:59:59 PM" -sender "vikas@lab.com" -resultsize unlimited | select Timestamp,clientip, ClientHostname,ServerIp,ServerHostname,sender,EventId,MessageSubject, TotalBytes , SourceContext,ConnectorId,Source , InternalMessageId , MessageId ,@{Name="Recipents";Expression={$_.recipients}} | export-csv c:\track.csv

Поиск сообщений Почтовый ящик/ Удалённые

Только поиск:

import-csv c:\tmp\messagesubject.csv | foreach {Search-Mailbox $_.alias -SearchQuery subject:"Test SUbject" -TargetMailbox "Exmontest" -TargetFolder "Logs" -LogOnly -LogLevel Full} >c:\tmp\output.txt

Удаление:

import-csv c:\tmp\messagesubject.csv | foreach {Search-Mailbox $_.alias -SearchQuery subject:"Test Schedule" -DeleteContent -force} >c:\tmp\output.txt

Удаление и регистрация:

Get-transportserver

Отчёт о квотах Exchange

Этот пример находится также и в Export-CSV.

#форматирование даты
$date = get-date -format d
$date = $date.ToString().Replace("/", "-")
$output = ".\" + "QuotaReport_" + $date + "_.csv"
Collection = @()
Get-Mailbox -ResultSize Unlimited | foreach-object{
$st = get-mailboxstatistics $_.identity
$TotalSize = $st.TotalItemSize.Value.ToMB()
$user = get-user $_.identity
$mbxr = "" | select DisplayName,Alias,RecipientType,TotalItemSizeinMB, QuotaStatus,
UseDatabaseQuotaDefaults,IssueWarningQuota,ProhibitSendQuota,ProhibitSendReceiveQuota,
Itemcount, Email,ServerName,Company,Hidden, OrganizationalUnit,
RecipientTypeDetails,UserAccountControl,Exchangeversion

$mbxr.DisplayName = $_.DisplayName
$mbxr.Alias = $_.Alias
$mbxr.RecipientType = $user.RecipientType
$mbxr.TotalItemSizeinMB = $TotalSize
$mbxr.QuotaStatus = $st.StorageLimitStatus
$mbxr.UseDatabaseQuotaDefaults = $_.UseDatabaseQuotaDefaults
$mbxr.IssueWarningQuota = $_.IssueWarningQuota.Value
$mbxr.ProhibitSendQuota = $_.ProhibitSendQuota.Value
$mbxr.ProhibitSendReceiveQuota = $_.ProhibitSendReceiveQuota.Value
$mbxr.Itemcount = $st.Itemcount
$mbxr.Email = $_.PrimarySmtpAddress
$mbxr.ServerName = $st.ServerName
$mbxr.Company = $user.Company
$mbxr.Hidden = $_.HiddenFromAddressListsEnabled
$mbxr.RecipientTypeDetails = $_.RecipientTypeDetails
$mbxr.OrganizationalUnit = $_.OrganizationalUnit
$mbxr.UserAccountControl = $_.UserAccountControl
$mbxr.ExchangeVersion= $_.ExchangeVersion
$Collection += $mbxr
}
 #экспорт собранной коллекции в csv , надлежащим образом определяем путь $output
$Collection | export-csv $output

Настройка квот

Предел почтового ящика в 1ГБ (обязан иметь включённым значение $false)

set-mailbox testmailbox -UseDatabaseQuotaDefaults $false -IssueWarningQuota 997376KB -ProhibitSendQuota 1048576KB -ProhibitSendReceiveQuota 4194304KB

Предел почтового ящика в 2ГБ (обязан иметь включённым значение $false)

set-mailbox "testmailbox" -UseDatabaseQuotaDefaults $false -IssueWarningQuota 1.75GB -ProhibitSendQuota 2GB -ProhibitSendReceiveQuota 4GB

Предел почтового ящика в 3ГБ (обязан иметь включённым значение $false)

set-mailbox "testmailbox" -UseDatabaseQuotaDefaults $false -IssueWarningQuota 2.75GB -ProhibitSendQuota 3GB -ProhibitSendReceiveQuota 5GB

Active Directory

Active Directory это дорога жизни для всех продуктов Microsoft. Применяя PowerShell вы можете автоматизировать различные компоненты Active Directory. К счастью, Microsoft создала для такого задания собственный модуль Active Directory.

Ниже приводятся методы, которые вы можете применять для написания сценариев Active Directory при помощи PowerShell:

Модуль Active Directory

Оболочка Quest Management для Active Directory

ADSI (выходит за рамки этой книги)

В прошлом моим любимчиком была оболочка Quest Management, за которой следовал модуль Active Directory Microsoft. Оболочка Quest бесплатна и её можно выгружать. Однако Microsoft добавила обновления, так что, на мой взгляд, теперь он на уровне или даже лучше чем Quest.

Ещё одна из причин, по которой модуль Active Directory обладает приоритетом, на мой взгляд, состоит в том, что модуль AD Quest больше не является бесплатным, хотя вы ещё можете найти его старую версию. Я обнаружил ей по приводимой ниже ссылке (если вы хотите применять его промышленным образом, убедитесь что это не потребует лицензирования).

Я призываю вас применять модуль Active Directory Microsoft, но всё ещё имеется множество администраторов или организаций, пользующихся Quest, причём как бесплатно, так и приобретая его. Выгрузите бесплатную версию AD Quest (1.5.1) по следующей ссылке (найдена через Google). Смотрите Рисунок 10-4).

Рисунок 10-4

Отображение модуля AD Quest

Экспорт Участников группы

Сработает лишь одна строка кода:

При помощи Quest:

Get-QADGroupMember "group Name" | select Name, Type | Export-Csv .\members.csv

При помощи модуля Active Directory:

Get-ADGroup -identity "group Name" -Properties member | Select-Object -ExpandProperty member | Get-ADUser -Properties DisplayName,Samaccountname,mail,employeeid | export-csv c:\exportgroup.csv -notypeinfo

Установка значения для атрибутов AD

Вот пример кода, который может применяться для настройки атрибутов AD:

При помощи Quest:

Set-QADUser -identity samaccountname -ObjectAttributes @{extensionattribute10 = "IntuneCommCompleted"}

При помощи модуля Active Directory:

Set-ADUser -identity samaccountanme -replace @{"extensionattribute10" = "IntuneCommCompleted"}

Экспорт атрибутов AD

Этот пример служит вызову Excel а также в качестве использования Quest ☺:

# вызов excel для записи получаемых результатов
$objExcel = new-object -comobject excel.application
$workbook = $objExcel.Workbooks.Add()
$worksheet=$workbook.ActiveSheet
$objExcel.Visible = $False # true или false для настройки видимости на экране или нет
$cells=$worksheet.Cells
# define top level cell
$cells.item(1,1)="UserId"
$cells.item(1,2)="FirstName"
$cells.item(1,3)="LastName"
$cells.item(1,4)="Employeeid"
$cells.item(1,5)="email"
$cells.item(1,6)="Office"
$cells.item(1,7)="Department"
$cells.item(1,8)="Title"
$cells.item(1,9)="Company"
$cells.item(1,10)="City"
$cells.item(1,11)="State"
$cells.item(1,12)="Country"
#intitialize row out of the loop
$row = 2
#импорт оболочки управления quest
if ( (Get-PSSnapin -Name Quest.ActiveRoles.ADManagement -ErrorAction SilentlyContinue) -eq $null )
{
    Add-PsSnapin Quest.ActiveRoles.ADManagement
}
$data = get-qaduser -IncludedProperties "CO", "extensionattribute1" #-sizelimit 0
#цикл по пользователям
foreach ($i in $data){
#инициализация столбца внутри цикла с тем, чтобы он всегда возвращал цикл обратно в столбец 1
$col = 1
$userid=$i.Name
$FisrtName=$i.givenName
$LastName=$i.sn
$Employeeid=$i.extensionattribute1
$email=$i.PrimarySMTPAddress
$office=$i.Office
$Department=$i.Department
$Title=$i.Title
$Company=$i.Company
$City=$i.l
$state=$i.st
$Country=$i.CO
Write-host "Processing.................................$userid"
$cells.item($row,$col) = $userid
$col++
$cells.item($row,$col) = $FisrtName
$col++
$cells.item($row,$col) = $LastName
$col++
$cells.item($row,$col) = $Employeeid
$col++
$cells.item($row,$col) = $email
$col++
$cells.item($row,$col) = $office
$col++
$cells.item($row,$col) = $Department
$col++
$cells.item($row,$col) = $Title
$col++
$cells.item($row,$col) = $Company
$col++
$cells.item($row,$col) = $City
$col++
$cells.item($row,$col) = $state
$col++
$cells.item($row,$col) = $Country
$col++
$row++}
#форматирование excel
$range = $objExcel.Range("A2").CurrentRegion
$range.ColumnWidth = 30
$range.Borders.Color = 0
$range.Borders.Weight = 2
$range.Interior.ColorIndex = 37
$range.Font.Bold = $false
$range.HorizontalAlignment = 3
# Заголовки жирным шрифтом
$cells.item(1,1).font.bold=$True
$cells.item(1,2).font.bold=$True
$cells.item(1,3).font.bold=$True
$cells.item(1,4).font.bold=$True
$cells.item(1,5).font.bold=$True
$cells.item(1,6).font.bold=$True
$cells.item(1,7).font.bold=$True
$cells.item(1,8).font.bold=$True
$cells.item(1,9).font.bold=$True
$cells.item(1,10).font.bold=$True
$cells.item(1,11).font.bold=$True
$cells.item(1,12).font.bold=$True
#сохраняем в файл excel
$filepath = "c:\exportAD.xlsx" #сохраняем свой файл excel
$workbook.saveas($filepath)
$workbook.close()
$objExcel.Quit()

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

# вызов excel для записи получаемых результатов
$objExcel = new-object -comobject excel.application
$workbook = $objExcel.Workbooks.Add()
$worksheet=$workbook.ActiveSheet
$objExcel.Visible = $True # true или false для настройки видимости на экране или нет
$cells=$worksheet.Cells
# define top level cell
$cells.item(1,1)="UserId"
$cells.item(1,2)="FirstName"
$cells.item(1,3)="LastName"
$cells.item(1,4)="Employeeid"
$cells.item(1,5)="email"
$cells.item(1,6)="Office"
$cells.item(1,7)="Department"
$cells.item(1,8)="Title"
$cells.item(1,9)="Company"
$cells.item(1,10)="City"
$cells.item(1,11)="State"
$cells.item(1,12)="Country"
#intitialize row out of the loop
$row = 2
#импорт оболочки управления AD
Import-module Activedirectory
$data = Get-ADUser -Filter {Enabled -eq $True} -Properties extensionattribute1,mail,physicalDeliveryOfficeName,Department,title,Company,l,st,co -ResultSetSize 1000 #define the size
#цикл по пользователям
foreach ($i in $data){
#инициализация столбца внутри цикла с тем, чтобы он всегда возвращал цикл обратно в столбец 1
$col = 1
$userid=$i.Name
$FisrtName=$i.givenName
$LastName=$i.surname
$Employeeid=$i.extensionattribute1
$email=$i.mail
$office=$i.physicalDeliveryOfficeName
$Department=$i.Department
$Title=$i.Title
$Company=$i.Company
$City=$i.l
$state=$i.st
$Country=$i.CO
Write-host "Processing.................................$userid"
$cells.item($row,$col) = $userid
$col++
$cells.item($row,$col) = $FisrtName
$col++
$cells.item($row,$col) = $LastName
$col++
$cells.item($row,$col) = $Employeeid
$col++
$cells.item($row,$col) = $email
$col++
$cells.item($row,$col) = $office
$col++
$cells.item($row,$col) = $Department
$col++
$cells.item($row,$col) = $Title
$col++
$cells.item($row,$col) = $Company
$col++
$cells.item($row,$col) = $City
$col++
$cells.item($row,$col) = $state
$col++
$cells.item($row,$col) = $Country
$col++
$row++}
#форматирование excel
$range = $objExcel.Range("A2").CurrentRegion
$range.ColumnWidth = 30
$range.Borders.Color = 0
$range.Borders.Weight = 2
$range.Interior.ColorIndex = 37
$range.Font.Bold = $false
$range.HorizontalAlignment = 3
# Заголовки жирным шрифтом
$cells.item(1,1).font.bold=$True
$cells.item(1,2).font.bold=$True
$cells.item(1,3).font.bold=$True
$cells.item(1,4).font.bold=$True
$cells.item(1,5).font.bold=$True
$cells.item(1,6).font.bold=$True
$cells.item(1,7).font.bold=$True
$cells.item(1,8).font.bold=$True
$cells.item(1,9).font.bold=$True
$cells.item(1,10).font.bold=$True
$cells.item(1,11).font.bold=$True
$cells.item(1,12).font.bold=$True
#сохраняем свой файл excel
$filepath = "c:\exportAD.xlsx" #сохраняем свой файл excel
$workbook.saveas($filepath)
$workbook.close()
$objExcel.Quit()

Добавление участников в группу из текстового файла

При помощи оболочки управления Quest:

$users = Get-Content C:\Users.txt   # samccountnames of users in text file
$groupname = "Group Name"
$users | ForEach-Object{
$user = $_
Write-host "adding $user to $groupname" -foregroundcolor green
Add-QADGroupMember -Identity $groupname -Member $user
}

Аналогично, при помощи модуля Active Directory:

$users = Get-Content C:\Users.txt    # samccountnames of users in text file
$groupname = "Group Name"
$users | ForEach-Object{
$user = $_
Write-host "adding $user to $groupname" -foregroundcolor green
Add-ADGroupMember -id $groupname -members $user
}

Удаление участников в группу из текстового файла

При помощи оболочки управления Quest:

$users = Get-Content C:\Users.txt   # samccountnames of users in text file
$groupname = "Group Name"
$users | ForEach-Object{
$user = $_
Write-host "adding $user to $groupname" -foregroundcolor green
Remove-QADGroupMember -Identity $groupname -Member $user -confirm:$false
}

Аналогично, при помощи модуля Active Directory:

$users = Get-Content C:\Users.txt    # samccountnames of users in text file
$groupname = "Group Name"
$users | ForEach-Object{
$user = $_
Write-host "adding $user to $groupname" -foregroundcolor green
Remove-ADGroupMember -id $groupname -members $user -confirm:$false
}

Office 365

Office 365 вездесущ, поэтому подключения это важные повседневные действия для администраторов. Вы можете применять vsadmin или отдельные функции.

Операции:

LaunchEOL/RemoveEOL (Exchange Online)

LaunchSOL/RemoveSOL (Skype online)

LaunchSPO/RemoveSPO (SharePoint online)

LaunchCOL/RemoveCOL (Security and Compliance)

LaunchMSOL/RemoveMSOL (MS Online Azure Active Directory)

##################Exchange Modern Online##################
Function LaunchEOL {
  [CmdletBinding()]
  param
  (
    [Parameter(Mandatory = $false)]
    $Credential
  )
  Import-Module ExchangeOnlineManagement -Prefix "EOL"
  Connect-ExchangeOnline -Prefix "EOL" -Credential $Credential -ShowBanner:$false
}
Function RemoveEOL {
  Disconnect-ExchangeOnline -Confirm:$false
}
#############Skype Online#####################################
function LaunchSOL
{
  param
  (
    [Parameter(Mandatory = $true)]
    $Domain,
    [Parameter(Mandatory = $false)]
    $Credential
  )
  Write-Host -Object "Enter Skype Online Credentials" -ForegroundColor Green
  $dommicrosoft = $domain + ".onmicrosoft.com"
  $CSSession = New-CsOnlineSession -Credential $Credential -OverrideAdminDomain $dommicrosoft
  Import-Module (Import-PSSession -Session $CSSession -AllowClobber) -Prefix SOL  -Global
} #Function LaunchSOL
Function RemoveSOL
{
  $Session = Get-PSSession | Where-Object -FilterScript { $_.ComputerName -like "*.online.lync.com" }
  Remove-PSSession $Session
} #Function RemoveSOL
############Sharepoint Online###############################
function LaunchSPO
{
  param
  (
    [Parameter(Mandatory = $true)]
    $orgName,
    [Parameter(Mandatory = $false)]
    $Credential
  )
  Write-Host "Enter Sharepoint Online Credentials" -ForegroundColor Green
  Connect-SPOService -Url "https://$orgName-admin.sharepoint.com" -Credential $Credential
} #LaunchSPO
Function RemoveSPO
{
  disconnect-sposervice
} #RemoveSPO
####Secuirty and Compliance#####################################
Function LaunchCOL {
  [CmdletBinding()]
  param
  (
    [Parameter(Mandatory = $false)]
    $Credential
  )
  Import-Module ExchangeOnlineManagement
  Connect-IPPSSession -Credential $Credential
  $s=Get-PSSession | where {$_.ComputerName -like "*compliance.protection.outlook.com"}
  Import-Module (Import-PSSession -Session $s  -AllowClobber) -Prefix col -Global
}
Function RemoveCOL {
  Disconnect-ExchangeOnline -Confirm:$false
}
###############################Msonline######################
function LaunchMSOL {
  [CmdletBinding()]
  param
  (
    [Parameter(Mandatory = $false)]
    $Credential
  )
  import-module msonline
  Write-Host "Enter MS Online Credentials" -ForegroundColor Green
  Connect-MsolService -Credential $Credential
}
Function RemoveMSOL {
  Write-host "Close Powershell Window - No disconnect available" -ForegroundColor yellow
}
#######################################################

Отчёт Почтового ящика Exchange Online

Теперь воспользуемся приводимой выше функцией для запуска оболочки Exchange Online. В PowerShell наберите LaunchEOL и снабдите свой Exchange Online идентификатором пользователя/ паролем администратора. После того как вы подключитесь к Exchange Online, для выделения отчётов почтовых ящиков из Office 365 воспользуйтесь следующей командой, которую вы можете видеть на Рисунке 10-5).

Рисунок 10-5

Отображение подключения в оболочке Exchange

Get-EOLMailbox -ResultSize unlimited | Select Name,Recipient TypeDetails,PrimarySMTPAddress,UserPrincipalName,litigationhold enabled,LitigationHoldDuration,PersistedCapabilities,Retention HoldEnabled,RetentionPolicy,RetainDeletedItemsFor,ArchiveName, Archivestatus,ProhibitSendQuota,ProhibitSendReceiveQuota,MaxSend Size,MaxReceiveSize,AuditEnabled | export-csv c:\auditmbx.csv -notypeinfo

Когда у вас большое число арендаторов, воспользуйтесь приводимым кодом вместо указанного, поскольку этот не будет дросселироваться даже с более чем 50 000 пользователей:

$allmbx=Invoke-Command -Session (Get-PSSession | Where-Object{$_.computerName -eq "outlook.office365.com"}) -scriptblock {Get-Mailbox -ResultSize unlimited | Select-object Name,RecipientTypeDetails, PrimarySMTPaddress,UserPrincipalname,AuditEnabled,litigationholdenabled,LitigationHoldDuration,PersistedCapabilities,RetentionHoldEnabled,RetentionPolicy,RetainDeletedItemsFor,ArchiveName,Archivestatus,ArchiveGuid,ProhibitSendQuota,ProhibitSendReceiveQuota,MaxSendSize,MaxReceiveSize,WhenMailboxCreated,WhenCreated,HiddenFromAddressListsEnabled }
 $allmbx | export-csv c:\data\auditmbx.csv -notypeinfo

Отслеживание сообщения Exchange Online

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

$index = 1
while ($index -le 1001)
{
Get-EOLMessageTrace -SenderAddress "VikasS@techWizard.cloud" -StartDate 09/20/2019 -EndDate 09/25/2019 -PageSize 5000 -Page $index | export-csv c:\messagetracking.csv -Append
$index ++
sleep 5
}

Поиск унифицированного журнала

Office 365 применяет унифицированное ведение регистрации аудита и вы можете осуществлять аудит всех своих действий с применением оболочки Exchange Online (будь то SharePoint Online или Teams, либо любой иной продукт внутри Office 365). Вот ссылка для дополнительных подробностей: https://docs.microsoft.com/en-us/microsoft-365/compliance/search-the-audit-log-in-security-and-compliance%253FWT.mc_id%253DM365-MVP-5001317

Пример выделения действий Microsoft Teams:

Search-EOLUnifiedAuditLog -StartDate 1/8/2019 -EndDate 4/7/2019 -RecordType MicrosoftTeams -UserIds VikasS@sycloudpro.com  -ResultSize:5000 |export-csv c:\VikasS.csv -notypeinfo

Пример выделения аудита действий почтового ящика Exchange:

Search-EOLUnifiedAuditLog -StartDate 10/24/2019 -EndDate 10/25/2019 -UserIds VikasS@syscloudpro.com -recordtype "ExchangeItemGroup","ExchangeItem","ExchangeAggregatedOperation" -ResultSize:5000 |export-csv c:\VikasS.csv -notypeinfo

Пример добавления или удаления участника роли:

Search-EOLUnifiedAuditLog -StartDate 4/16/2019 -EndDate 7/15/2019 -UserIds VikasS@syscloudpro.com -operations "Add role member to role" -ResultSize:5000 |export-csv c:\VikasS.csv -notypeinfo

Azure AD

Я рассмотрел практические примеры Active Directory, однако в мире наших дней Azure AD становится распространённым, поэтому вот некоторые образцы из мира Azure AD.

Для Azure AD вам потребуется вначале для подключения применять connect-AzureAD, а для MS Online вы можете воспользоваться Connect-MsolService. После соединения, вы будете способны воспользоваться приводимыми далее примерами обновляя соответствующие переменные.

Добавление пользователей в группу Azure AD из текстового файла UPN

$group1 = "93345231-7454-4629-943b-e4245426bf" #
Get-Content C:\users.txt | ForEach-Object{$user=$_.trim();$user;$upn= $user
$getazureaduser = Get-AzureADUser -Filter "userprincipalname eq '$($upn)'"
 Add-AzureADGroupMember -ObjectId $group1  -RefObjectId $getazureaduser.ObjectId
}

Удаление пользователей в группе Azure AD из текстового файла UPN

$group1 = "93345231-7454-4629-943b-e4245426bf" #
Get-Content C:\users.txt | ForEach-Object{$user=$_.trim();$user;$upn= $user
$getazureaduser = Get-AzureADUser -Filter "userprincipalname eq '$($upn)'"
Remove-AzureADGroupMember -ObjectId $group1  -MemberId $getazureaduser.ObjectId
}

Проверка является ли пользователь участником группы

$group1 = "93345231-7454-4629-943b-e4245426bf" #
$getazmembership = Get-AzureADUserMembership  -ObjectId "UserObjectId"
if($getazmembership.objectId -contains $group1){
write-host  "User is already member of the group group1"
}

Добавление в роль Администраторов

Get-MsolRole | Sort Name | Select Name,Description #check role name
$roleName = "Lync Service Administrator"
Get-content c:\users.txt | foreach-object{$_;
Add-MsolRoleMember -RoleMemberEmailAddress $_ -RoleName $roleName
}

Проверка ошибок предоставления пользователей Azure AD

Get-MsolUser -HasErrorsOnly | ft DisplayName,UserPrincipalName,@{Name="Error";Expression={($_.errors[0].ErrorDetail.objecterrors.errorrecord.ErrorDescription)}} -AutoSize

Аналогичным образом вы можете подключаться к любому продукту Microsoft, сверившись с его документацией. Что касается прочих продуктов Azure, для подключения к Azure существует команда Connect-AzAccount. Просто убедитесь что в вашей машине установлены соответствующие модули для тех продуктов, к которым вы желаете подключаться.

Операции с файлом Text/CSV

Удаление имеющейся строки заголовка из файла CSV

Метод 1:

Get-Content .\abc.csv | select -skip 1 | Set-Content .\abc1.csv

Метод 2:

$a = import .\abc.csv
$a |ForEach-Object{
  $Con_string = $null
  $Con_string = $_.ID, $_.GrpName -join ','
  Write-Host $Con_string
  Add-Content .\abc6.csv $Con_string
}

Метод 3 (за исключением CRLF):

$text = [System.IO.File]::ReadAllText("$pwd\file.csv") -replace '^[^\r\n]*\r?\n'
[System.IO.File]::WriteAllText("$pwd\newFile.csv", $text)

Метод 4 (за исключением CRLF):

$file = Get-Item .\example_test.csv
$reader = $file.OpenText()
# discard the first line
$null = $reader.ReadLine()
# Write the rest of the text to the new file
[System.IO.File]::WriteAllText("$pwd\newFile.csv", $reader.ReadToEnd())
$reader.Close()

Добавление строки заголовка в текстовый файл:

Например, у вас имеется список идентификаторов работников в текстовом файле:

14562
67578
65888

$filep = "c:\file.txt"
$getNetworkID = Get-Content $filep | where { $_ -ne "" }
@("Employeeid") +  $getNetworkID | Set-Content  $filep -Force #add emplyeeidheader

Regex

Существуют ситуации, при которых вам для выполнения внутри своих сценариев операций установления соответствия требуется воспользоваться regex.

[Совет]
Совет

Для проверки любого regex перед его применением вы можете воспользоваться https://regex101.com/.

Вот как вы можете применять его в PowerShell и это будет в основном использоваться с операторами match. Смотрите Рисунок 10-6 и Рисунок 10-7.

$regexemail = "^\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$"
"sukhijav@techwizard.cloud" -match $regexemail

Рисунок 10-6

Отображение проверки регулярного выражения

Рисунок 10-7

Отображение операции регулярного выражения в PowerShell

Таблица 10-1. Шпаргалки регулярных выражений

№
Шпаргалка Regex
Комментарий

1

Receipt_[0-9][0-9][0-9][0-9][0-9][0-9][0-9]\.doc

Содержит Reciept_7didgitnumber.doc

2

(Tickets issued to)(.*)(for travel)

Выпущенные для Vikas Sukhija билеты на путешествие

3

(.*)Aborted_payment_(.*)

Сообщите aborted_payment_(Y075958)

4

(.*)(\([A-Z][0-9][0-9][0-9][0-9][0-9][0-9])\)

(Y782714)

5

(.*)[0-9]{2}[A-Z]{1}[0-9]{6}

Critical_alert_-_36B881478

6

(?<=V0)(.*)(?=a)

V01234a

7

^\d+$

Для поиска целого

8

^0+$

Для поиска целого с 000000

9

^\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$

Для адреса электронной почты

Выводы

Это последняя глава данной книги и она была о том, как вы можете сочетать различные фрагменты кода и составлять сценарий, который способен выполнять кучу дел. Я делюсь различными примерами продуктов, которые можно применять системным администраторам в их повседневной деятельности. Дополнительные сценарии и сотни примеров доступны в https://techwizard.cloud/downloads/.