パイプされたSet-Locationは何をしているのか

先に結論言っとくと、なにやってんのかわかんない、です
なんにも解決しない
ひどい記事だ

PS> Get-Item HKLM:\SOFTWARE | Set-Location -PassThru

Path                                                           
----                                                           
Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SOFTWARE

これがね、よくわからない
なぜ Get-Item してパイプで渡すとPSPathに移動するのか
おまえは何をしているんだ

Set-Location がバイプで受けられるパラメータは以下の三つ

-LiteralPath <string>

    必須                         true
    位置                         名前付き
    パイプライン入力を許可する   true (ByPropertyName)
    パラメーター セット名        LiteralPath
    エイリアス                   PSPath
    動的                         false


-Path <string>

    必須                         false
    位置                         0
    パイプライン入力を許可する   true (ByValue, ByPropertyName)
    パラメーター セット名        Path
    エイリアス                   なし
    動的                         false


-StackName <string>

    必須                         false
    位置                         名前付き
    パイプライン入力を許可する   true (ByPropertyName)
    パラメーター セット名        Stack
    エイリアス                   なし
    動的                         false

-StackName はこの場合全然関係ないので考慮しない
なので値の受け方は以下の三通りのはずだ

  • ToString() されたものを -Path で受ける
  • Path プロパティを -Path で受ける
  • LiteralPath プロパティを -LiteralPath で受ける
PS> Get-Item HKLM:\SOFTWARE | gm -MemberType Properties


   TypeName: Microsoft.Win32.RegistryKey

Name          MemberType   Definition
----          ----------   ----------
Property      NoteProperty string[] Property=System.String[]
PSChildName   NoteProperty string PSChildName=SOFTWARE
PSDrive       NoteProperty PSDriveInfo PSDrive=HKLM
PSIsContainer NoteProperty bool PSIsContainer=True
PSParentPath  NoteProperty string PSParentPath=Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE
PSPath        NoteProperty string PSPath=Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SOFTWARE
PSProvider    NoteProperty ProviderInfo PSProvider=Microsoft.PowerShell.Core\Registry
Handle        Property     Microsoft.Win32.SafeHandles.SafeRegistryHandle Handle {get;}
Name          Property     string Name {get;}
SubKeyCount   Property     int SubKeyCount {get;}
ValueCount    Property     int ValueCount {get;}
View          Property     Microsoft.Win32.RegistryView View {get;}

PathLiteralPath もないので -PathByValue で受けてるに違いないですね
そうに決まってる

PS> Get-Item HKLM:\SOFTWARE | % {$_.ToString()}
HKEY_LOCAL_MACHINE\SOFTWARE

なるほど、 HKEY_LOCAL_MACHINE\SOFTWARE が渡ってるんでしょう
そうに決まってる
検証コードも書こう

PS> function Test-Hoge
{
    [CmdletBinding()]
    param
    (
        [parameter(Mandatory=$false,Position=0,ValueFromPipeline,ValueFromPipelineByPropertyName,ParameterSetName='Path')]
        [string] $Path,
        [parameter(Mandatory=$false,ValueFromPipelineByPropertyName,ParameterSetName='PSPath')]
        [string] $LiteralPath
    )

    $PSCmdlet.ParameterSetName
    $Path
}

PS> Get-Item HKLM:\SOFTWARE | Test-Hoge
Path
HKEY_LOCAL_MACHINE\SOFTWARE

間違いなさそう
じゃあ ToString() してパイプで渡してもいいんじゃないの…って思うじゃん?

PS> Get-Item HKLM:\SOFTWARE | % {$_.ToString()} | Set-Location -PassThru
Set-Location : パス 'C:\HKEY_LOCAL_MACHINE\SOFTWARE' が存在しないため検出できません。
発生場所 行:1 文字:47
+ Get-Item HKLM:\SOFTWARE | % {$_.ToString()} | Set-Location
+                                               ~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (C:\HKEY_LOCAL_MACHINE\SOFTWARE:String) [Set-Location], ItemNotFoundException
    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.SetLocationCommand

!?

PS> Get-Item HKLM:\SOFTWARE | % {$_.PSPath} | Set-Location -PassThru

Path
----
Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SOFTWARE

PSPath を渡すと最初のやつと同じ結果になる
パイプでなくパラメータで渡した場合も一応確認しとこう

PS> Set-Location -Path (Get-Item HKLM:\SOFTWARE) -PassThru
Set-Location : パス 'C:\HKEY_LOCAL_MACHINE\SOFTWARE' が存在しないため検出できません。
発生場所 行:1 文字:1
+ Set-Location -Path (Get-Item HKLM:\SOFTWARE) -PassThru
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (C:\HKEY_LOCAL_MACHINE\SOFTWARE:String) [Set-Location], ItemNotFoundException
    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.SetLocationCommand

PS> Set-Location -Path (Get-Item HKLM:\SOFTWARE).PSPath -PassThru

Path
----
Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SOFTWARE

ふむふむ

つまりなんだ、パイプで渡ってるのは PSPath ってことなのか、そういうことだよね
…なんで?
イミワカンナイ


おまけ

LiteralPath のエイリアスが PSPath なのも納得いかないな

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中