正在Powershell中将System.Collections.ArrayList转换为字符串



我在powershell中有以下测试脚本,我面临的问题是我想将错误的详细信息存储在自定义对象或变量中作为字符串,现在错误变量的值的类型是System.Collections.ArrayList。

invoke-sqlcmd -ServerInstance "$sql" -inputfile $file  -Database test -OutputSqlErrors $true -ConnectionTimeout 10 -ErrorAction Continue -Errorvariable err | Out-Null

现在,如果我运行,奇怪的是

$err | Get-Type

System.Collections.ArrayList

如果我运行write-host $err,它会正确地打印出错误,但会将$err的值分配给自定义对象,那么我会丢失该值,但会得到'System.Collections.ArrayList'

$error_values += New-Object -TypeName psobject -Property @{ErrorMessage =$err}

现在运行$error_values | select ErrorMessage returns System.Collections.ArrayList

我只需要它是一个简单的字符串,不确定这里有什么不正确的地方。

$arrayList = [System.Collections.ArrayList]::new()
[void]$arrayList.Add("one")
[void]$arrayList.Add("two")
[void]$arrayList.Add("three")
$msg = $arrayList -join ", "
Write-Host $msg
  • 通常,不要使用Write-Host输出数据,因为这不起作用仅用于显示仅用于输出;若要输出数据,请使用Write-Output,或者更好地使用PowerShell的隐式输出功能。

    • 在您的情况下,$error_values | select ErrorMessage本身不仅会将感兴趣的信息输出为数据,还会产生有用的输出格式。

    • 有关详细信息,请参阅此答案。

  • 特别是,即使只需要显示输出,也不要使用Write-Host打印复杂对象的表示(粗略地说,是具有属性的对象(
    请改用Out-Host

    • $error_values | select ErrorMessage | Out-Host
    • 顺便说一句:select(Select-Object(调用实际上是一个无操作;我想你的实际意思是$error_values | select -ExpandProperty ErrorMessage——更多信息请参阅此答案
    • Write-Host不执行丰富的输出格式,而PowerShell的默认显示格式,Out-Host执行。由于Write-Host使用简单的.ToString()字符串化,复杂对象通常会导致无效的表示-有关详细信息,请参阅此答案

一个完整的例子:

# Create a sample ArrayList, as returned by 
$err = [System.Collections.ArrayList] ('one', 'two')
# Construct a custom object ([pscustomobject]) with an .ErrorMessage
# property that contains the array list
$obj = [pscustomobject] @{ ErrorMessage = $err }
# !! Write-Host results in UNHELPFUL display:
# !! Note how instead of listing the *elements* of the ArrayList
# !! the *type name* ("System.Collections.ArrayList") is printed instead.
PS> Write-Host $obj
@{ErrorMessage=System.Collections.ArrayList}
# OK: Out-Host produces richly formatted *display-only* output.
PS> $obj | Out-Host
ErrorMessage
------------
{one, two}

# OK as well: *implicit* output, *as data* - same representation.
PS> $obj
ErrorMessage
------------
{one, two}

注意:对于直接显示元素为而非复杂对象的集合的输出,如果需要单行输出,则Write-Host可能会有所帮助,因为这些元素只是空间连接的:

$err = [System.Collections.ArrayList] ('one', 'two')
# OK with collection of non-complex objects to get a 
# *single-line* representation.
# Out-Host and implicit output print each element on its own line.
PS> Write-Host $err
one two

您甚至可以使用-Separator使用空格以外的分隔符:

PS> Write-Host -Separator /  'one', 'two'
one/two

当然,您也可以使用表达式来创建这样的字符串,使用-join,字符串连接运算符,这将允许您将输出用作数据:

PS> 'one', 'two' -join '/'
one/two

可选读取:传递给-ErrorVariable的目标变量为何接收System.Collections.ArrayList实例:

常见的-ErrorVariable参数——实际上是所有收集变量中流输出的常见-*Variable参数——总是返回具有收集输出的System.Collections.ArrayList实例,这在两个方面令人惊讶:

  • PowerShell通常使用[object[]]数组作为其默认收集数据类型。

  • 此外,在-OutVariable的情况下,行为与管道的直接输出不一致,其中从命令输出的单个对象被输出为,而不是被包装在集合中,如本例中的ArrayList;也就是说,即使您期望以下两个命令是等效的,但它们不是:

    $out = Get-Date  
    # -> $out is a [datetime] instance.
    # !! -OutVariable *always* creates ArrayList.
    $null = Get-Date -OutVariable out 
    # -> $out is a *single-element ArrayList* containing a [datetime] instance.
    

有关这些不一致的讨论,请参阅GitHub第3154期。

最新更新