如何从 System.IO.File 调用访问 PSDrive?

sil*_*rip 4 c# powershell new-psdrive

我正在编写 ac# cmdlet,它将文件从一个位置复制到另一个位置(类似于 rsync)。它甚至支持 ToSession 和 FromSession。

我希望它能够与使用文件系统提供程序的 PSDrive 一起使用,但它当前会从 System.IO.File.GetAttributes("psdrive:\path") 引发错误

我真的很想在 PSDrive 上使用来自 System.IO 的调用。

像 copy-item 这样的东西是如何做到这一点的?

我已经执行了从 c# 访问 PSDrive 的搜索,但没有返回任何结果。

这相当于我的代码

new-psdrive -name mydrive -psprovider filesystem  -root \\aserver\ashare -Credential domain\user
$attributes=[system.io.file]::GetAttributes("mydrive:\path\")
Run Code Online (Sandbox Code Playgroud)

回报

Exception calling "GetAttributes" with "1" argument(s): "The given path's format is not supported."
Run Code Online (Sandbox Code Playgroud)

mkl*_*nt0 5

.NET 对PowerShell驱动器一无所知(通常也有不同的工作目录),因此需要转换为文件系统本机路径:

在 PowerShell 代码中

用于Convert-Path将基于 PowerShell 驱动器的路径转换为 ​​.NET 类型理解的本机文件系统路径:

$attributes=[System.IO.File]::GetAttributes((Convert-Path "mydrive:\path\"))
Run Code Online (Sandbox Code Playgroud)

默认情况下(位置参数使用)和 with -Path,Convert-Path执行通配符解析;要抑制后者,请使用该-LiteralPath参数。

警告Convert-Path仅适用于现有路径。解除该限制是GitHub 问题 #2993中功能请求的主题。


在 C# 代码中:

PSCmdlet派生的 cmdlet 中:

  • 用于GetUnresolvedProviderPathFromPSPath()将基于 PS 驱动器的路径转换为基于本机驱动器的路径[1] unresolved,这意味着,除了转换驱动器部分之外:

    • 不验证路径是否存在(但驱动器名称必须存在)
    • 并且执行通配符解析。
  • 用于GetResolvedProviderPathFromPSPath()将基于 PS 驱动器的路径解析为基于本机驱动器的路径,这意味着,除了转换驱动器部分之外:

    • 执行通配符解析,可能产生多个路径,甚至没有路径。
    • 文字路径组件必须存在
  • 使用CurrentProviderLocation()提供者 ID 的方法"FileSystem"来获取当前文件系统位置的路径作为System.Management.Automation.PathInfo实例;该实例的.Path属性和.ToString()方法返回路径的 PS 形式;使用该.ProviderPath属性来获取本机表示。

下面是一个简单的临时编译的 cmdlet,它可以使用这两种方法:

# Compiles a Get-NativePath cmdlet and adds it to the session.
Add-Type @'
    using System;
    using System.Management.Automation;
    [Cmdlet("Get", "NativePath")]
    public class GetNativePathCommand : PSCmdlet {

        [Parameter(Mandatory=true,Position=0)]
        public string PSPath { get; set; }

        protected override void ProcessRecord() {
            WriteObject("Current directory:");
            WriteObject("  PS form:      " + CurrentProviderLocation("FileSystem"));
            WriteObject("  Native form:  " + CurrentProviderLocation("FileSystem").ProviderPath);
            //
            WriteObject("Path argument in native form:");
            WriteObject("  Unresolved:");
            WriteObject("    " + GetUnresolvedProviderPathFromPSPath(PSPath));
            //
            WriteObject("  Resolved:");
            ProviderInfo pi;
            foreach (var p in GetResolvedProviderPathFromPSPath(PSPath, out pi))
            {
              WriteObject("    " + p);
            }
        }
    }
'@ -PassThru | % Assembly | Import-Module
Run Code Online (Sandbox Code Playgroud)

您可以按如下方式测试:

# Create a foo: drive whose root is the current directory.
$null = New-PSDrive foo filesystem .

# Change to foo:
Push-Location foo:\

# Pass a wildcard path based on the new drive to the cmdlet
# and have it translated to a native path, both unresolved and resolved;
# also print the current directory, both in PS form and in native form.
Get-NativePath foo:\*.txt
Run Code Online (Sandbox Code Playgroud)

如果您当前的目录是C:\Temp并且它恰好包含文本文件a.txtb.txt,您将看到以下输出:

Current directory:
  PS form:      foo:\
  Native form:  C:\Temp\
Path argument in native form:
  Unresolved:
    C:\Temp\*.txt
  Resolved:
    C:\Temp\a.txt
    C:\Temp\b.txt
Run Code Online (Sandbox Code Playgroud)

[1] 如果输入路径中引用的 PS 驱动器(使用 创建New-PSDrive)是根据UNC路径定义的,则生成的本机路径也将是 UNC 路径。