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

San*_*ndy 3 powershell powershell-5.0

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

CSV :

  header1;header2
  column1;column2
Run Code Online (Sandbox Code Playgroud)

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
}
Run Code Online (Sandbox Code Playgroud)

电话 myFunc -param1 $line.header1抛出一个:

无法将值转换为 System.String (...) ParameterBindingArgumentTransformationException

检查 $line.header1(或 $line.header2)的类型$line.header1.GetType()并按预期返回System.string

  • 如果我删除一个参数(无论哪个),它就可以工作
  • 如果我像这样删除[Parameter(Mandatory=$true)]$param1第一个上的类型定义 : ,第一个被识别,但第二个为空...

为什么?

mkl*_*nt0 5

Note: As of this writing, there's no explanation for the specific symptoms described in the question, and Sandy reports their problem as now resolved.
This answer generally explains under what circumstance you'll see the Cannot convert value to type System.String error when passing an argument to a [string]-typed parameter.


With your sample function, which by virtue of using a [Parameter()] attribute is implicitly an advanced function, there are only two ways that passing a value to your [string]-typed parameters can fail:

  • passing $null or an empty string (such as '' or "")[1]

  • passing an array[2] instead of a single value.

If you pass a value of any other type, it is automatically converted to a string.

Given the error message you received, the latter must be the problem, as demonstrated here:

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'
Run Code Online (Sandbox Code Playgroud)

This yields the following error:

Cannot process argument transformation on parameter 'param1'. 
Cannot convert value to type System.String
Run Code Online (Sandbox Code Playgroud)

The inability to pass an array to a [string] parameter applies only to advanced functions (the explicit alternative to making a function implicitly an advanced one via a [Parameter() attribute is to place a [CmdletBinding()] attribute above the param(...) block).

A simple (non-advanced) function does accept an array as a [string] argument, and simply joins the array elements with spaces[3] on conversion; e.g.,
'one', 'two' turns into 'one two'

Note: Arguably, passing an array to a [string] parameter should always require a deliberate action on the caller's part - both to confirm the actual intent to pass an array and to control how it is stringified - so it is the behavior of advanced functions that is the more sensible one (except for not consistently applying to collections in general).
Given PowerShell's commitment to backward compatibility, the behavior of non-advanced functions is unlikely to change, however.


[1] 允许这些值的唯一方法是通过删除属性属性(或将其设置为)来使参数成为强制性的。奇怪的是,强制参数即使故意传递也不接受这些值。Mandatory=$true$false[string]

[2] 奇怪的是,技术上不是数组(派生自[System.Array]/ [object[]])的集合,例如[System.Collections.ArrayList]or [System.Collections.Generic.List[object]]接受,然后像非高级函数一样被字符串化。

[3] 从技术上讲,您可以通过首选项变量$OFS来控制分隔符(字符串)。