Windows PowerShell — это командная оболочка, обеспечивающая выполнение объектно-ориентированных сценариев на базе инфраструктуры Microsoft. NET Framework. В основе этой технологии лежат составные команды PowerShell — компактные команды, выполняющие определенные действия и возвращающие тот или иной объект. NET. Составные команды PowerShell дают возможность обращаться к целому ряду систем и выполнять многочисленные задачи, связанные с этими системами. Однако совершение определенных действий с помощью одних только составных команд не всегда возможно. Для выполнения этих действий часто приходится создавать собственные объекты на базе классов. NET. К числу типов. NET-объектов, которые могут создаваться пользователем, относятся пользовательские объекты. Пользовательский объект позволяет нам определять типы данных, назначаемые этому объекту, а также задавать действия, которые он может выполнять. Разобравшись с тем, как создаются пользовательские объекты, вы получите мощный инструмент, который позволит дополнительно расширить возможности PowerShell.
Надо сказать, что вопросы, связанные с технологией. NET Framework и объектно-ориентированным программированием, довольно сложны и выходят за рамки настоящей статьи. Но чтобы понять, в чем состоит объектно-ориентированная природа технологии PowerShell, было бы полезно получить представление хотя бы об основах упомянутых концепций. Более подробные сведения о платформе. NET Framework можно найти в статье MSDN «Overview of the. NET Framework» (http://msdn.microsoft.com/en-us/library/zw4w595w.aspx). С общей информацией по объектно-ориентированному программированию вы можете ознакомиться в статье MSDN «Object-Oriented Programming (C# and Visual Basic)» (http://msdn.microsoft.com/en-us/library/vstudio/dd460654.aspx).
Создание пользовательских объектов
Чтобы создать пользовательский объект в среде PowerShell, необходимо первым делом сформировать первоначальный объект с помощью команды New-Object. Эта команда дает возможность формировать объекты. NET и COM на базе подборки классов. Пользовательский объект представляет собой особый тип объектного класса. NET, созданный на базе. NET-классов Object или PSObject. В том, что касается формирования первоначального объекта, между этими двумя классами нет никакой разницы. Однако, как правило, удобнее использовать класс PSObject, поскольку при добавлении свойств к объекту, построенному на базе класса Object, могут возникать определенные проблемы. Поэтому давайте будем пользоваться классом PSObject.
Чтобы создать объект на базе класса PSObject, необходимо выполнить команду New-Object с параметром -TypeName и указать в качестве параметра значения класс PSObject. Делается это так:
$system = New-Object -TypeName PSObject
При выполнении этой команды будет создан объект PSCustomObject, который далее будет ассоциирован с переменной $system. В большинстве случаев ассоциация объекта с переменной желательна, так как при этом появляется удобная возможность для работы с элементами данного объекта. Элементами являются компоненты, составляющие тот или иной объект, такие, как свойства, методы, свойства «псевдоним», а также числовые множества.
При работе с объектами в среде PowerShell пользователи сталкиваются со свойствами и методами. Свойство описывает тот или иной аспект объекта. Так, к числу элементов класса FileInfo. NET относится свойство Length, которое отображает размер файла в байтах. Если вы создадите объект FileInfo на базе этого класса, то сможете использовать свойство Length для определения размера файла, ассоциированного с данным объектом. Метод осуществляет некое действие, имеющее отношение к данному объекту. Так, в состав класса FileInfo входит метод Delete, который используется для удаления файла, представленного данным объектом.
Возможность быстрого определения элементов того или иного объекта облегчает работу с ним. Для получения списка элементов, составляющих объект, мы можем воспользоваться командой Get-Member. Например, чтобы просмотреть список элементов нового объекта, ассоциированного с переменной $system, мы можем передать переменную $system по конвейеру команде Get-Member:
$system | Get-Member
Как показано на рисунке 1, созданный вами объект базируется на классе System.Management.Automation.PSCustomObject, в состав которого входит лишь небольшое число элементов, причем все они являются методами. Но именно по этой причине объект и именуется пользовательским — вы можете настроить его, добавляя те или иные элементы.
Рисунок 1. Список элементов нового объекта |
Перед тем как приступить к разъяснению процесса добавления элементов, я хотел бы отметить, что в состав класса PSCustomObject (как, впрочем, и многих других классов. NET) входит ряд скрытых элементов различных типов, таких, как memberset и codeproperty. Список этих элементов вы можете отобразить, если при вызове команды Get-Member включите в нее параметр -Force. Описание скрытых элементов остается за рамками данной статьи, но в будущем вы, возможно, сочтете полезным познакомиться со скрытыми элементами класса PSCustomObject и других. NET-классов, дабы получить доступ ко всем возможностям объектов PowerShell.
Добавление свойств к пользовательскому объекту
Польза, которую мы можем извлечь из пользовательского объекта, сводится к преимуществам, получаемым от элементов, ассоциированных с этим объектом. Вы можете дополнить пользовательский объект несколькими элементами различных типов. В рассматриваемом примере мы будем дополнять объект элементами NoteProperty и ScriptMethod. Элемент NoteProperty аналогичен обычному свойству, а элемент ScriptMethod напоминает обычный метод. Возможность пополнения пользовательского объекта обычным свойством или методом не предусмотрена, и именно поэтому вы будете задействовать элементы NoteProperty и ScriptMethod. Сведения об элементах, применение которых допускается в пользовательских объектах, приведены в материале «Add-Member» ресурса PowerShell TechNet (http://technet.microsoft.com/en-us/library/hh849879.aspx).
Начнем с добавления пары элементов NoteProperty к объекту $system. Для добавления элементов мы можем воспользоваться командой Add-Member; она дает возможность задавать имена и значения свойств. Предположим для примера, что вы хотите добавить комментарии на основе данных, полученных с помощью встроенных в PowerShell средств WMI (Windows Management Instrumentation). WMI обеспечивает инфраструктуру для управления данными и операциями в операционных системах Windows. Объектная модель WMI включает в себя многочисленные классы, позволяющие выполнять широкий спектр операций управления. Так, класс Win32_OperatingSystem обеспечивает доступ к таким данным, как имя установленной на компьютере операционной системы и название последнего пакета обновлений, примененного к этой операционной системе.
Если вы хотите создать объект WMI, воспользуйтесь командой Get-WmiObject и укажите нужный класс. К примеру, чтобы создать WMI-объект Win32_OperatingSystem и связать его с переменной $os, нужно ввести следующий код:
$os = Get-WmiObject Win32_OperatingSystem
В данном случае вы считываете системную информацию с локального компьютера, но вся прелесть инструментария WMI состоит в том, что он позволяет также обращаться к удаленным компьютерам Windows и управлять ими.
В дальнейшем вы сможете использовать переменную $os для обращения к сведениям, возвращенным данным объектом. Связывание объекта с переменной указанным образом фиксирует данные, полученные в соответствующий момент времени. К примеру, если новый пакет обновлений применяется к операционной системе после создания вами переменной $os, свойство объекта CSDVersion не будет отражать соответствующее изменение, поскольку объект был в свое время создан на основе первоначальных данных.
После того как вы определите переменную $os, нужно будет сформировать две команды Add-Member. Каждая из этих команд принимает четыре параметра:
- InputObject. Параметр -InputObject используется для идентификации объекта, получающего новые свойства. В данном случае потребуется определить объект $system.
- MemberType. Параметр -MemberType указывает на тип создаваемого элемента, поэтому вам следует указать NoteProperty.
- Name. Параметр -Name применяется для указания имени нового элемента. В контексте нашего примера давайте присвоим первому элементу имя OperatingSystem, а второму — имя ServicePack.
- Value. Этот параметр указывает значение элемента. Для первого свойства вам нужно использовать параметр $os.Caption, чтобы получить имя операционной системы. Для второго свойства следует использовать параметр $os.CSDVersion; в результате будет возвращено имя последнего пакета обновлений, примененного к операционной системе.
Две команды Add-Member имеют следующий вид:
Add-Member -InputObject $system -MemberType NoteProperty ` -Name OperatingSystem -Value $os.Caption Add-Member -InputObject $system -MemberType NoteProperty ` -Name ServicePack -Value $os.CSDVersion
Обратите внимание: каждую команду Add-Member я расположил на двух строках. В обоих случаях в конце первой строки я поставил символ обратной кавычки (`), тем самым извещая процессор PowerShell о том, что код команды продолжается на следующей строке.
Выполнив команды Add-Member, вы можете вызывать переменную $system для просмотра ее содержимого:
$system
Примерные результаты показаны на рисунке 2.
Рисунок 2. Содержимое переменной $system |
Переменную $system можно использовать и для вызова индивидуальных элементов. Для этого просто укажите имя переменной, затем поставьте точку и введите имя элемента. К примеру, следующая команда возвращает свойство OperatingSystem:
$system.OperatingSystem
Одно из преимуществ, достигаемых при создании пользовательских объектов, состоит в том, что они позволяют создавать свойства на базе данных, поступающих из различных источников, а также свойства, значения которых представляют собой заданную строку. Взгляните для примера на код в листинге 1, который дополняет объект $system тремя новыми свойствами.
Большинство элементов, представленных в листинге 1, уже знакомы вам по предыдущему примеру. Однако отметим, что данный код создает экземпляр класса Win32_PhysicalMemory, связанного с переменной $mem, и экземпляр класса Win32_DiskDrive, связанного с переменной $disk. Два из добавленных свойств используют эти новые объекты WMI в качестве источников данных.
Первая команда Add-Member считывает данные из свойства $mem.Capacity, которое отражает объем памяти на целевой системе. Однако в этом случае параметр -Value несколько сложнее, нежели тот, что был представлен в предыдущем примере. Во-первых, команда содержит символы «{0:N2}», за которыми следует -f, — а это конструкция. NET, используемая для форматирования выходного числа. В сущности, это означает, что число необходимо возвратить с двумя знаками после запятой. За командами форматирования следует краткое выражение ($mem.Capacity/1GB), обозначающее деление значения Capacity на 1 Гбайт. Значение Capacity отражает значение памяти в байтах. PowerShell облегчает перевод байтов в гигабайты простым делением на 1 Гбайт. Наконец, команда помечает строку ' GB' (включая пробел) для вывода и заключает все символы в скобки.
Вторая команда Add-Member, сформированная в соответствии с той же логикой, возвращает объем жесткого диска компьютера. Она возвращает объем диска в байтах с помощью свойства $disk.Size и затем преобразует его в гигабайты.
Третья команда Add-Member добавляет новое свойство Owner и назначает ему строковое значение janetp. В данном случае owner может означать что угодно — главный пользователь, последний пользователь, администратор, — или иметь иное значение, которое вы пожелаете назначить данному свойству. Я привожу его здесь лишь для того, чтобы показать, что вы можете добавить свойство, значение которого представляет собой простую строку.
Добавив к пользовательскому объекту все три элемента, вы можете вновь вызвать переменную $system. Она возвратит результаты, подобные представленным на рисунке 3.
Рисунок 3. Свойства, добавленные с помощью составной команды Add-Member |
Итак, мы получили единый объект, который содержит данные, извлеченные из трех различных объектов WMI. Кроме того, новый объект имеет свойство Owner, основанное на строковом значении. Это свойство вызывается так же, как и любой другой элемент:
$system.Owner
Нетрудно догадаться, что команда возвращает значение janetp. Однако пользователь может заменить это значение другим, назначив свойству новое значение — скажем, вот так:
$system.Owner = «rogert»
В данном случае свойству Owner присваивается значение rogert. И если теперь пользователь вызовет данное свойство, будет возвращено это новое значение.
Как и при решении множества других задач в среде PowerShell, существует целый ряд различных способов дополнения пользовательского объекта новыми элементами. Так, в версии PowerShell 3.0 пользователь может создать хеш-таблицу и передать хеш команде New-Object. Код в листинге 2 создает все те же пять свойств, но имена элементов и их значения передаются с помощью хеш-таблицы.
Этот код сначала создает хеш-таблицу, определяющую пять пар свойство/значение, каждая из которых соответствует свойствам. Как видно из кода, пары свойство/значение следует отделять друг от друга с помощью точки с запятой. Кроме того, набор из пяти пар свойство/значение необходимо заключать в фигурные скобки и перед открывающей скобкой ставить символ @. Наконец, хеш-таблицу нужно связать с переменной $info.
После определения таблицы хеширования код с помощью составной команды New-Object создает объект на базе класса PSObject и связывает его с переменной $system. Только на этот раз команда включает в себя параметр -Property, который принимает переменную $info в качестве значения.
Наконец, код вызывает переменную $system, и последняя возвращает результаты, подобные показанным на рисунке 4. Обратите внимание на порядок, в котором свойства были добавлены к объекту. Одна из проблем, возникающих при использовании таблицы хеширования, состоит в том, что пользователь не может определять их порядок. Для управления порядком необходимо пользоваться командой Add-Member при добавлении каждого элемента.
Рисунок 4. Свойства, созданные с помощью таблицы хэширования |
Добавление методов в пользовательский объект
Итак, мы видим, насколько просто решаются такие задачи, как добавление свойств, оценка их значения, а также изменение этих значений. Перейдем теперь к работе с методами. Это дело несколько более сложное, ведь методы должны выполнять некоторые операции, и вам нужно описывать эти операции в процессе формулирования значения метода.
Пример. Код в листинге 3 создает метод, который считывает текущую дату, а также время и возвращает их как в первоначальном формате, так и в формате UTC.
Для улучшения читаемости кода вы можете присвоить значение этого метода переменной (скажем, переменной $method). Это значение включает в себя выражения, необходимые для возвращения сведений о дате и времени. Однако для того чтобы передать упомянутое значение команде Add-Member, вы должны определить его в виде блока сценария. Для этого содержимое значения заключается в фигурные скобки. Далее PowerShell присвоит это значение в его текущей форме переменной в виде объекта ScriptBlock.
В листинге 3 значение метода включает в себя два выражения. Первое выражение возвращает текущую дату и время, а второе — те же данные в формате UTC. Первое выражение начинается с команды Get-Date; она считывает сведения о текущей дате и времени, которые вы присваиваете переменной $a. Отметим, что при вызове команды Get-Date вы должны включать параметр -Format наряду со значением F. В результате PowerShell получит указание отобразить отметку времени в формате «полная дата и время» — скажем, Monday, August 19, 2013 12:28:25 PM. Далее вам нужно дополнить значение переменной строкой «Local:» (вместе с пробелом); в результате будут возвращены текущая дата и время вместе с данной меткой.
Во втором выражении нужно подобным образом начать с команды Get-Date. Она возвратит значение текущей даты и времени, которое вы присвоите переменной $b. Далее вы воспользуетесь методом ToUniversalTime для возвращения даты и времени в формате UTC и зададите свойство DateTime, чтобы данные были возвращены в корректном формате.
Если бы в этот момент вам нужно было вызвать переменную $method, она возвратила бы два ранее заданных выражения в виде строк, то есть в том виде, в каком они были введены с клавиатуры. Значение переменной было определено вами как блок сценария, и именно по этой причине команды не обрабатываются в момент их связывания с переменной $method. Дело в том, что переменная $method формируется как объект ScriptBlock, в чем вы можете убедиться с помощью метода GetType, который считывает тип переменной:
$method.GetType()
Чтобы иметь возможность работать с блоком сценария, нужно после определения переменной $method добавить упомянутый метод в качестве элемента объекта $system. Проблема решается путем формирования команды Add-Member, которая определяет ScriptMethod в качестве типа, GetUTC в качестве имени, а переменную $method указывает в качестве значения.
Выполнив код в листинге 3, вы сможете использовать переменную $system для вызова метода GetUTC практически таким же образом, как вызывали свойства:
$system.GetUTC()
Впрочем, надо отметить, что при вызове метода сценария необходимо включать скобки — как и при вызове любого иного метода, даже если вы не передаете каких-либо аргументов. Теперь метод должен возвращать результаты, аналогичные тем, что представлены на рисунке 5, с тем отличием, что при вызове данного метода возвращаются дата и время.
Рисунок 5. Примерные результаты выполнения метода GetUTC() |
В реальной жизни вы, вероятно, будете стремиться создавать методы, способные выполнять более сложные задачи. Скажем, в методы сценария объекта $system можно включить задачи управления WMI. Если вы пойдете по этому пути, следует всесторонне протестировать избранный метод. Вы должны убедиться, что команды выполняют задачи в строгом соответствии с вашим замыслом. И PowerShell, и WMI являются мощными инструментами, и при управлении компьютерами Windows их нужно использовать со всей осторожностью.
Добавление пользовательских объектов к массиву
Пользовательские объекты применяются не только в качестве автономных объектов, с которыми можно работать по принципу «на один раз». Такие объекты можно включать в состав массивов и обращаться к ним через эти массивы. Допустим, вы хотите обработать данные, полученные от нескольких компьютеров. Эти данные могут включать в себя сведения о памяти и о логических дисках, имеющихся в соответствующих системах. В таком случае возможность манипулировать упомянутыми данными в среде PowerShell нужным вам образом придется весьма кстати. Благодаря объектно-ориентированной природе упомянутой оболочки введение требуемых данных в объекты часто представляет собой наиболее простой способ работы с этими данными.
Рассмотрим действия пользователя на примере. В контексте настоящей статьи способ сбора информации о различных компьютерах не имеет особого значения. Вы можете, к примеру, организовать в среде PowerShell цикл foreach, внутри которого к считыванию информации с различных рабочих станций будут привлекаться средства WMI. Итак, для краткости изложения мы не будем касаться вопроса о методах, использованных для сбора данных. Предположим, что вы собрали требуемые данные (представленные на рисунке 6) в текстовый файл с разделителями в виде запятых.
Рисунок 6. Собранные данные WMI |
Текстовый файл включает в себя строку заголовка, а также строку для каждого логического накопителя системы. Так, в первой строке данных описываются характеристики логического накопителя C компьютера ws01. Емкость этого накопителя составляет 500 Гбайт, из которых 225 Гбайт свободны. Кроме того, система оснащена памятью емкостью 4 Гбайт. Вторая строка содержит данные о том, что рассматриваемый компьютер оснащен логическим накопителем D той же емкости, что и накопитель C, но объем свободного пространства на нем составляет 320 Гбайт.
Цель состоит в том, чтобы превратить каждую строку данных в собственный пользовательский объект, а затем включить такие объекты в массив. После этого вы сможете выполнять над этими объектами действия, для чего соответствующие данные нужно будет передавать по конвейеру другим командам PowerShell. Код в листинге 4 определяет пустой массив, импортирует данные из текстового файла, после чего с помощью цикла foreach создает объекты и включает их в состав массива.
Как видите, первый шаг состоит в создании пустого массива (@()) и в связывании его с переменной $SystemInfo. Позднее вы будете включать в состав этого массива пользовательские объекты.
Далее вы будете импортировать данные в переменную $SourceData с помощью составной команды Import-CSV. Пусть в нашем примере текстовый файл называется SourceData.txt и сохраняется в папке C:\DataFiles. Команда Import-CSV считывает каждую строку как автономный объект и сохраняет его в переменной $SourceData. На данном этапе вы можете использовать переменную как инструмент для обращения к данным, но у вас не будет возможности управлять элементами, включенными в объект, и вы не сможете добавлять элементы.
Итак, следующий шаг состоит в том, чтобы создать цикл foreach, который даст вам возможность формировать пользовательский объект для каждой строки текстового файла. Как определяет условие цикла foreach (переменная $source в $SourceData), в процессе прохождения кода по циклу foreach каждая строка $SourceData должна поочередно связываться с переменной $source. Логика, заданная в блоке сценария foreach (заключенном в фигурные скобки), будет выполняться по одному разу для каждой строки, и при этом в ходе каждой итерации будет применяться новый объект $source. Более подробные сведения о формировании цикла foreach можно найти в теме PowerShell TechNet about_ForEach (http://technet.microsoft.com/en-us/library/hh847816.aspx).
Присмотримся внимательнее к блоку сценария foreach. Его первая команда создает исходный объект и сохраняет его в переменной $system, как было показано в предыдущих примерах. Далее переменная $system передается по конвейеру команде Add-Member с тем, чтобы та создала первое свойство note property. Здесь мы имеем дело с форматом, несколько отличающимся от использованного ранее. На этот раз параметр -InputObject не включается в команду Add-Member; вместо этого переменная $system просто пересылается по конвейеру упомянутой команде. Результаты ее выполнения совпадают с теми, что были получены в предыдущих примерах. Я применил новый формат лишь для того, чтобы продемонстрировать еще один способ, с помощью которого мы можем добавлять элементы в среде PowerShell.
В качестве значения команды Add-Member мы используем переменную $source; она вызывает свойство Computer, которое соответствует полю Computer в исходных данных. Вторая команда Add-Member функционирует таким же образом, только данные она считывает из свойства DeviceID. Обратите внимание: свойство Memory в число используемых этой командой свойств не входит. В процессе создания пользовательских объектов вы можете опускать те или иные свойства либо располагать их в произвольном порядке.
Третья команда Add-Member работает почти так же, как первые две — с той лишь разницей, что она обращается к свойству DriveSize. Поскольку замысел пользователя может состоять в том, чтобы вводить полученные данные не в строковом формате, а в виде цифрового значения, команда явным образом преобразует их в число. Для этого перед именем свойства вводятся символы [int] (это означает, что требуются данные типа int), после чего все выражение свойства заключается в скобки.
Четвертая команда Add-Member выполняет несколько иную задачу. Она формирует вычисляемый элемент, представляющий разность значений DriveSize и FreeSpace; иначе говоря, вычисляется объем занятого пространства. И здесь перед именем свойства вводятся символы [int], а все выражение заключается в скобки. Возможность создавать вычисляемые свойства — одна из главных причин, побуждающих пользователей формировать пользовательские объекты.
Последняя команда Add-Member работает так же, как и третья, только данные в этом случае считываются из свойства FreeSpace.
Наконец, последняя команда в блоке сценария foreach добавляет текущий объект $system в массив $SystemInfo. Обратите внимание на то, что здесь используется оператор +=; таким образом система гарантирует, что с каждой итерацией цикла в массив добавляется новый объект $system, причем возможность записи поверх старых данных исключается.
По выполнении кода из листинга 4 вы можете вызывать переменную для просмотра ее содержимого. На рисунке 7 показана часть списка данных, включаемых ныне в массив $SystemInfo. Точнее говоря, на рисунке представлены первые семь объектов массива, что соответствует первым семи строкам данных в исходном текстовом файле. Каждая группа данных представляет один из объектов, включенных в массив $SystemInfo. Вы можете удостовериться в том, что создали массив объектов, используя метод GetType, который возвратит тип переменной:
$SystemInfo.GetType()
Рисунок 7. Данные, хранимые в массиве $SystemInfo |
Если эта команда возвратит значение BaseType of System.Array, это будет означать, что переменная $SystemInfo действительно является массивом объектов, способным содержать пользовательские объекты. Далее эту переменную можно будет задействовать для выполнения нужных вам операций. Так, вы сможете по конвейеру передать переменную команде Sort-Object, дабы расположить данные в порядке убывания по значениям FreeSpace:
$SystemInfo | Sort FreeSpace -Descending
В данном случае команда, указывая псевдоним Sort, обращается к составной команде Sort-Object; при этом она включает свойство FreeSpace и параметр -Descending. Как показано на рисунке 8, теперь объекты перечислены в соответствии со значениями FreeSpace, причем первые позиции в списке занимают накопители, обладающие наибольшим объемом свободного пространства. И опять-таки отображается только часть списка.
Рисунок 8. Данные, отсортированные в соответствии с объемом свободного пространства |
Сортировать данные можно и в соответствии с показателями нескольких столбцов. К примеру, вы можете отсортировать данные сначала по свойству Computer, а затем по свойству FreeSpace в порядке убывания:
$SystemInfo | Sort Computer, FreeSpace -Descending
Понятно, что теперь вы получите совсем другие результаты, как показано на рисунке 9.
Рисунок 9. Данные, отсортированные по именам компьютеров и объему имеющегося свободного пространства в?порядке убывания |
Одно из следствий применения такого метода сортировки столбцов состоит в том, что значения Computer, а также значения FreeSpace отображаются в порядке убывания. Команда Sort-Object не предусматривает простого способа сортировки информации таким образом, чтобы данные из одного столбца отображались в порядке возрастания, а данные другого столбца — в порядке убывания. Если вы используете параметр -Descending, все данные будут отсортированы в порядке убывания. Однако можно обойти это ограничение, для чего необходимо для каждого свойства создать выражения, задающие порядок сортировки соответствующих данных. Так, следующая команда обеспечивает сортировку данных сначала по свойству Computer в порядке возрастания, а затем по свойству FreeSpace в порядке убывания:
$SystemInfo | Sort ` @{Expression=«Computer»; Descending=$false}, @{Expression=«FreeSpace»; Descending=$true}
Первое выражение Sort-Object присваивает свойству Expression значение Computer, а свойству Descending значение $false. Второе выражение присваивает свойству Expression значение FreeSpace, а свойству Descending — значение $true. Переменные $true и $false являются встроенными системными переменными, которые могут принимать булевы значения true и false, выражаемые единицей и нулем соответственно. Затем следует заключить каждое выражение в фигурные скобки и ввести перед ним символ @. Теперь данные можно сортировать в желаемом порядке, как показано на рисунке 10.
Рисунок 10. Данные, отсортированные в порядке возрастания по столбцу Computer Name и в порядке убывания по столбцу Amount of Free Space |
Кто-то может сказать, что теме сортировки данных я уделил слишком много внимания, но эта операция хорошо иллюстрирует широкие возможности работы с объектами в массиве. И, конечно же, вы не ограничены применением составной команды Sort-Object. Еще один пример: следующая команда передает по конвейеру переменную $SystemInfo составной команде Where-Object:
$SystemInfo | Where DriveSize -gt 250 | Sort FreeSpace -Descending
В этом примере команда обращается к составной команде Where-Object с помощью псевдонима Where. Кроме того, она указывает, что в число результатов будут включаться только те значения DriveSize, которые превосходят 250. В среде PowerShell символы -gt используются в качестве оператора «больше, чем» (greater than). Результаты, соответствующие указанному критерию, передаются по конвейеру команде Sort-Object, которая обеспечивает отображение данных в заданном порядке.
Вы можете даже передать отсортированные данные команде Select-Object. Делается это так:
$SystemInfo | Where DriveSize -gt 250 | Sort FreeSpace -Descending | Select -First 5
Эта команда, использующая составную команду Select-Object (вызываемую с помощью псевдонима Select), возвращает только пять первых строк результирующего набора. Как видите, добавляя пользовательские объекты в массив $SystemInfo, мы получаем целый ряд средств для работы с этими объектами.
Широкие возможности пользовательских объектов
В большинстве случаев создание пользовательских объектов в среде PowerShell не составляет труда. Если и можно говорить о тех или иных сложностях, то они, как правило, связаны с выражениями значения, определяемыми пользователем для свойств, или с методами сценария. Выражения, встречающиеся в упомянутых в статье примерах, относительно просты по сравнению с выражениями, которые вы можете создавать средствами PowerShell. Но как бы то ни было, представленный здесь материал послужит вам основой, необходимой для формирования пользовательских объектов. При эффективном использовании последние могут стать мощными компонентами составляемых вами сценариев PowerShell вне зависимости от того, для каких целей вы их применяете — создаете индивидуальные объекты и добавляете их в массивы или используете каким-либо иным способом. Вы можете, например, создавать пользовательские объекты внутри своего профиля PowerShell, чтобы они были под рукой всякий раз, когда вы начинаете новый сеанс. Как применять пользовательские объекты в сценариях — решать вам. Но знайте, что эти объекты представляют собой эффективные и гибкие инструменты, которые способны удовлетворить многие потребности, возникающие в процессе работы со сценариями.
Листинг 1. Код, добавляющий три новых свойства с помощью составной команды Add-Member
$mem = Get-WmiObject Win32_PhysicalMemory $disk = Get-WmiObject Win32_DiskDrive Add-Member -InputObject $system -MemberType NoteProperty ` -Name PhysicalMemory ` -Value ((«{0:N2}» -f ($mem.Capacity/1GB)) + ' GB') Add-Member -InputObject $system -MemberType NoteProperty ` -Name DiskSize ` -Value ((«{0:N2}» -f ($disk.Size/1GB)) + ' GB') Add-Member -InputObject $system -MemberType NoteProperty ` -Name Owner -Value «janetp»
Листинг 2. Код, в котором пять свойств создаются с помощью хеш-таблицы
$info = @{ «OperatingSystem» = $os.Caption; «ServicePack» = $os.CSDVersion; «PhysicalMemory» = ((«{0:N2}» -f ($mem.Capacity/1GB)) + ' GB'); «DiskSize» = ((«{0:N2}» -f ($disk.Size/1GB)) + ' GB'); «Owner» = 'janetp' } $system = New-Object -TypeName PSObject -Property $info $system
Листинг 3. Код, создающий метод
$method = { $a = Get-Date -Format F; «Local:» + $a; $b = Get-Date; «UTC:» + $b.ToUniversalTime().DateTime } Add-Member -InputObject $system -MemberType ScriptMethod ` -Name GetUTC -Value $method
Листинг 4. Код, превращающий строки данных в пользовательские объекты и включающий их в состав массива
$SystemInfo = @() $SourceData = Import-CSV C:\DataFiles\SourceData.txt foreach ($source in $SourceData) { $system = New-Object -TypeName PSObject $system | Add-Member -Type NoteProperty ` -Name Computer -Value $source.Computer $system | Add-Member -Type NoteProperty ` -Name DeviceID -Value $source.DeviceID $system | Add-Member -Type NoteProperty ` -Name DriveSize -Value ([int]$source.DriveSize) $system | Add-Member -Type NoteProperty ` -Name UsedSpace ` -Value ([int]$source.DriveSize — $Source.FreeSpace) $system | Add-Member -Type NoteProperty ` -Name FreeSpace -Value ([int]$source.FreeSpace) $SystemInfo += $system }