【发布时间】: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