Powershell Select-Object -expandproperty странное поведение, когда ввод является массивом и содержит свойства массива

Я пытаюсь создать файл отчета, собирая данные из разных источников. Я построил структуру отчетности следующим образом:

$Data = import-csv "some CSV FILE"
<#
csv file must look like this
hostname,IP
server1,192.168.1.20
#>

Затем я создаю объект массива, предварительно заполненный "начальными значениями", и присоединяю его к своей переменной $data

$Ids = ('7.1.1.1','7.1.1.2')
$CheckObj= @()
foreach ($id in $IDs) {
    $row = "" | Select-Object CheckID,CheckData,CheckDataRaw
    $row.CheckID = $id
    $row.CheckData = "NotChecked"
    $CheckObj+= $row
    }


$Data = $Data | Select *,CheckData

$data | % {$_.CheckData = $CheckObj}

Полученный объект:

hostname  : server1
ip        : 192.168.1.20
CheckData : {@{CheckID=7.1.1.1; CheckData=NotChecked; CheckDataRaw=}, 
            @{CheckID=7.1.1.2; CheckData=NotChecked; CheckDataRaw=}}

Все хорошо, пока я не хочу сделать это:

$FinalReport = $data | Select-Object -Property * -ExpandProperty Checkdata

Я получаю все эти ошибки, которые, скажем, я могу игнорировать...

Select-Object : The property cannot be processed because the property 
"CheckData" already exists.
At line:1 char:24
+ ... lReport = $data | Select-Object -Property * -ExpandProperty Checkdata
+                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (@{hostname=serv...ystem.Objec 
   t[]}:PSObject) [Select-Object], PSArgumentException
    + FullyQualifiedErrorId : AlreadyExistingUserSpecifiedPropertyExpand,Micro 
   soft.PowerShell.Commands.SelectObjectCommand

НО, весь набор других переменных изменяется, например:

$data | fl


hostname  : server1
ip        : 192.168.1.1
CheckData : {@{CheckID=7.1.1.1; CheckData=NotChecked; CheckDataRaw=; 
            hostname=server1; ip=192.168.1.1}, @{CheckID=7.1.1.2; 
            CheckData=NotChecked; CheckDataRaw=; hostname=server1; 
            ip=192.168.1.1}}

а также переменная $CheckObj

$CheckObj


CheckID      : 7.1.1.1
CheckData    : NotChecked
CheckDataRaw : 
hostname     : server1
ip           : 192.168.1.1

CheckID      : 7.1.1.2
CheckData    : NotChecked
CheckDataRaw : 
hostname     : server1
ip           : 192.168.1.1

Это совершенно непреднамеренно с моей стороны... Может кто-то уточнить, что я делаю не так?

Я использую PowerShell 5.0 в Windows 7. Все тестирование проводилось с использованием powershell_ise, и я не изменил ни одного из значений по умолчанию PowerShell.

Я ожидаю, что переменная $Final Report будет содержать расширенное содержимое, а не все переменные, которые я использовал в процессе...

1 ответ

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

Я использую простые назначения $b = $a, которые кажутся мелкой копией. Таким образом, любое изменение в $ b также влияет на объект $ a и наоборот.

Для моей цели мне нужны отдельные копии данных, кажется, решение состоит в том, чтобы сделать глубокое копирование, аналогичное решению этого поста: PowerShell полностью копирует массив

Таким образом, рабочий код, который дает мне желаемый результат, будет:

    Function Copy-Object ($Source,[switch]$DeepCopy) {
        # Serialize and Deserialize data using BinaryFormatter
        if ($DeepCopy) {
            $ms = New-Object System.IO.MemoryStream
            $bf = New-Object System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
            $bf.Serialize($ms, $Source)
            $ms.Position = 0

            #Deep copied data
            $Target = $bf.Deserialize($ms)
            $ms.Close()
            Write-Output $Target
            }
        Else {
            Write-Output $Source
            }
        }


$Data = "" | select hostname,IP
$data.Hostname = "server1"
$data.IP = "192.168.1.10"

$Ids = ('7.1.1.1','7.1.1.2')
$CheckObj= @()
foreach ($id in $IDs) {
    $row = "" | Select-Object CheckID,CheckData,CheckDataRaw
    $row.CheckID = $id
    $row.CheckData = "NotChecked"
    $CheckObj += $row
    }


$Data = Copy-Object -source $Data -DeepCopy | Select *,CheckData2

$Data | % {$_.CheckData2 = Copy-Object -source $CheckObj -DeepCopy}

$FinalReport = Copy-Object -source $Data -DeepCopy | Select-Object -Property hostname,IP -ExpandProperty Checkdata2
$FinalReport  | ft

выходное значение:

CheckID CheckData  CheckDataRaw hostname IP          
------- ---------  ------------ -------- --          
7.1.1.1 NotChecked              server1  192.168.1.10
7.1.1.2 NotChecked              server1  192.168.1.10
Другие вопросы по тегам