C# 从cmdlet中的管道中正确获取文件路径

C# 从cmdlet中的管道中正确获取文件路径,c#,powershell,C#,Powershell,我编写了小测试代码: namespace Test { using System; using System.Management.Automation; using System.Linq; using System.IO; [Cmdlet(VerbsCommon.Get, "Test", DefaultParameterSetName="Path")] public sealed class GetTestCommand : PSCmdlet { priva

我编写了小测试代码:

namespace Test {
  using System;
  using System.Management.Automation;
  using System.Linq;
  using System.IO;

  [Cmdlet(VerbsCommon.Get, "Test", DefaultParameterSetName="Path")]
  public sealed class GetTestCommand : PSCmdlet {
    private String[] _paths;
    private Boolean  _wildcards;

    [Parameter(
      ParameterSetName="Path",
      Mandatory=true,
      Position=0,
      ValueFromPipeline=true,
      ValueFromPipelineByPropertyName=true
    )]
    public String[] Path {
      get { return _paths; }
      set {
        _wildcards = true;
        _paths = value;
      }
    }

    [Parameter(
      ParameterSetName="LiteralPath",
      Mandatory=true,
      Position=0,
      ValueFromPipeline=false,
      ValueFromPipelineByPropertyName=true
    )]
    public String[] LiteralPath {
      get { return _paths; }
      set { _paths = value; }
    }

    protected override void ProcessRecord() {
      ProviderInfo pi;

      (from p in _paths
      select new {
        FilePath = (_wildcards ?
          this.SessionState.Path.GetResolvedProviderPathFromPSPath(p, out pi)[0] :
          this.SessionState.Path.GetUnresolvedProviderPathFromPSPath(p))
      }).ToList()
      .ForEach(i => WriteObject(i.FilePath));
    }
  }
}
这项工作:

Get-Test *.txt
Get-ChildItem -Filter *.txt | Get-Test
这是有效的:

Get-Test *.txt
Get-ChildItem -Filter *.txt | Get-Test
但这不起作用:

Get-ChildItem -Filter *.txt -Recurse | Get-Test

请向我解释出了什么问题,如何修复,以及我应该阅读哪些内容来深入了解PowerShell的机制。

问题在于您实际上没有处理从
PowerShell cmdlet
收到的对象。 正确的方法是将收到的参数绑定到适当类型的对象,然后访问其属性,即:

[Cmdlet(VerbsCommon.Get, "Test", DefaultParameterSetName = "Path")]
public sealed class GetTestCommand : PSCmdlet
{
    private FileSystemInfo[] _paths;

    [Parameter(
      ParameterSetName = "Path",
      Mandatory = true,
      Position = 0,
      ValueFromPipeline = true,
      ValueFromPipelineByPropertyName = true
    )]
    public FileSystemInfo[] Path
    {
        get { return _paths; }
        set
        {
            _paths = value;
        }
    }


    protected override void ProcessRecord()
    {
        ProviderInfo pi;

        (from p in _paths
         where (p.GetType() != typeof(DirectoryInfo))
         select new
         {
             FilePath = p.FullName}).ToList()
        .ForEach(i => WriteObject(i.FilePath));
    }
}
为了便于将来参考,您可能需要使用
Get ChildItem | foreach object-process{$\uu0.GetType()}
检查从
cmdlet
接收到的类型。 更重要的是,使用
Powershell
,您实际上可以以相同的方式实现您想要的功能,例如:
Get ChildItem | foreach object-process{$\ FullName}

要获得与纯Powershell完全相同的结果,请尝试:

Get-ChildItem -Recurse | ForEach-Object -Process { if ($_ -isnot [System.IO.DirectoryInfo]) { Write-Host $_.FullName } }

[Alias(“PSPath”)]
添加到
LiteralPath
参数。谢谢,这与此属性一起工作。首先,感谢您的回复,但我不确定这是否是我在测试中寻找的。我只是想了解PowerShell一般是如何工作的。你说的“PowerShell一般是如何工作的”是什么意思?您已经创建了一个函数,该函数接受
String
类型的参数,然后处理它们。错误之处在于,您将参数的类型设置为
String
,而导入函数的
Get ChildItem
的结果返回类型为
FileSystemInfo
的对象。由于param的类型是
String
,所以您只接收到了所有被强制转换为
.ToString()
的对象。实际上,您可以使用
getchilditem | ForEach对象-进程{$\u0.ToString()}
检查这一点。