【问题标题】:How do I fix the problem I have with passing all objects output via the pipeline?如何解决通过管道传递所有对象输出的问题?
【发布时间】:2019-07-04 19:40:43
【问题描述】:

我正在编写一个 PowerShell 模块以使用 C# 中存储系统的 API,但我遇到了一个我无法理解的问题。我有一个命令可以将一个或多个对象通过管道传输到另一个命令中,并且 ProcessRecord() 按照您的预期单独处理它们。但是,这只是当我在第一个 cmdlet 中命名项目时,或者先将其保存为 PowerShell 中的变量。

这是我在执行此操作时在 PowerShell 中看到的内容:

PS C:\> $a = Show-ISSFileSystem -Name fs1
PS C:\> $b = Show-ISSFileSystem -Name fs1,cesSharedRoot
PS C:\> $c = Show-ISSFileSystem    # Contains the two objects listed above.

# Types
PS C:\> $a.Gettype().Fullname
ISS.FileSystemInfo.Filesystem
PS C:\> $b.Gettype().Fullname
System.Object[]
PS C:\> $c.Gettype().Fullname
ISS.FileSystemInfo.Filesystem[]

# Introduce second command
PS C:\> $a | Show-ISSFileset                    # Returns as expected
PS C:\> $b | Show-ISSFileset                    # Returns as expected
PS C:\> $c | Show-ISSFileset                    # Returns as expected
PS C:\> Show-ISSFileSystem | Show-ISSFileSet    # Fails, complaining about the input object - Custom Class(Filesystem)

Show-ISSFileset : The input object cannot be bound to any parameters for the command either because the command does
not take pipeline input or the input and its properties do not match any of the parameters that take pipeline input.

# Counting objects
PS C:\> (Show-ISSFileSystem -Name fs1 | Measure-Object).Count               # Returns 1 as expected
PS C:\> (Show-ISSFileSystem -Name fs1,cesSharedRoot | Measure-Object).Count # Returns 2 as expected
PS C:\> (Show-ISSFileSystem | Measure-Object).Count                         # Returns 1, even though the variable has two objects
PS C:\> ($c | Measure-Object).Count                                         # Saved to variable first, the command above correctly returns 2 as expected.

如有必要,我可以添加部分代码,但我只是想知道是否有人对这里可能发生的事情有任何快速的想法。它可以非常清楚地处理多个对象,但不能直接来自第一个函数,除非我们命名一个(我使用了 ValueFromPipeline 而不是 ValueFromPipelineByProperty)。有很多代码,我很难提供一个最小的例子。

就像第一个命令直接运行时将对象混合在一起,而第二个命令不知道输入是什么。有人遇到过类似的问题吗?

更新:

好的,所以我意识到输出发生了一些奇怪的事情。从 JSON 转换响应后,如果指定了 Name 参数,我将通过 .Where() 运行它,最终结果是对象列表。任何经历的事情都会出来并通过管道。如果不指定Name,则直接写入转换后的Json对象。

没用:

// Convert from Json
FileSystemInfo _convertJson = FileSystemInfo.FromJson(_response);

// Filter by name if requested
if (Name != null)
{
    List<Filesystem> FileSystems = _convertJson.Filesystems.Where(
        f =>
            Regex.IsMatch(f.Name.ToString(),
                string.Format("(?:{0})", string.Join("|", Name)))).ToList();
    FileSystems.ForEach(WriteObject);
}
else
{
    WriteObject(_convertJson.Filesystems);
}

作品:

// Convert from Json
FileSystemInfo _convertJson = FileSystemInfo.FromJson(_response);

// Filter by name if requested
if (Name != null)
{
    List<Filesystem> FileSystems = _convertJson.Filesystems.Where(
        f =>
            Regex.IsMatch(f.Name.ToString(),
                string.Format("(?:{0})", string.Join("|", Name)))).ToList();
    FileSystems.ForEach(WriteObject);
}
else
{
    _convertJson.Filesystems.ToList().ForEach(WriteObject);
}

也许这不是最好的答案,有人可以纠正我。我才学 C# 三个月。

更新 2:

非常感谢下方的 PetAlSer 和 Mathias 为我指明了正确的方向。上面的列表转换不是必需的,只需将集合枚举为 WriteObject 的一部分,以便第二个 cmdlet 接收每个对象。

WriteObject(_convertJson.Filesystems, true);

【问题讨论】:

  • 这是 PowerShell 的核心行为:当管道的第一个(或唯一)元素是一个表达式并且该表达式导致集合时,则枚举该集合并且其内容由管道而不是集合本身传递。

标签: c# powershell


【解决方案1】:

正如 PetSerAl 在 cmets 中已经指出的那样:

这是 PowerShell 的核心行为:当管道的第一个(或唯一)元素是一个表达式并且该表达式导致集合时,则枚举该集合并且其内容由管道而不是集合本身传递。

Cmdlet.WriteObject() 具有an overload,它允许您指示管道处理器展开可与List&lt;T&gt;.ForEach() 一起使用的可枚举输出(假设T 是可枚举的)柯里化:

Action<object> WriteObjectWithoutEnumeration = 
    o => this.WriteObject(o, false);

FileSystems.ForEach(WriteObjectWithoutEnumeration);

// or, without ForEach:
WriteObject(_convertJson.Filesystems, false);

【讨论】:

  • @mathias-r-jessen 我想我在某些地方因为不完全清楚而让人们感到困惑,但我们已经找到了答案。我今天早上注意到 WriteObject 上的 enumerateCollection 布尔值,当我将其设置为 true 时,它​​会按预期工作,即来自第一个 cmdlet 的所有对象都可以由第二个 cmdlet 处理。更新了我的问题。谢谢
  • @Ash 啊,我明白了,现在一切都变得更有意义了。无论如何,现在你至少知道如何控制这种行为了:)
  • 是的,我想我只是没有关注 Visual Studio。再次感谢。
  • 注意falseWriteObject的第二个参数的默认值:tio.run/##K8gvTy0qzkjNyfn/…
猜你喜欢
  • 2013-03-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-04
  • 2021-11-27
相关资源
最近更新 更多