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