Powershell 5:无法将值转换为 System.String

Powershell 5 : Cannot convert value To System.String

我有一个 PS 脚本,我用它逐行读取一个 csv 文件到一个变量中:

CSV 格式:

  header1;header2
  column1;column2

PS 脚本:

#-------------------------
#   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.GetType() returns 检查 $line.header1(或 $line.header2)的类型 System.string

为什么?

注意:在撰写本文时,问题中描述的具体症状没有任何解释,Sandy 报告他们的问题现已解决。
这个答案通常解释了在什么情况下您会看到 Cannot convert value to type System.String 将参数传递给 [string] 类型的参数时出错


对于您的示例函数,它通过使用 [Parameter()] 属性隐含地是一个 advanced function,只有两种方法可以将值传递给您的 [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'

这会产生以下错误:

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] 奇怪的是,技术上不是 arrays 的集合(派生自 [System.Array] / [object[]]),例如[System.Collections.ArrayList][System.Collections.Generic.List[object]] 接受,然后像非高级函数一样被字符串化。

[3] 从技术上讲,您可以通过 preference variable $OFS.

控制分隔符(字符串)