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

    здесь перечислены разные способы создания объектов PowerShell. Даны советы и трюки. Текст великоват. Для всех изучающих пошик.

    Кроме удобства чтения, количество нажатий на клавиши, требования к сохранению порядка свойств, все эти методы по существу делают тоже самое. Несколько тонких различий: техника 1, хэш таблица. Как правило самая быстрая, техника 2 медленнее, техника 3 может быть значительно медленнее.

    В хорошей рецензии learn-powershell.net/2010/09/19/custom-powershell-objects-and-performance измерена скорость создания объектов выполненная MVP Boe Prox. Проводится сравнение скорости работы трех методов, работа Add-Member в 10 раз медленнее. Так что это плюс к технике 1. Мы не тестировали технику 4 как это делал Boe, но наши тесты показывают что техника 4 быстрее на 10% чем техника 1. Техника 5 должна быть использована в тех случаях когда типизация свойств имеет значение.


    Сам перевод:

    21.2 Синтаксис для создания пользовательских объектов
    Мы часто говорили, что всегда есть несколько способов сделать что-либо в PowerShell, и это, верно для пользовательских объектов. Мы покажем вам все основные пути, потому что вы, наверняка столкнетесь с ними в жизни, мы хотим, чтобы вы могли распознать их и использовать их, когда вы захотите.

    Глава 21.1 Техника номер 1. Использование хеш таблиц для создания кастомных объектов.

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

    # Собираем какието данные, в последующем нам нужно это скомпоновать и вывести
    $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
    
    # Хэш таблица. Описывает свойства будущего объекта
    $props = @{OSVersion=$os.version
    Model=$cs.model
    Manufacturer=$cs.manufacturer
    BIOSSerial=$bios.serialnumber
    ComputerName=$os.CSName
    OSArchitecture=$os.osarchitecture
    ProcArchitecture=$proc.addresswidth}
    
    # Создаем объект из хэш таблицы и выводим
    $obj = New-Object –TypeName PSObject –Property $props
    Write-Output $obj
    


    выполнив этот код вы получите результат подобный этому:

    Manufacturer : Microsoft Corporation
    OSVersion : 6.3.9600
    OSArchitecture : 64-bit
    BIOSSerial : 036685734653
    ComputerName : RSSURFACEPRO2
    Model : Surface Pro 2
    ProcArchitecture : 64
    


    Т.к. на выходе у вас объект имеющий более четырех свойств PowerShell сделал вывод на экран в виде списка. Вы могли бы выполнить

    Write-Output $obj | ft
    


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

    Manufacturer=$cs.manufacturer
    


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

    Преимущество этого подхода в том что легко построить хэш таблицу на лету и создать из нее много пользовательских объектов. Вы можете заметить что в выходном объекте свойства имеют не тот же самый порядок как они были определены в таблице. Одно из возможных решений — создать форматирование для кастомного объекта (специальный XML файл описывающий как выводить на экран, в каком порядке и т.п.) или, если вы используете powershell 3 и выше, то можно использовать свойство ordered

    $props = [ordered]@{ OSVersion=$os.version
    Model=$cs.model
    Manufacturer=$cs.manufacturer
    BIOSSerial=$bios.serialnumber
    ComputerName=$os.CSName
    OSArchitecture=$os.osarchitecture
    ProcArchitecture=$proc.addresswidth}
    


    Все остальное тоже самое. Теперь свойства объекта будут отображаться в том порядке как они были записаны. Если вы передадите $obj на Get-Member, вы увидете что это PS-CustomObject.

    Примечание PowerShell по умолчанию не отслеживает порядок элементов в хэш таблице. Вот почему когда вы видете окончательный вывод его свойства идут не в том порядке в каком вы их создавали. Начиная с PowerShell 3 вы можете исправить это использовав атрибут [ordered]. Это создает упорядоченный словарь (другое название хэш таблиц) и поддерживает порядок элементов в ней.

    21.2.2 Техника 2. Использование Select-Object
    Этот метод был фаворитом в PowerShell v1, и мы по прежнему видим людей использующих его. Нам она не нравится поскольку ее гораздо сложнее читать. Следующий листинг показывает технику где мы создадим пустой объект, а затем запишем значения этих свойств

    Листинг 21.3. Создание объекта используя Select-Object
    # Наши четыре неизменные четыре команды
    $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-Object
    $obj = 1 | Select-Object ComputerName,OSVersion,OSArchitecture, ProcArchitecture,Model,Manufacturer,BIOSSerial
    
    # заполняем поля
    $obj.ComputerName = $os.CSName
    $obj.OSVersion = $os.version
    $obj.OSArchitecture = $os.osarchitecture
    $obj.ProcArchitecture = $proc.addresswidth
    $obj.BIOSSerial = $bios.serialnumber
    $obj.Model = $cs.model
    $obj.Manufacturer = $cs.manufacturer
    Write-Output $obj
    


    Обратите внимание, что в листинге 21.3 было сделано $obj = 1, по существу значение 1 никогда не будет использовано.

    СОВЕТ Вы увидите много примеров, когда пустая строка используют в качестве инициализатора: $obj="" | select .... Это просто способ определить $obj как объект, закинуть в конвеер что-то, чтобы перейти к Select-Object, который и сделает всю работу.

    В этом подходе есть недостаток. Подадим $obj в Get-Member и посмотрим на результат.

    PS C:\> $obj | Get-Member
    TypeName: Selected.System.Int32
    Name MemberType Definition
    ---- ---------- ----------
    Equals Method bool Equals(System.Object obj)
    GetHashCode Method int GetHashCode()
    GetType Method type GetType()
    ToString Method string ToString()
    BIOSSerial NoteProperty System.String BIOSSerial=
    ComputerName NoteProperty System.String ComputerName= WIN-KNBA0R0TM23
    Manufacturer NoteProperty System.String Manufacturer= VMware, Inc.
    Model NoteProperty System.String Model= VMware Virtual Platform
    OSArchitecture NoteProperty System.String OSArchitecture= 64-bit
    OSVersion NoteProperty System.String OSVersion= 6.1.7601
    ProcArchitecture NoteProperty System.UInt16 ProcArchitecture=64
    

    Свойства на месте, но TypeName может привести к проблемам или даже просто путанице, все зависит от того что вы еще намереваетесь делать с этим объектом. Мы рекомендуем избегать эту технику.

    вставка от переводчика
    Здесь имеет в виду вот что:
    подадим в Get-Member пример из листинга 21.2 — где мы создавали хэш таблицей
    image

    теперь подадим на GM пример из листинга 21.3 — создание через Select-Object
    image


    21.2.2 Техника 3. Использование Add-Member
    Этот метод считается формальным. Мы считаем что он иллюстрирует то что происходит в жизни с формальными подходами. Он наиболее дорогостоящий в вычислительном отношении, медленее всех, так что не часто встретишь людей использующих его в реальной жизни. Это наиболее общий подход PowerShell v1. Есть две вариации, и сначала листинг с кодом.

    Листинг 21.4. Создание объекта используя Add-Member
    # Наши четыре неизменные четыре команды
    $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
    
    # создаем объект указав его тип
    $obj = New-Object –TypeName PSObject
    
    # добавляем поля указав тип и значение
    $obj | Add-Member NoteProperty ComputerName $os.CSName
    $obj | Add-Member NoteProperty OSVersion $os.version
    $obj | Add-Member NoteProperty OSArchitecture $os.osarchitecture
    $obj | Add-Member NoteProperty ProcArchitecture $proc.addresswidth
    $obj | Add-Member NoteProperty BIOSSerial $bios.serialnumber
    $obj | Add-Member NoteProperty Model $cs.model
    $obj | Add-Member NoteProperty Manufacturer $cs.manufacturer
    Write-Output $obj
    

    Мы создали PSObject и добавляем по одному свойству к нему за раз. Вам нужно вызвать метод каждый раз когда вы добавляете NoteProperty которая содержит только статическое значение. Для сокращения кода мы использовали позиционные параметры Add-Member. Если использовать полный синтаксис то каждый оператор Add-Member будет выглядеть следующим образом

    Add-Member -MemberType NoteProperty -Name ComputerName -Value $os.CSName
    

    вы видите что получается очень много кода.

    Вариация этого метода заключается в использовании парамера -PassThru (сокращенно -Pass в листинге 21.5) команды Add-Member. Этот параметр поместит модифицированный объект обратно в конвеер, так что вы сможете передать его на следующую команду и так далее.

    Покажем на примере

    Листинг 21.4. Создание объекта используя Add-Member с параметром -PassThru
    # Наши четыре неизменные четыре команды
    $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
    
    # создаем объект указав его тип
    $obj = New-Object –TypeName PSObject
    
    # создаем свойства
    $obj | Add-Member NoteProperty ComputerName $os.CSName –pass |
    Add-Member NoteProperty OSVersion $os.version –pass |
    Add-Member NoteProperty OSArchitecture $os.osarchitecture –Pass |
    Add-Member NoteProperty ProcArchitecture $proc.addresswidth –pass |
    Add-Member NoteProperty BIOSSerial $bios.serialnumber –pass |
    Add-Member NoteProperty Model $cs.model –pass |
    Add-Member NoteProperty Manufacturer $cs.manufacturer
    Write-Output $obj
    


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

    вставка переводчика
    имеет в виду что отладка легче


    21.2.4 Техника 4. Использование декларации типа

    Это одна из вариаций техники 1, работает только в PowerShell v3 и v4, этот метод компактнее. Вы начинаете с тойже хэш таблицы.
    # Наши четыре неизменные четыре команды
    $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
    
    $obj = [pscustomobject]@{
                             OSVersion=$os.version
                             Model=$cs.model
                             Manufacturer=$cs.manufacturer
                             BIOSSerial=$bios.serialnumber
                             ComputerName=$os.CSName
                             OSArchitecture=$os.osarchitecture
                             ProcArchitecture=$proc.addresswidth
                             }
    Write-Output $obj
    


    Вы могли бы продолжать заполнять переменную $props, трюк этой техники в том что порядок свойств в объекте будет сохранен также как будто мы использовали директиву [ordered]

    Совет. Тип который мы используем это PSCustomObject. Вы должны использовать этот тип потому что в .NET терминах вы используете конструктор PSObject без параметров. Не пытайтесь сократить код указав вместо PSCustomObject объект PSObject, вы не получите нужного результата.

    Вы могли заметить, что предыдущие методы добавляют свойства в другом порядке чем вы их добавляете. В технике 1 например мы не добавили Computer_Name первым, но он был бы выведен первым в списке. Не беспокойтесь, в подавляющем большинстве случаев PowerShell работает со свойствами в любом порядке. Техника 4 сохраняет порядок свойств, если вам это нужно используйте ее.

    21.2.5 Техника 5. Создание нового класса

    Не часто используемая техника. Она дает некоторые преимущества в обработке на конвеере. Может быть оценена как продвинутая техника, не все повершельщики захотят вникать в .NET. Но возможность доступна в виде опции

    Листинг 21.7 Создание объекта используя класс
    $source=@"
    public class MyObject
    {
    public string ComputerName {get; set;}
    public string Model {get; set;}
    public string Manufacturer {get; set;}
    public string BIOSSerial {get; set;}
    public string OSArchitecture {get; set;}
    public string OSVersion {get; set;}
    public string ProcArchitecture {get; set;}
    }
    "@
    Add-Type -TypeDefinition $source -Language CSharpversion3
    
    # наши четыре команды
    $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
    
    $props = @{OSVersion=$os.version
    Model=$cs.model
    Manufacturer=$cs.manufacturer
    BIOSSerial=$bios.serialnumber
    ComputerName=$os.CSName
    OSArchitecture=$os.osarchitecture
    ProcArchitecture=$proc.addresswidth}
    $obj = New-Object –TypeName MyObject –Property $props
    Write-Output $obj
    


    Листинг 21.7 начинается с создания записи содержащей C# код описания класса. Класс имеет имя, MyObj и делает ряд описаний свойств класса. В этом примере свойства указаны как строки, но допускается смешивать типы. И хотя мы не собираемся записывать устанавливать свойства в будущем, определение класса требует записи GET и SET, в противном случае PowerShell выдаст исключение.

    Add-Type используется для компиляции класса, после чего мы можем использовать его вместо PSObject. Для установки свойств объекта может быть использована техника представленная здесь и в листинге 21.6:
    $obj = [MyObject]@{OSVersion=$os.version
                                       Model=$cs.model
                                       Manufacturer=$cs.manufacturer
                                       BIOSSerial=$bios.serialnumber
                                       ComputerName=$os.CSName
                                       OSArchitecture=$os.osarchitecture
                                       ProcArchitecture=$proc.addresswidth
                                       }
    

    проведем тестирование в Get-Member
    PS C:\> $obj | get-member
    TypeName: MyObject
    Name MemberType Definition
    ---- ---------- ----------
    Equals Method bool Equals(System.Object obj)
    GetHashCode Method int GetHashCode()
    GetType Method type GetType()
    ToString Method string ToString()
    BIOSSerial Property string BIOSSerial {get;set;}
    ComputerName Property string ComputerName {get;set;}
    Manufacturer Property string Manufacturer {get;set;}
    Model Property string Model {get;set;}
    OSArchitecture Property string OSArchitecture {get;set;}
    OSVersion Property string OSVersion {get;set;}
    ProcArchitecture Property string ProcArchitecture {get;set;}
    


    Этот более громоздкий, но имеет и свои преимущества. Если вы объявите свойство как строку и попытаетесь записать туда число то будет сгенерировано сообщение об ошибке.

    21.2.6 Какие различия???

    Кроме удобства чтения, количество нажатий на клавиши, требования к сохранению порядка свойств, все эти методы по существу делают тоже самое.

    Несколько тонких различий: техника 1, хэш таблица. Как правило самая быстрая, особенно когда вы работаете с несколькими объектами, техника 2 немного медленнее, техника 3 может быть значительно медленнее.

    В хорошей рецензии learn-powershell.net/2010/09/19/custom-powershell-objects-and-performance измерена скорость создания объектов выполненная MVP Boe Prox. Проводится сравнение скорости работы трех методов, работа Add-Member в 10 раз медленнее. Так что это плюс к технике 1. Мы не тестировали технику 4 как это делал Boe, но наши тесты показывают что техника 4 быстрее на 10% чем техника 1. Техника 5 должна быть использована в тех случаях когда типизация свойств имеет значение.
    Поделиться публикацией
    Похожие публикации
    • Программист 1С
      от 70 000 до 100 000 руб.
      Компания БКС Новосибирск Полный рабочий день
    • DeVops инженер
      от 60 000 руб.
      ГисАвто Novosibirsk Новосибирск Полный рабочий день
    • QA engineer
      от 70 000 руб.
      Tickets Cloud Москва Полный рабочий день
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама
    Комментарии 0

    Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.