PowerShell - 函数中的 "Write-Output"与 "return"

标签 powershell syntax psobject pscustomobject

我已经使用 PowerShell 多年了,我以为我已经掌握了它的一些更“古怪”的行为,但我遇到了一个我无法理解的问题.. .

我一直使用“return”从函数返回值,但最近我想我应该看看 Write-Output 作为替代方案。然而,PowerShell 就是 PowerShell,我发现了一些似乎没有意义的东西(至少对我来说):

function Invoke-X{ write-output @{ "aaa" = "bbb" } };
function Invoke-Y{ return @{ "aaa" = "bbb" } };

$x = Invoke-X;
$y = Invoke-Y;

write-host $x.GetType().FullName
write-host $y.GetType().FullName

write-host ($x -is [hashtable])
write-host ($y -is [hashtable])

write-host ($x -is [pscustomobject])
write-host ($y -is [pscustomobject])

输出:

System.Collections.Hashtable
System.Collections.Hashtable
True
True
True
False

$x 和 $y(或“write-output”和“return”)之间有什么区别,这意味着它们都是哈希表,但其中只有一个“-is”是 pscustomobject?除了明显检查变量中的每个哈希表是否也是 pscustomobject 之外,是否有一种通用方法可以确定与代码的差异?

我的 $PSVersionTable 看起来像这样,以防此行为特定于特定版本的 PowerShell:

Name                           Value
----                           -----
PSVersion                      5.1.16299.492
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.16299.492
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1

干杯,

中号

最佳答案

return[pscustomobject]在某种程度上,这是转移注意力的事情。

归根结底是:

  • 隐式表达式输出与cmdlet生成的输出;使用return (没有 cmdlet 调用)属于前一类,使用 Write-Output进入后者。

  • 输出对象被包裹 - 大部分不可见 - [psobject]仅在cmdlet生成的输出中的实例。

# Expression output: NO [psobject] wrapper:
@{ "aaa" = "bbb" } -is [psobject] # -> $False

# Cmdlet-produced output: [psobject]-wrapped
(Write-Output @{ "aaa" = "bbb" }) -is [psobject]  # -> $True

请注意 - 令人惊讶的是 - [pscustomobject][psobject] 相同:它们都引用类型 [System.Management.Automation.PSObject] ,这是 PowerShell 在幕后使用的通常不可见的帮助程序类型
(更令人困惑的是,有一个单独的 [System.Management.Automation.PSCustomObject] 类型。)

在很大程度上,这个额外的[psobject]包装器是良性的 - 它的行为大多与包装对象直接的行为相同 - 但在某些情况下它会导致细微不同的行为(见下文)。

<小时/>

And is there a generalised way I can determine the difference from code, other than obviously checking whether every hashtable I have in a variable is also a pscustomobject

请注意,哈希表不是 PS 自定义对象 - 它仅以这种方式出现 - 任何 - [psobject] - 由于[pscustomobject]而包裹的对象与 [psobject] 相同.

检测真正的 PS 自定义对象 - 使用 [pscustomobject] @{ ... } 创建或New-Object PSCustomObject/New-Object PSObject或由 cmdlet 生成,例如 Select-ObjectImport-Csv - 使用:

$obj -is [System.Management.Automation.PSCustomObject] # NOT just [pscustomobject]!

请注意,使用相关的 -as从 Windows PowerShell v5.1/PowerShell Core v6.1.0 开始,具有真正 PS 自定义对象的运算符已损坏 - 请参阅下文。

作为额外 [psobject] 的情况的示例包装器是良性的,您仍然可以直接测试包装对象的类型:

(Write-Output @{ "aaa" = "bbb" }) -is [hashtable]  # $True

也就是说,尽管有包装器,-is仍然可以识别包装类型。 因此,有点矛盾的是,两者 -is [psobject]-is [hashtable]返回$True在这种情况下,即使这些类型不相关。

<小时/>

这些差异没有充分的理由,而且它们给我的印象是有漏洞的抽象(实现):内部构造意外地从幕布后面窥视。

以下 GitHub 问题讨论这些行为:

关于PowerShell - 函数中的 "Write-Output"与 "return",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51177881/

相关文章:

c# - 测试 PSObject 是否源自 WriteObject() WriteWarning() WriteError()

regex - netsh 结果到 PowerShell 对象

windows - Windows 中用于应用程序白名单的代码签名应用程序

Powershell不释放内存

powershell - teamcity powershell-无法运行批处理文件

powershell - 为什么此哈希表产生不正确的结果?

java - Java中12小时制与24小时制的时间转换

c - Visual Studio C 语法着色问题

Delphi——将整数转换为类型指针?

powershell - ExpandProperty - 管道中缺少的对象