Ошибка при создании нового объекта PSObject - PullRequest
1 голос
/ 13 апреля 2020

Этот сценарий powershell берет до 8 строк в файле csv и объединяет их в одну строку, дублируя столбцы, а затем сохраняя их в файле результатов (первый файл результатов сохраняется нормально). Если в csv есть 16 строк, то это означает, что нужно сохранить второй файл результатов и т. Д. c.

, например, в rows.csv:

first_field second_field 3rd_field 2nd_field

мяч летучая мышь ракетка клуб

оранжевый банан человек go груша

В результате1.csv:

первый1 второй1 третий1 четвертый1 первый2 второй2 третий2 четвертый2

мяч летучая мышь рэкет-клуб оранжевый банан человек go груша

Я получаю сообщение об ошибке:

New-Object : Cannot convert 'System.Object[]' to the type 'System.Collections.IDictionary' required by parameter 'Property'. Specified method is not supported.
At C:csv.ps1:19 char:42
+ $results = New-Object PSObject -Property $details
+                                          ~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [New-Object], ParameterBindingException
    + FullyQualifiedErrorId : CannotConvertArgument,Microsoft.PowerShell.Commands.NewObjectCommand

Обратите внимание, что первое создание нового объекта работало нормально в строке 16. В PowerShell ISE, если я перезапущу Сценарий это ошибки в строке 16 тоже. Я понятия не имею, что здесь не так, но предположим, что мне нужно уничтожить PSObject после сохранения каждого файла CSV?

$csvObjects = import-csv C:\rows.csv
$results = @()
$counter=1
foreach ($item in $csvObjects){
    $detailsnew = [ordered] @{            
        "first$counter" = $item.'First_field'          
        "second$counter" = $item.'Second_field'           
        "third$counter"  = $item.'Third_field'
        "fourth$counter" = $item.'Fourth_field'
    }   
    $details  +=  $detailsnew 
    # modulus comparison returns remainder - write out file every 8
    if ($counter % 8 -eq 0) {
        if ($counter -eq 8) {
            #works on line below on first run but fails on subsequent runs within Powershell ISE
            $results = New-Object PSObject -Property $details 
        }

        if ($counter -eq 16) {
            # fails on line below
            $results2 = New-Object PSObject -Property $details
        }

        $quotient = $counter / 8
        $results | export-csv -Path c:\result"$quotient".csv -noType
        $details = @()
        $results = @()
    }                     
    $counter++           
}
#write out final file if number not divisible by 8
if (-not($counter % 8 -eq 0)) {
    $results += New-Object PSObjectF -Property $details
    $modulo = $counter % 8
    $quotient_plus1 = (($counter-$modulo) / 8) +1
    $results | export-csv -Path C:\result"$quotient_plus1".csv -noType 
}

1 Ответ

4 голосов
/ 13 апреля 2020

tl; др

  • $details = @() должно быть $details = [ordered] @{}

  • Для выполнения повторных выполнений от ИСП работа по назначению, место другое $details = [ordered] @{} заявление до л oop.


  • В самой первой итерации l oop, $details изначально undefined , а $details += $detailsnew назначает таблицу $detailsnew (упорядоченную) ha sh ( [ordered] @{ ... } га sh таблица в PowerShell имеет тип System.Collections.Specialized.OrderedDictionary) как есть до $details (то есть с $details undefined, += эффективно ведет себя так же, как =).

  • Таблицы $detailsnew ha sh, созданные в следующих 7 итерациях, затем объединяются на += в таблица ha sh уже сохранена в $details.

  • После 8-й итерации вы по ошибке (ре) инициализируете $details как массив ( @()), который является источником проблемы: последующее использование += затем добавляет новый элемент массива * 10 От 61 * до $details вместо объединения записей таблицы ha sh и передачи array вместо таблицы ha sh (или любого типа словаря, который реализует System.Collections.IDictionary) к параметру New-Object -Property, то, как и ожидалось, происходит сбой.

    • Вместо этого (re) -initialize $details как упорядоченная таблица ha sh: $details = [ordered] @{}

В PowerShell ISE, если я перезапущу сценарий, он также выдает ошибки в строке 16.

PowerShell ISE dot-sources скрипты, которые он запускает , что означает, что переменные из предыдущих вызовов могут задерживаться .

В качестве отступления: это в равной степени относится к Коду Visual Studio с его расширением PowerShell , которое следует рассмотреть при переходе на [ 1] . Тем не менее, там вы можете создать новый временный сеанс вместо , как описано в нижнем разделе этот ответ .

В вашем случае это означает, что $details уже является массивом в самой первой итерации, когда вы повторно выполняете сценарий в ISE.


[1] ISE PowerShell равен более не активно развивается и есть причины не использовать его (нижняя часть).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...