私はPowerShellを何年も使用していて、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」)の違いは何ですか?つまり、両方ともハッシュテーブルですが、そのうちの1つだけが「pscustomobject」です。そして、変数にあるすべてのハッシュテーブルがpscustomobjectでもあるかどうかを明らかにチェックする以外に、コードとの違いを判断できる一般的な方法はありますか?
この動作がPowerShellの特定のバージョンに固有である場合、$ PSVersionTableは次のようになります。
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
を使用すると前者のカテゴリに分類され、_Write-Output
_を使用すると後者に分類されます。
オブジェクトがにラップされるほとんど非表示の_[psobject]
_インスタンスのみコマンドレット出力。
_# implicit / 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]
_ラッパーは無害です-ラップされたオブジェクトが直接動作するように動作します-しかし、微妙に異なる動作を引き起こす場合があります(以下を参照)。
そして、変数にあるすべてのハッシュテーブルがpscustomobjectでもあるかどうかを明らかにチェックする以外に、コードとの違いを判断できる一般的な方法はありますか?
ハッシュテーブルはnotPSカスタムオブジェクトであることに注意してください-_[psobject]
_-ラップされたオブジェクトの場合にのみそのように表示されます-_[pscustomobject]
_は_[psobject]
_と同じです。
_[pscustomobject] @{ ... }
_または_New-Object PSCustomObject
_/_New-Object PSObject
_で作成された、または_Select-Object
_や_Import-Csv
_などのコマンドレットによって生成された真のPSカスタムオブジェクトを検出するには、次を使用します。
_$obj -is [System.Management.Automation.PSCustomObject] # NOT just [pscustomobject]!
_
関連する_-as
_演算子を真のPSカスタムオブジェクトで使用すると、Windows PowerShell v5.1/PowerShell Corev6.1.0以降で機能しなくなることに注意してください。以下を参照してください。
余分な_[psobject]
_ラッパーが無害である状況の例として、ラップされたオブジェクトでもそのタイプを直接テストできます。
_(Write-Output @{ "aaa" = "bbb" }) -is [hashtable] # $True
_
つまり、ラッパーにもかかわらず、_-is
_はwrappedタイプを認識します。したがって、いくぶん逆説的に、両方_-is [psobject]
_と_-is [hashtable]
_は、この場合、これらのタイプが_$True
_を返します。無関係。
これらの不一致の正当な理由はありませんそしてそれらは漏れのある抽象化(実装)として私を襲います:内部構造が誤ってカーテンの後ろから覗いています。
次のGitHubの問題では、これらの動作について説明しています。