Тип Powershell PSCustomObject - это еще один способ хранить структурированные данные наряду с массивами. Выбор в строну PSCustomObject более верен, когда нам нужно хранить не набор элементов, а объект. Кроме того этот объект будет быстрее работать.
Создание
Для создания объекта можно использовать два подхода. Первый работает с версии PS 3.0:
$object = [PSCustomObject]@{
Name = 'Alex'
Language = 'Powershell'
Country = 'Russia'
}
Либо использовать команду New-Object, но с большими данными он будет работать медленнее:
$object = New-Object PSObject -Property @{Name = 'Alex';
Language = 'Powershell';
Country = 'Russia'}
Если вы читали статью про создание hashtable в Powershell, то видели некоторые сложности с экспортом и форматированием обычных хэш таблиц, но использование PSCustomObject решает эти проблемы.
Доступ к данным можно получить так:
$object.Name
$object.'Name'
$value = 'Name'
$object.$value
Все эти способы работают одинаково.
Преобразование существующих hashtable
Если у вас уже создана хеш-таблица, то вы ее можете преобразовать следующим образом:
$hash_object = @{'Computer'='Sql1'; 'Administrator'='Dimitriy'; 'Date'=(Get-Date)}
$hash_object.GetType()
$ps_object = [pscustomobject]$hash_object
$ps_object.GetType()
Если попытаться вывести эти таблицы, то можно заметить разницу в отображении данных:
Один из минусов работы с такими объектами в том, что порядок свойств может поменяться. Вы так же не сможете передавать такой объект в качестве параметров и аргументов команды.
Сохранение в файл
Этот тип можно импортировать и экспортировать из файла работая с различными форматами.
CSV
Если вы пробовали сохранить хэш таблицу в CSV, то могли испытывать сложности с этим. Я читал, что это можно сделать, но с преобразованием в объект сделать это проще всего:
$ps_obj = @{'Name1'='Var1'; 'Name2'='Var2';'Name3'='Var3'}
[PSCustomObject]$ps_obj | Export-Csv -Path C:\ps_object.csv -Delimiter ',' -NoTypeInformation
На примере виден результат экспорта в CSV hashtable и csv:
С импортом таких данных проблем тоже нет:
$peobject = Import-Csv -Path C:\ps_object.csv -Delimiter ','
$peobject
$peobject.GetType()
JSON
Так же как и с hashtable вы можете конвертировать данные в Json с дальнейшим импортом и экспортом:
$pwobject = [pscustomobject]@{'Name'='Lera';'Age'=10;}
$pwobject | ConvertTo-Json | Set-Content -Path "C:\json.txt"
$pwobject = Get-Content -Path "C:\json.txt" -Raw | ConvertFrom-Json
$pwobject.GetType()
$pwobject
Этот способ работает и с хэш таблицами и с кастомными объектами:
$ps_xml = [PSCustomObject]@{'key'='val';'key1'=@{'key1'='val1';'key2'='val2'}}
Export-Clixml -Path "C:\ps_xml.cli" -InputObject $ps_xml
Import-Clixml -Path "C:\ps_xml.cli"
Изменение, добавление и удаление свойств
Мы не можем изменять объект так же как и с hashtable. При таких действиях мы получим ошибку:
$ps_xml = [PSCustomObject]@{'key'='val';}
$ps_xml['key'] = 'change'
$ps_xml
- Не удается индексировать в объект типа System.Management.Automation.PSObject.
- Unable to index into an object of type System.Management.Automation.PSObject.
Для добавления свойств нужно использовать команду Add-Member:
$ps_xml = [PSCustomObject]@{'key'='val';}
$ps_xml | Add-Member -MemberType NoteProperty -Name 'key2' -Value 'val2'
Так же и меняется значение:
$ps_xml = [PSCustomObject]@{'key'='val';}
$ps_xml | Add-Member -MemberType NoteProperty -Name 'key' -Value 'val2' -Force
Если вы забудете указать ключ Force, то получите ошибку:
- Add-Member : Не удается добавить элемент с именем "key", так как элемент с таким именем уже существует. Чтобы все равно перезаписать этот элемент, добавьте в команду параметр Force.
- Add-Member : Cannot add a member with the name "key3" because a member with that name already exists. To overwrite the member anyway, add the Force parameter to your command.
Когда нужно удалить свойство используется метод remove:
$ps_xml.psobject.properties.remove('key')
При попытке удалить несуществующее значение появится ошибка:
- Невозможно вызвать метод для выражения со значением NULL
- You cannot call a method on a null-valued expression.
Получение имен свойств
Мы можем вывести все свойства и методы у объекта таким же способом, каким получаем аналогичные данные у результатов команд:
$objects = [PSCustomObject]@{'PropertyName'='PropertyValue';}
$objects | Get-Member
Либо отобразить только имена:
$objects = [PSCustomObject]@{'PropertyName'='PropertyValue';}
$objects | Get-Member -MemberType NoteProperty | Select -ExpandProperty Name
Как вы можете заметить, что у нас не отображается метод, который удаляет значения. Часть методов, у этого типа объекта, скрыта.
Преобразование в hashtable
Выше мы уже рассматривали как сделать объект из обычно таблицы, но вам может понадобиться и обратное преобразование. Прямой возможности сделать этого нет и нам нужно добавлять такие значения в таблицу самостоятельно через цикл:
$myobject = [PSCustomObject]@{'DateToday'=(Get-Date); 'Month'=(Get-Date).Month;}
$hashtable = @{}
foreach( $property in $myobject.psobject.properties.name )
{
$hashtable[$property] = $myObject.$property
}
Проверка в условиях
Перед вызовом свойств обычно делается проверка на существование. Так мы можем выполнить проверку значения:
$myobject = [PSCustomObject]@{'DateToday'=(Get-Date); 'Month'=(Get-Date).Month;}
if ($null -ne $myobject.Month){'Ok'}
Либо использовать еще один скрытый метод:
if ($myobject.psobject.properties.match('Month')){'Ok'}
Создание своих методов у объектов
Мы можем создать свой метод у таких объектов. На примере ниже я добавил скрипт, который будет возвращать имена свойств:
$ptobject = [PSCustomObject]@{'SQL'='127.0.0.1'; 'Login'='TechSupport'}
# Скрипт, который будет вызывать при вызове метода
$ScriptBlock = {
$result = $ptobject | Get-Member -MemberType NoteProperty | Select -ExpandProperty Name
return $result
}
# Добавление параметров в объект
$memberParam = @{
MemberType = "ScriptMethod"
InputObject = $ptobject
Name = "TakeNames"
Value = $scriptBlock
}
Add-Member @memberParam
$ptobject | Get-Member
# Вызов метода
$ptobject.TakeNames()
Так же сработает и со скриптом, который преобразовываем объект в хэш таблицу:
$psobject = [PSCustomObject]@{'SQL'='127.0.0.1'; 'Login'='TechSupport'}
# Скрипт, который будет вызывать при вызове метода
$ScriptBlock = {
$hashtable = @{}
foreach( $property in $psobject.psobject.properties.name )
{
$hashtable[$property] = $psobject.$property
}
return $hashtable
}
# Добавление параметров в объект
$memberParam = @{
MemberType = "ScriptMethod"
InputObject = $psobject
Name = "ConvertToHashTable"
Value = $scriptBlock
}
Add-Member @memberParam
$psobject | Get-Member
# Вызов метода
$psobject.ConvertToHashTable()
Как в Powershell сменить пароль локального пользователя и AD
Объекты и ссылки
Возможно вы знаете, что переменные не хранят сами значения, а только ссылки на них. Это можно убедиться на следующем примере:
$a = 1
$b = $a
$b = 2
$b
$a
В момент объявления $b = $a они не начинают хранить по 1, а ссылаются на один и тот же элемент. Исходя из этой ситуации в примере ниже мы изменим значение объекта:
$a = [PSCustomObject]@{Val=3}
$b = $a
$b.Val = 2
$b
$a
psobject.copy()
Если мы хотим создать копию объекта, например для изменения, нужно использовать следующий метод:
$third = [PSCustomObject]@{Key=3}
$fourth = $third.psobject.copy()
$fourth.Key = 4
Таким образом у нас находятся два разных массива в памяти и изменение одного из них не повлияет на другой.
Изменения свойства TypeName
Если у созданного объекта мы выполним следующую команду, то увидим имя, которое было дано по умолчанию:
$val = [PSCustomObject]@{Key=3}
$val | Get-Member
Для его изменения мы можем использовать следующую команду:
$val.PSObject.TypeNames.Insert(0,"KeysObject")
Это можно сделать и при создании объекта:
$val = [PSCustomObject]@{
Key=3;
PSTypeName = 'Key.Object'}
$val | Get-Member
...
Подписывайтесь на наш Telegram канал
Теги: #powershell