PowerShell开始使用Microsoft.PowerShell.Core\FileSystem::

xxhby3vn  于 2023-10-18  发布在  Shell
关注(0)|答案(2)|浏览(139)

我在PowerShell中遇到了以下行为,我无法解释并发现麻烦。
我正在一个任意目录中工作,该目录的路径显示在提示符中:

PS C:\Users\Rene\AppData\Local\Temp>

另外,get-location报告“正确”路径:

PS C:\Users\Rene\AppData\Local\Temp> get-location

Path
----
C:\Users\Rene\AppData\Local\Temp

然后我输入mkdir xyz | cd来创建一个目录,并将工作目录更改为这个新目录:

PS C:\Users\Rene\AppData\Local\Temp> mkdir xyz | cd

突然,提示符中的路径以Microsoft.PowerShell.Core\FileSystem::为前缀:

PS Microsoft.PowerShell.Core\FileSystem::C:\Users\Rene\AppData\Local\Temp\xyz>

这种变化也反映在get-location上:

PS Microsoft.PowerShell.Core\FileSystem::C:\Users\Rene\AppData\Local\Temp\xyz> get-location

Path
----
Microsoft.PowerShell.Core\FileSystem::C:\Users\Rene\AppData\Local\Temp\xyz

这是怎么回事,我怎么才能把这个前缀关闭?

fzwojiic

fzwojiic1#

按相反顺序:

如何关闭前缀?

简单,使用 * 显式 * 管道绑定!

mkdir xyz |cd -Path {$_.FullName}

这是怎么回事?
好问题!您在这里看到的是提供程序的小工具(Get-ChildItemGet-ItemSet-Location等)如何实现 * 管道绑定**的副作用。
当您针对FileSystem提供程序调用New-Item(这是mkdir所做的)时,它返回一个对象(对应于新创建的文件或目录),该对象具有一系列隐藏属性,PowerShell使用这些属性来跟踪提供程序之间的项目-这些可以通过Get-Member -Force发现:

PS C:\> Get-Item .|Get-Member PS* -MemberType NoteProperty -Force

   TypeName: System.IO.DirectoryInfo

Name          MemberType   Definition
----          ----------   ----------
PSChildName   NoteProperty string PSChildName=C:\
PSDrive       NoteProperty PSDriveInfo PSDrive=C
PSIsContainer NoteProperty bool PSIsContainer=True
PSParentPath  NoteProperty string PSParentPath=
PSPath        NoteProperty string PSPath=Microsoft.PowerShell.Core\FileSystem::C:\
PSProvider    NoteProperty ProviderInfo PSProvider=Microsoft.PowerShell.Core\FileSystem

当你在下游构造一个带有提供程序小程序(例如Set-Location/cd)的管道语句时,它使用提供程序限定的PSPath值来数字绑定输入对象。
这可以用Trace-Command来观察:

PS C:\> Trace-Command -Expression {Get-Item .|Set-Location} -Name ParameterBinding,MemberResolution -PSHost

结果是(为了简洁起见,我删除了Get-Item的细节):

DEBUG: ParameterBinding Information: 0 : BIND NAMED cmd line args [Set-Location]
DEBUG: ParameterBinding Information: 0 : BIND POSITIONAL cmd line args [Set-Location]
DEBUG: ParameterBinding Information: 0 : BIND cmd line args to DYNAMIC parameters.
DEBUG: ParameterBinding Information: 0 : MANDATORY PARAMETER CHECK on cmdlet [Set-Location]
DEBUG: ParameterBinding Information: 0 : CALLING BeginProcessing
DEBUG: ParameterBinding Information: 0 : CALLING BeginProcessing
DEBUG: ParameterBinding Information: 0 : BIND PIPELINE object to parameters: [Set-Location]
DEBUG: ParameterBinding Information: 0 :     PIPELINE object TYPE = [System.IO.DirectoryInfo]
DEBUG: ParameterBinding Information: 0 :     RESTORING pipeline parameter's original values
DEBUG: ParameterBinding Information: 0 :     Parameter [Path] PIPELINE INPUT ValueFromPipeline NO COERCION
DEBUG: ParameterBinding Information: 0 :     BIND arg [C:\\] to parameter [Path]
DEBUG: ParameterBinding Information: 0 :         BIND arg [C:\\] to param [Path] SKIPPED
DEBUG: ParameterBinding Information: 0 :     Parameter [Path] PIPELINE INPUT ValueFromPipelineByPropertyName NO COERCION
DEBUG: MemberResolution Information: 0 :     Lookup
DEBUG: MemberResolution Information: 0 :         "Path" NOT present in type table.
DEBUG: MemberResolution Information: 0 :         Adapted member: not found.
DEBUG: ParameterBinding Information: 0 :     Parameter [StackName] PIPELINE INPUT ValueFromPipelineByPropertyName NO COERCION
DEBUG: MemberResolution Information: 0 :     Lookup
DEBUG: MemberResolution Information: 0 :         "StackName" NOT present in type table.
DEBUG: MemberResolution Information: 0 :         Adapted member: not found.
DEBUG: ParameterBinding Information: 0 :     Parameter [LiteralPath] PIPELINE INPUT ValueFromPipelineByPropertyName NO COERCION
DEBUG: MemberResolution Information: 0 :     Lookup
DEBUG: MemberResolution Information: 0 :         "LiteralPath" NOT present in type table.
DEBUG: MemberResolution Information: 0 :         Adapted member: not found.
DEBUG: MemberResolution Information: 0 :     Lookup
DEBUG: MemberResolution Information: 0 :         Found PSObject instance member: PSPath.
DEBUG: ParameterBinding Information: 0 :     BIND arg [Microsoft.PowerShell.Core\FileSystem::C:\] to parameter [LiteralPath]
DEBUG: ParameterBinding Information: 0 :         BIND arg [Microsoft.PowerShell.Core\FileSystem::C:\] to param [LiteralPath] SUCCESSFUL
DEBUG: ParameterBinding Information: 0 : MANDATORY PARAMETER CHECK on cmdlet [Set-Location]
DEBUG: ParameterBinding Information: 0 : CALLING EndProcessing
DEBUG: ParameterBinding Information: 0 : CALLING EndProcessing

正如你所看到的,PowerShell放弃了将C:\绑定到Set-Location-Path参数,因为将PSPath属性值绑定到-LiteralPath更合适?!
其原因是-LiteralPath参数别名为PSPath,通过使用Get-Command挖掘位可以看出:

PS C:\> (Get-Command Set-Location).Parameters['LiteralPath'] |Select Aliases

Aliases
-------
{PSPath}

以这种方式实现提供程序小工具的管道绑定的真实的原因有两个:

  • 将“provider-native”字符串表示直接绑定到Path可能会产生与 globbing 相关的意外后果。
  • 例如,Get-Item -Path 'a[bcd]'Get-Item -LiteralPath 'a[bcd]'是两个非常不同的查询
  • 绑定在provider-qualified PSPath值上意味着我们可以将位置切换到不同的提供程序,而不会丢失自动绑定:
  • PS Cert:\> $aFile |Get-Content * 只是工作 *
cetgtptt

cetgtptt2#

在Mathias发布的基础上,您可以使用一个非常简单的过滤器来保存一些输入并完成相同的事情。把它放在脚本中并运行它,直接运行它,或者把它放在你的配置文件中:

filter slp(){
    Set-Location -Path $_.FullName
}

然后您可以使用:用途:

mkdir | slp

其工作原理与以下内容相同:

mkdir | sl

你可以选择任何你想要的过滤器。例如,“cdp”而不是“slp”。

相关问题