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

Converting System.Collections.ArrayList to a string in Powershell

我在 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

if i 运行 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 to output data, as that won't work; use it for display-only output only; to output data, use Write-Output,或者更好的是,使用 PowerShell 的 implicit 输出功能。

    • 在你的情况下,$error_values | select ErrorMessage 本身 不仅会输出感兴趣的信息作为 data,它也会导致有用输出格式。

    • 有关详细信息,请参阅 this answer

  • 具体来说,即使只显示输出,也不要使用Write-Host打印表示复杂对象(松散地说,具有属性的对象);
    改用Out-Host

    • $error_values | select ErrorMessage | Out-Host
    • 顺便说一句:selectSelect-Object) call is virtually a no-op; I presume what you actually meant was $error_values | select -ExpandProperty ErrorMessage - see 了解更多信息。
    • 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}

注意:对于直接显示元素为复杂对象的集合的输出,[=如果需要 单行 输出 ,15=] 可能会有所帮助,因为这些元素只是 space 连接:

$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 来使用除 space:

之外的分隔符
PS> Write-Host -Separator /  'one', 'two'
one/two

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

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

可选阅读:为什么传递给-ErrorVariable的目标变量接收到System.Collections.ArrayList实例:

常用 -ErrorVariable 参数 - 事实上所有常用 -*Variable 参数都将流的输出收集到变量中 - always return 具有收集输出的 System.Collections.ArrayList 实例,这在两个方面令人惊讶:

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

  • 此外,在 -OutVariable 的情况下,行为与管道的 direct 输出不一致,其中 命令的单个 对象输出是 原样 - 而不是包装在集合中,例如本例中的 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 issue #3154