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

标签 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 {
    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-ChildItem -Filter *.txt -Recurse | Get-Test

请向我解释哪里出了问题、如何解决以及我应该阅读哪些内容以深入了解 PowerShell 的机制。

最佳答案

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

[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 | 检查从 cmdlet 接收到的类型foreach-object-process { $_.GetType() } . 更重要的是,您实际上可以使用 Powershell 以相同的方式实现您想要的,例如:Get-ChildItem | foreach-object-process { $_.FullName }.

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

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

关于c# - 从 cmdlet 中的管道正确获取文件路径,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34570328/

相关文章:

c# - 使用ObjectQuery <T>进行过滤错误

powershell - 如何在powershell脚本中填写提示

powershell - 从超过1级深度的属性中从数组中提取项目?

powershell - 使用 Powershell 确定 Azure VM 上允许的最大数据驱动器数

c# - 以行值作为列的 SQL 查询的建议

c# - XAML 共享资源

variables - 发送邮件消息失败,因为附件丢失(变量变乱)

powershell - 从表输出中删除椭圆

c# - 为什么 decimal.TryParse 成功解析了类似 12,2,2,2 的东西

c# - 企业库 5.0 是否在 DataReader 和访问器方法的自定义类之间缓存映射