Я много читал об этом в StackOverflow, Microsoft и других источниках, но изо всех сил пытался разобраться в создании и добавлении объектов в массивы. Большинство примеров, которые я могу найти, слишком упрощены и содержат только целые числа или простые значения. Я знаю, что это не лучший способ ниже, но это просто пример того, что я пытаюсь сделать в данном случае. Мне нужно что-то, что я могу вывести в CSV, что будет иметь что-то вроде следующего, и наиболее эффективным способом (очевидно, += это плохо):
OUDN,Inheritancetype,etc
OU=Test,Whatever
OU=Test,Whatever
OU=Brush,Thing
OU=Brush,Whatever
$OUACLResults = @()
$OUs = Get-ADOrganizationalUnit -Filter *
foreach ($OU in $OUs)
{
# additional question, I like doing it this way so I can easily use intellisense to complete the attributes like $OU.distinguishedname, is there an easy way to do this when piping?
$OUACLs = (get-ACl ad:\$OU.Distinguishedname).access
Foreach ($ACL in $OUACLs)
{
#example of other work required, this is doing a lookup in table $ObjectTypeGUID
$ObjectType = $ObjectTypeGUID.Item($ACL.ObjectType)
$Object = new-object -typename psobject
Add-Member -inputobject $Object -membertype noteproperty -name "OUDN" -value $OU.distinguishedname
Add-Member -inputobject $Object -membertype noteproperty -name "Inheritancetype" -value $ACL.Inheritancetype
Add-Member -inputobject $Object -membertype noteproperty -name "ObjectType" -value $ObjectType
#and so on for other attributes
#next line particularly inefficient
$OUACLResults += $Object
}
}
Судя по тому, что я видел, приведенная выше часть $object кажется эффективной (хотя передача по конвейеру и использование foreach-obj может быть лучше), но добавление $object в $OUACLResults не работает:
#tried
$OUACLresults = @{}
$OUACLResults.add($object)
#no overload for Add and argument count "1"
И воспользуйтесь этим руководством: gist.github.com/kevinblumenfeld/…
В ответ на вопрос Почему мне следует избегать использования оператора присваивания увеличения (+=) для создания коллекции, я дал полное объяснение того, почему «очевидно +=
это плохо» и шаги, необходимые для исправления вашего сценария.
+=
не так ли...
@iRon, я прочитал ваш ответ, но (вероятно, по моей вине) с трудом смог применить свой пример, вероятно, главным образом потому, что помещать все в конвейер казалось слишком сложным. Мне следовало упомянуть об этом в своем вопросе, поскольку ваш ответ привел меня к расследованию неэффективности +=. Спасибо :-)
@{}
создает хеш-таблицу — неупорядоченный словарь — вместо этого вам нужно создать список:
$OUACLResults = [System.Collections.Generic.List[psobject]]::new()
Затем в теле цикла:
$OUACLResults.Add($object)
Кроме того, использование сокращенного синтаксиса [pscustomobject]@{ ... }
для создания объектов обычно происходит намного быстрее, чем New-Object
+ Add-Member
:
$object = [pscustomobject]@{
OUDN = $OU.distinguishedname
Inheritancetype = $ACL.Inheritancetype
ObjectType = $ObjectType
}
Спасибо, это привело меня туда, куда мне нужно было.
это не обязательно рабочий скрипт, он приведен для примера работы с массивами. UPD https://learn.microsoft.com/ru-ru/powershell/module/microsoft.powershell.core/about/about_arrays?view=powershell-7.4#manipulated-an-array заменить +=
$OUACLResults = @()
$OUs = Get-ADOrganizationalUnit -Filter *
foreach ($OU in $OUs)
{
# additional question, I like doing it this way so I can easily use intellisense to complete the attributes like $OU.distinguishedname, is there an easy way to do this when piping?
$OUACLs = (get-ACl ad:\$OU.Distinguishedname).access
Foreach ($ACL in $OUACLs)
{
#example of other work required, this is doing a lookup in table $ObjectTypeGUID
$ObjectType = $ObjectTypeGUID.Item($ACL.ObjectType)
#$Object = new-object -typename psobject
$array = "" | Select OUDN, Inheritancetype, ObjectType
#Add-Member -inputobject $Object -membertype noteproperty -name "OUDN" -value $OU.distinguishedname
$array.OUDN = $OU.distinguishedname
#Add-Member -inputobject $Object -membertype noteproperty -name "Inheritancetype" -value $ACL.Inheritancetype
$array.Inheritancetype = $ACL.Inheritancetype
#Add-Member -inputobject $Object -membertype noteproperty -name "ObjectType" -value $ObjectType
$array.ObjectType = $ObjectType
#and so on for other attributes
write-host $array #for debug
#next line particularly inefficient
#$OUACLResults += $array
$OUACLResults.add($array)
}
}
Как описано в вопросе, +=
— не самая эффективная операция для добавления элементов.
Забавно, но это действительно Learn.microsoft.com/ru-ru/powershell/module/…
Чтобы ответить на комментарий:
@iRon, я прочитал ваш ответ, но (вероятно, по моей вине) с трудом смог применить свой пример, вероятно, главным образом потому, что помещать все в конвейер казалось слишком сложным. Мне следовало упомянуть об этом в своем вопросе, поскольку ваш ответ привел меня к расследованию неэффективности +=. Спасибо :-)
По сути, это шаги, которые необходимо выполнить для исправления сценария:
$OUACLResults =
$OUACLResults = foreach ...
+=
задания$OUACLResults +=
Результат (не удалось/не удалось полностью протестировать):
$OUs = Get-ADOrganizationalUnit -Filter *
$OUACLResults = foreach ($OU in $OUs) {
$OUACLs = (get-ACl ad:\$OU.Distinguishedname).access
Foreach ($ACL in $OUACLs) {
$ObjectType = $ObjectTypeGUID.Item($ACL.ObjectType)
$Object = new-object -typename psobject
Add-Member -inputobject $Object -membertype noteproperty -name "OUDN" -value $OU.distinguishedname
Add-Member -inputobject $Object -membertype noteproperty -name "Inheritancetype" -value $ACL.Inheritancetype
Add-Member -inputobject $Object -membertype noteproperty -name "ObjectType" -value $ObjectType
$Object
}
}
Поскольку командлет Add-Member
довольно многословен и дорог, я рекомендую просто создавать новые объекты PSCustomObject
следующим образом:
$OUs = Get-ADOrganizationalUnit -Filter *
$OUACLResults = foreach ($OU in $OUs) {
$OUACLs = (get-ACl ad:\$OU.Distinguishedname).access
Foreach ($ACL in $OUACLs) {
$ObjectType = $ObjectTypeGUID.Item($ACL.ObjectType)
[PSCustomObject]@{
OUDN = $OU.distinguishedname
Inheritancetype = $ACL.Inheritancetype
ObjectType = $ObjectType
}
}
}
Попробуйте это:
$Object = [PSCustomObject]@{ OUDN = $OU.distinguishedname; Inheritancetype = $ACL.Inheritancetype; ObjectType = $ObjectType }