Powershell 5: невозможно преобразовать значение в System.String - PullRequest
1 голос
/ 09 марта 2020

У меня есть сценарий PS, с помощью которого я построчно считываю файл CSV в переменную:

CSV:

  header1;header2
  column1;column2

PS Script:

#-------------------------
#   Func declarations    
#-------------------------
function myFunc{
   param(
    [Parameter(Mandatory=$true)][string]$param1,
    [Parameter(Mandatory=$true)][string]$param2
   )
   #Do something
}

#-------------------------
#       Run    
#-------------------------

$lines = Import-Csv .\etc\file.csv -Delimiter ";" -Header "header1","header2"

foreach($line in $lines) {
    myFunc -param1 $line.header1 -param2 $line.header1
}

Вызов myFunc -param1 $line.header1 выдает:

Cannot convert value To System.String (...) ParameterBindingArgumentTransformationException

Проверка типа $ line.header1 (или $ line.header2) с помощью $line.header1.GetType() возвращает как ожидалось System.string.

  • Если я удаляю один параметр (в зависимости от того, что произойдет), он работает
  • Если я удаляю определение типа для первого примерно так: [Parameter(Mandatory=$true)]$param1, первый признается, но второй является нулевым ...

Любая идея по этому вопросу будет высоко ценится

Спасибо

1 Ответ

1 голос
/ 09 марта 2020

Примечание: На момент написания этой статьи нет объяснения специфическим c симптомам, описанным в вопросе, и Сэнди сообщает, что их проблема решена.
Этот ответ обычно объясняет, при каких обстоятельствах вы будете см. ошибку Cannot convert value to type System.String при передаче аргумента в [string] -типированный параметр .


с вашей функцией примера, которая в силу использования атрибута [Parameter()] неявно является расширенная функция , есть только два способа, которыми может произойти сбой при передаче значения вашим [string] типизированным параметрам:

  • передача $null или пустая строка (например, '' или "") [1]

  • , передавая массив [2] вместо одного значения.

Если вы передадите значение любого другого типа, оно автоматически преобразуется в строку.

Учитывая полученное вами сообщение об ошибке, последнее должно быть проблемой, как показано здесь:

function myFunc { 
  param(
    [Parameter(Mandatory)] # NOTE: This makes the function an *advanced* function.
    [string] $param1
  )
  "[$param1]"
}

# FAILS, because an *array* can't be passed as a *single string*
# to an *advanced* function's [string] parameter.
myFunc -param1 'one', 'two'

Это да lds следующая ошибка:

Cannot process argument transformation on parameter 'param1'. 
Cannot convert value to type System.String

Невозможность передать массив в параметр [string] применяется только к расширенным функциям ( явная альтернатива сделать функцию неявно расширенной с помощью атрибута [Parameter() - поместить атрибут [CmdletBinding()] над блоком param(...)).

Простой (не продвинутая) функция принимает массив в качестве аргумента [string] и просто объединяет элементы массива с пробелами [3] при преобразовании; например,
'one', 'two' превращается в 'one two'

Примечание. Возможно, передача массива параметру [string] должна всегда потребовать преднамеренного действия со стороны вызывающего - оба чтобы подтвердить фактическое намерение передать массив и контролировать его строковое форматирование - таким образом, поведение продвинутых функций является наиболее разумным (за исключением того, что не применяется последовательно к коллекциям в целом ).
Однако учитывая приверженность PowerShell к обратной совместимости, поведение непродвинутых функций вряд ли изменится.


[1] Единственный способ разрешить эти значения должны сделать параметры не -обязательными, удалив свойство атрибута Mandatory=$true (или установив его в $false). Любопытно, что обязательные параметры [string] не принимают эти значения, даже когда намеренно переданы.

[2] Любопытно, что коллекции, которые технически не являются массивами (производные из [System.Array] / [object[]]), такие как [System.Collections.ArrayList] или [System.Collections.Generic.List[object]], принимаются и затем преобразуются в строку с непродвинутыми функциями.

[3] Технически, вы можете управлять символом разделителя (строкой) через переменную предпочтения $OFS.

...