Я пытаюсь создать PSCustomObject с несколькими свойствами, которые являются ArrayLists, содержащими PSCustomObjects. Я также добавляю родительский объект в ArrayList. Идея состоит в том, чтобы создать отношение, которое я могу легко преобразовать в yml или другой формат. Например,
Hosts: # Parent ArrayList
- HostName: myhost # Start of Parent Object
FQDN: myhost.my.domain.com
IPs: # ArrayList of Objects, Property of Parent Object
- IP: 192.168.1.2 # Start of Child Object
MAC: 00:00:00:00:00:00
- IP: 10.10.1.1 # Start of Child Object
Records: # ArrayList of Objects, Property of Parent Object
- Zone: 192.168.1 # Start of Child Object
RRType: PTR
Source: 2
Target: myhost.my.domain.com
TTL: 2H
- Zone: my.domain.com # Start of Child Object
RRType: A
Source: myhost.my.domain.com
Target: 192.168.1.2
TTL: 2H
Проблема, с которой я сталкиваюсь, заключается в том, что когда я пытаюсь добавить новый объект в одно из свойств ArrayList родительского объекта, я получаю следующую ошибку:
Method invocation failed because [System.Management.Automation.PSCustomObject] does not contain a method named 'add'.
At C:\merge.ps1:96 char:13
+ ,$_.DNSRecords.Add($RecordObj)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (add:String) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound
Я использую эту функцию для создания хостов:
function New-HostEntry {
param (
[Parameter(ValueFromPipeline=$true,position=0)]$HostName,
[Parameter(ValueFromPipeline=$true,position=1)]$FQDN,
[Parameter(ValueFromPipeline=$true,position=2)]$IP,
[Parameter(ValueFromPipeline=$true,position=3)]$MAC,
[Parameter(ValueFromPipeline=$true,position=4)]$RecordObj
)
$IPS = New-Object System.Collections.ArrayList
if ($IP){
$IPEntry = [PSCustomObject]@{
IP = $IP
MAC = $MAC
}
$IPS.Add($IPEntry)
}
$DNSRecords = New-Object System.Collections.ArrayList
if ($RecordObj){
$DNSRecords.Add($RecordObj)
}
[PSCustomObject]@{
HostName = $HostName
FQDN = $FQDN
IPs = $IPS
DNSRecords = $DNSRecords
}
}
В основной части скрипта я создаю родительскую коллекцию и добавляю в нее хосты со следующим:
[System.Collections.ArrayList]$hosts= @()
$hosts.add((New-HostEntry -HostName $hostname -FQDN $fqdn -IP $ip -MAC $mac -RecordObj $RecordObj))
Иногда значения IP, MAC или RecordObj могут быть нулевыми или отсутствовать. Это не имеет значения при первоначальном создании нового объекта Host и добавлении его в коллекцию.
Позже к существующему объекту Host (внутри $Hosts ArrayList) может потребоваться добавить $RecordObj:
Add-DNSRecordToHost $_.HostName $RecordObj
Это пример RecordObj:
$RecordObj = [PSCustomObject]@{
Zone = $zonename
Source = $Source
TTL = $TTL
RRType = $RRType
Preference = $Preference
Target = $Target
Comment = $Comment
}
Наконец, это функция, которая терпит неудачу:
function Add-DNSRecordToHost{
param (
[Parameter(ValueFromPipeline=$true,position=0)]$HostName,
[Parameter(ValueFromPipeline=$true,position=1)]$RecordObj
)
$found = $false
#Get the host with matching HostName
$hosts | Where-Object {$_.HostName -eq $HostName} | ForEach-Object {
#Compare each record already on the host to the new record
Write-host "Checking" $_.HostName "for" $RecordObj.Zone $RecordObj.RRType "record ..."
foreach ($DNSRecord in $_.DNSRecords){
if ( -not (Compare-Object $DNSRecord.PSObject.Properties $RecordObj.PSObject.Properties) ) {
#objects match
Write-Host "ERROR: Zone Record" $RecordObj.Zone "already exists on " $HostObj.Host -ForegroundColor Yellow
$found = $true
}
}
#If none of the records match add the new record to the host
if (!$found){
Write-Host "ACTION: Adding Zone Record" $RecordObj.Zone "to" $_.HostName -ForegroundColor Cyan
#Write-Host $DNSRecords.toString()
$_.DNSRecords.Add($RecordObj)
#,$_.DNSRecords.Add($RecordObj)
#$DNSRecords = $_.DNSRecords; $DNSRecords.add($RecordObj); $_.DNSRecords = $DNSRecords
#$_.DNSRecords | %{ Write-Host $_.Zone $_.Source $_.TTL $_.RRType $_.Preference $_.Target $_.Comment -ForegroundColor Yellow }
}
}
}
Я оставил (но закомментировал) свои попытки отладки.
Примечание. Я также пытался передать функции объект $host, но это также не удалось:
function Add-DNSRecordToHost{
param (
[Parameter(ValueFromPipeline=$true,position=0)]$Host,
[Parameter(ValueFromPipeline=$true,position=1)]$RecordObj
)
$found = $false
foreach ($DNSRecord in $Host.DNSRecords){
if ( -not (Compare-Object $DNSRecord.PSObject.Properties $RecordObj.PSObject.Properties) ) {
$found = $true
}
}
if (!$found){
$Host.DNSRecords.Add($RecordObj)
}
}
$hosts | % {Add-DNSRecordToHost $_ $RecordObj}
Возникает ошибка, когда я пытаюсь добавить $RecordObj в свойство DNSRecords объекта Host. Я ожидаю, что свойство DNSRecords будет ArrayList, но, согласно приведенному выше сообщению об ошибке, оно было преобразовано в PSCustomObject. Почему он меняется, и как я могу правильно добавить к нему?
$host.DNSRecords
определялось какArrayList
, из-за чего, вероятно, и возникает ошибка. - person Santiago Squarzon   schedule 02.07.2021$DNSRecords = New-Object System.Collections.ArrayList
и добавляю его в PSCustomObject как свойствоDNSRecords = $DNSRecords
Вы предлагаете мне изначально создать свойство как пустой список массивов, добавить в него переданную запись (если она существует), затем вернуть созданный объект Host? - person mcgheee   schedule 02.07.2021$NewHost= [PSCustomObject]@{DNSRecords = New-Object System.Collections.ArrayList}
, а затем добавить к нему $RecordObj с помощьюif ($RecordObj){NewHost.DNSRecords.Add($RecordObj)}
, а затемreturn $NewHost
, но я все еще вижу то же поведение при попытке добавить к нему $RecordObj. - person mcgheee   schedule 02.07.2021$host.DNSRecords
не являетсяArrayList
, иначе у вас не должно быть этой конкретной ошибки. Если у вас есть сомнения, вы можете попробовать$host.DNSRecords.GetType()
и убедиться в этом сами. - person Santiago Squarzon   schedule 02.07.2021$_.DNSRecords.GetType()
после$_.DNSRecords.Add($RecordObj)
(что выдает ошибку), и GetType() возвращается как PSCustomObject. Это именно мой вопрос. Если я создаю свойство DNSRecords как пустой ArrayList при создании объекта $host, почему оно меняется на PSCustomObject? - person mcgheee   schedule 02.07.2021