Глава 21. Часть 1 — Создание объектов и вывод данных объектами. PowerShell in depth — Don Jones, Richard Siddaway

в 19:53, , рубрики: powershell

Эта глава дает понимание «духа» PowerShell, его идеологии в области передачи данных по конвееру и является необходимой для понимания повершельного стиля программирования.

Глава 21. Создание объектов для вывода

в этой главе содержится:
«объектификация» вашего вывода
создание custom object (содержится информация как правильно создавать объекты в PoSh)
Работа с коллекциями свойств

В предыдущих главах мы показали Вам как создать простой скрипт и превратить его в функцию. Мы подчеркиваем что скрипты и функции должны выводить один, и только один тип данных, в нашем предыдущем простом примере мы использовали всего одну команду выводящую на выход только одни данные. Но вы несомненно попадете в ситуацию когда вам нужно выполнить несколько команд, скомбинировать их вывод и выдать эту комбинацию на выход функции или скрипта. Эта глава покажет вам, что основной целью создания объектов (в тексте custom objects) является объединение данных из нескольких объектов в один и последующий вывод из скрипта или функции. Ричард припоминает как на одной конференции был задан вопрос имеет ли PowerShell команду работающую подобно Union из SQL. В этой главе вы ближе познакомитесь с PowerShell потому что вы будете работать с объектами.

21.1 Почему на выходе объекты?
PowerShell производит только объекты. Объекты это единственное что может получится на выходе у скрипта (или фукнции, с этого места все что применимо к скрипту может быть применено и к функции). У вас может быть необходимость вывести только простое логическое значение (boolean), но это тоже объект. Дата — объект. Строка или символ — объект. Более комплексные данные, такие как детали процессора или сервиса, все они представлены как объекты.

отступление: Мы все еще видим как множество людей выводят данные строками вместо полноценных объектов из своих скриптов (прим переводчика — тоесть сцепляют данные в строку разделяя запятыми, и т.п.). Не делайте так. Вы должны всегда на выход выдавать объект. Если вы еще не знаете как задайте вопрос на форуме — попросите рассказать о выводе объектов.

вставка от переводчика — Стиль поша отличается от классического языка программирования, пош это язык администрирования, автоматики, и «управления большими блоками». Вам нужно стремится к максимальной простоте и понятности. Раньше, вы брали текстовый вывод команды и парсили ее, и это было правильно. В поше вы делаете объект и оперируете с объектом. Разница колоссальная.

Пример — вам надо посмотреть нетбиос и проанализировать некоторые данные. Ниже пош стайл:

# делаем функцию
Function Get-NBTName
{
    # получаем консольный вывод команды NBTSTAT, сразу же выкидываем ненужное
    $data=nbtstat /n | Select-String "<" | where {$_ -notmatch "__MSBROWSE__"}

    # обрезаем каждую строку от мусора
    $lines=$data | foreach { $_.Line.Trim() }

    # расщепляем кажду строку на массив элементов по пробелу
    # то что получилось помещаем в хэш таблицу формируя объект
    $lines | foreach { $temp=$_ -split "s+"
        [PSCustomObject]@{
        Name=$temp[0]
        NbtCode=$temp[1]
        Type=$temp[2]
        Status=$temp[3]
        }
    }
}

теперь делаем вызов функции, сортируем и после автоформатируем например так:

PS C:> Get-NBTName | sort type | Format-Table –Autosize

на выходе получаем:

Name NbtCode Type Status
---- ------- ---- ------
MYCOMPANY <1E> GROUP Registered
MYCOMPANY <00> GROUP Registered
MYCOMPANY <1D> UNIQUE Registered
CLIENT2 <00> UNIQUE Registered
CLIENT2 <20> UNIQUE Registered

Итого на выходе функции Get-NBTName объекты которые можно передавать, сортировать, делать выборку и т.п. Никаких for%%.

Можно возразить — ну и что, в начале ведь парсинг был. Ответ — в пошике вы парсите 1 раз — на входе от тулзы выдающей строки, а в командной строке вы парсите всегда, на выходе входе каждой функции. Вам придется делать парсинг каждый раз когда вы получаете вывод от nbtstat потом передаете это в ping потом пытаетесь сделать например tracert и каждый раз вам придется перебирать строки.

Объекты, всего лишь структуры данных которые PowerShell понимает и с которыми может работать. Разработчикам это говорить не нужно, и мы не будем разъяснять это.
Создание кастомного объекта позволяет следовать главному принципу — скрипт или функция должны выдавать только один вид объектов, например сформированный на основе нескольких разных вызовов WMI. Когда вам нужно вывести информацию которая поступила из нескольких источников, вам нужно создать объект в который нужно поместить эту информацию. Давайте сделаем скрипт предназначенный только для отчетности, предположим что вы ничего не хотите делать внутри, а хотите только собрать данные и передать дальше.
Мы используем четыре команды показанные в листинге 21.1. Каждая извлекает часть данных о компьютере (ограничимся localhost, но может работать на любом компьютере).

Совет: если вы создаете функцию использующую имя компьютера в качестве параметра, то используйте $Env:COMPUTERNAME по умолчанию, а не localhost или ".". Бывают случаи когда требуется имя машины, которое вы можете сразу получить из переменной окружения и сохранить дополнительные шаги в коде.

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

Листинг 21.1 Начальные команды

$os = Get-WmiObject –Class Win32_OperatingSystem –comp localhost
$cs = Get-WmiObject –Class Win32_ComputerSystem –comp localhost
$bios = Get-WmiObject –Class Win32_BIOS –comp localhost
$proc = Get-WmiObject –Class Win32_Processor –comp localhost | Select –First 1

последняя из четырех команд немного отличается. Первые три это операционная система, компьютерная система, и биос, они существуют по определению в одном экземпляре, процессор часто может быть не один. Поскольку все процессоры будут одинаковые мы делаем выборку Select –First 1. Windows Server 2003 и Windows XP будет возвращать один экземпляр класса Win32_Processor на ядро, поэтому следует помнить, что результаты использования этого класса будет варьироваться в зависимости от версии операционной системы.

Примечание. В хотфиксе доступно исправление этой проблемы для Windows Server 2003 на support.microsoft.com/kb/932370 учитывая ограниченное время оставшегося жизненного цикла этого продукта может быть не целесообразно ставить его.

Таким образом, каждый из наших четырех переменных содержит один объект. Это важно для следующей техники которую мы рассмотрим.
Совет. В PowerShell 3 и 4 у вас есть возможность пользоваться Common information model (CIM) командлеты вместо командлетов WMI. В примере этой главы не важно как вы получите данные — через WMI или CIM.

Вставка переводчика
PowerShell без WMI не полноценен, вся мощь пошика раскроется если использовать WMI (или CIM), в связке с удаленным исполнением команд. По заметке Сиддэвэя, если админ знает пош, но не знает WMI то он теряет до 60% мощности языка. Не знаю как это посчитано.

Итак, переменные заполнены, мы готовы вставлять их в наш код.

продолжение следует.

Автор: pak-nikolai

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js