PowerShell - “写输出"vs “返回"在函数中 [英] PowerShell - "Write-Output" vs "return" in functions

查看:67
本文介绍了PowerShell - “写输出"vs “返回"在函数中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I've been using PowerShell for a number of years, and I thought I had a handle on some of its more 'eccentric' behaviour, but I've hit an issue I can't make head nor tail of...

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

I've always used "return" to return values from functions, but recently I thought I'd have a look at Write-Output as an alternative. However, PowerShell being PowerShell, I've found something that doesn't seem to make sense (to me, at least):

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(或写输出"和返回")之间的区别是什么,这意味着它们都是哈希表,但其中只有一个-是"pscustomobject?是否有一种通用的方法可以确定与代码的差异,除了明显检查变量中的每个哈希表是否也是 pscustomobject)?

What is the difference between $x and $y (or 'write-output' and 'return') that means they're both hashtables, but only one of them '-is' a pscustomobject? 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)?

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

My $PSVersionTable looks like this, in case this behaviour is specific to a particular version of 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

干杯,

M

推荐答案

return[pscustomobject] 在这里,从某种意义上说.

return and [pscustomobject] are red herrings here, in a way.

归结为:

  • 隐式表达式输出与cmdlet产生的输出;使用 return(不使用 cmdlet 调用)属于前一类,使用 Write-Output 属于后者.

  • Implicit expression output vs. cmdlet-produced output; using return (without a cmdlet call) falls into the former category, using Write-Output into the latter.

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

Output objects getting wrapped in - mostly invisible - [psobject] instances only in cmdlet-produced output.

# 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] 类型.)

Note that - surprisingly - [pscustomobject] is the same as [psobject]: they both refer to type [System.Management.Automation.PSObject], which is the normally invisible helper type that PowerShell uses behind the scenes.
(To add to the confusion, there is a separate [System.Management.Automation.PSCustomObject] type.)

在大多数情况下,这个额外的 [psobject] 包装器是良性的 - 它的行为大多与直接包装的对象一样 - 但在某些情况下,它会导致微妙的不同行为(见下文).

For the most part, this extra [psobject] wrapper is benign - it mostly behaves as the wrapped object would directly - but there are instances where it causes subtly different behavior (see below).

是否有一种通用的方法可以确定与代码的差异,除了明显检查变量中的每个哈希表是否也是 pscustomobject

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] 相同.

Note that a hashtable is not a PS custom object - it only appears that way for - any - [psobject]-wrapped object due to [pscustomobject] being the same as [psobject].

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

To detect a true PS custom object - created with [pscustomobject] @{ ... } or New-Object PSCustomObject / New-Object PSObject or produced by cmdlets such as Select-Object and Import-Csv - use:

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

请注意,从 Windows PowerShell v5.1/PowerShell Core v6.1.0 开始,将相关的 -as 运算符与真正的 PS 自定义对象一起使用已被破坏 - 见下文.

Note that using the related -as operator with a true PS custom object is broken as of Windows PowerShell v5.1 / PowerShell Core v6.1.0 - see below.

举个例子,额外的 [psobject] 包装器是良性的,你仍然可以直接测试包装对象的类型:

As an example of a situation where the extra [psobject] wrapper is benign, you can still test even a wrapped object for its type directly:

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

也就是说,尽管有包装器,-is 仍然识别 wrapped 类型.因此,有些矛盾的是,both -is [psobject]-is [hashtable] 返回 $True 在这个案例,即使这些类型无关.

That is, despite the wrapper, -is still recognizes the wrapped type. Therefore, somewhat paradoxically, both -is [psobject] and -is [hashtable] return $True in this case, even though these types are unrelated.

这些差异没有充分的理由,我认为它们是有漏洞的抽象(实现):不小心从窗帘后面偷看的内部结构.

There is no good reason for these discrepancies and they strike me as leaky abstractions (implementations): internal constructs accidentally peeking from behind the curtain.

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

The following GitHub issues discuss these behaviors:

  • Objects are situationally invisibly [psobject]-wrapped, sometimes causing unexpected behavior.

为什么 [pscustomobject] 相同>[psobject],即使存在不同的 [System.Management.Automation.PSCustomObject] 类型?

Why is [pscustomobject] the same as [psobject], even though a distinct [System.Management.Automation.PSCustomObject] type exists?

是否应将所有 [psobject] cmdlet 参数更改为[对象]?

Should all [psobject] cmdlet parameters be changed to [object]?

-as 运算符无法识别 System.Management.Automation.PSCustomObject 实例等.

The -as operator does not recognize System.Management.Automation.PSCustomObject instances as such.

这篇关于PowerShell - “写输出"vs “返回"在函数中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆