我很难将文件传送到 Get-Content
(版本 PS 5.1)。
模块代码:
[Cmdlet(VerbsDiagnostic.Test, "FilePiping")]
public class PSTestFilePiping : PSCmdlet
{
[Parameter(Position = 0, Mandatory = true)]
public string FileName { get; set; }
protected override void ProcessRecord()
{
WriteObject(new System.IO.FileInfo(FileName));
}
}
命令:$x = Test-FilePiping .\readme.txt
$y = gci .\readme.txt
(为简单起见,我使用相对路径)两个
$x
和 $y
是 FileInfo
对象根据 GetType()
:IsPublic IsSerial Name BaseType
True True FileInfo System.IO.FileSystemInfo
然而我不能这样做:$x | gc
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.
但我可以这样做:$y | gc
这让我摸不着头脑。我哪里做错了?
最佳答案
除了@santiago-squarzon's helpful answer ,这里有两点值得注意:
Get-Item
和 Get-ChildItem
不仅仅是为 FileSystem 制作的,因此返回相关提供者的信息,这是 PSPath 等值的来源。 new FileInfo()
定位相对路径可能找不到您期望的文件,因此我们应该获取完整路径以防万一。 这可以在您的 cmdlet 中实现,以便它返回
PSPath
Get-Content
所需的属性.样本:
dotnet new classlib -o PSSample -n PSSample
cd PSSample
dotnet add package PowerShellStandard.Library --version 5.1.0
code . # I am using VSC - open your editor in the directory.
# Set target framework to netstandard2.0 in .csproj
# Copy and paste below in to Class1.cs
dotnet restore
dotnet build
ipmo .\bin\Debug\netstandard2.0\PSSample.dll
Test-FilePiping -FileName .\Class1.cs | FL *
Test-FilePiping -FileName .\Class1.cs | Get-Content
Cmdlet 类:using System;
using System.IO;
using System.Linq;
using System.Management.Automation;
namespace PSSample
{
[Cmdlet(VerbsDiagnostic.Test, "FilePiping")]
public class PSTestFilePiping : PSCmdlet
{
[Parameter(Position = 0, Mandatory = true)]
public string FileName { get; set; }
protected override void ProcessRecord()
{
string filePath = GetRelativePath(FileName);
var item = InvokeProvider.Item.Get(filePath);
WriteObject(item, true); // true enumerates the collection, because InvokeProvider.Item.Get() returns a collection.
}
protected string GetRelativePath(string path)
{
string currentDir = GetVariableValue("PWD").ToString();
if (Path.IsPathRooted(path) == true || path.StartsWith("\\", StringComparison.CurrentCulture))
{
// Nothing to see here.
}
else
{
if (path == ".")
{
path = currentDir;
}
else if (path.StartsWith("..", StringComparison.CurrentCulture))
{
path = Path.Combine(
string.Join("\\",
currentDir.Split('\\').Take(currentDir.Split('\\').Count() - path.Split('\\').Count(p => p == "..")).ToArray()
),
string.Join("\\", path.Split('\\').Where(f => f != "..").ToArray()));
}
else if (path.StartsWith(".", StringComparison.CurrentCulture))
{
path = Path.Combine(currentDir, path.Substring(2));
}
else
{
path = Path.Combine(currentDir, path);
}
}
return path;
}
}
}
输出:PS C:\Code\PSSample> Test-FilePiping -FileName .\Class1.cs | FL *
PSPath : Microsoft.PowerShell.Core\FileSystem::C:\Code\PSSample\Class1.cs
PSParentPath : Microsoft.PowerShell.Core\FileSystem::C:\Code\PSSample
PSChildName : Class1.cs
PSDrive : C
PSProvider : Microsoft.PowerShell.Core\FileSystem
PSIsContainer : False
Mode : -a----
VersionInfo : File: C:\Code\PSSample\Class1.cs
InternalName:
OriginalFilename:
FileVersion:
FileDescription:
Product:
ProductVersion:
Debug: False
Patched: False
PreRelease: False
PrivateBuild: False
SpecialBuild: False
Language:
BaseName : Class1
Target : {}
LinkType :
Name : Class1.cs
Length : 1947
DirectoryName : C:\Code\PSSample
Directory : C:\Code\PSSample
IsReadOnly : False
Exists : True
FullName : C:\Code\PSSample\Class1.cs
Extension : .cs
CreationTime : 02/05/2021 13:03:22
CreationTimeUtc : 02/05/2021 12:03:22
LastAccessTime : 02/05/2021 13:04:13
LastAccessTimeUtc : 02/05/2021 12:04:13
LastWriteTime : 02/05/2021 13:04:00
LastWriteTimeUtc : 02/05/2021 12:04:00
Attributes : Archive
PS C:\Code\PSSample> Test-FilePiping -FileName .\Class1.cs | Get-Content
using System;
using System.IO;
using System.Linq;
using System.Management.Automation;
namespace PSSample
{
[Cmdlet(VerbsDiagnostic.Test, "FilePiping")]
public class PSTestFilePiping : PSCmdlet
{
[Parameter(Position = 0, Mandatory = true)]
public string FileName { get; set; }
protected override void ProcessRecord()
{
string filePath = GetRelativePath(FileName);
var item = InvokeProvider.Item.Get(filePath);
WriteObject(item, true); // true enumerates the collection, because InvokeProvider.Item.Get() returns a collection.
}
protected string GetRelativePath(string path)
{
string currentDir = GetVariableValue("PWD").ToString();
if (Path.IsPathRooted(path) == true || path.StartsWith("\\", StringComparison.CurrentCulture))
{
// Nothing to see here.
}
else
{
if (path == ".")
{
path = currentDir;
}
else if (path.StartsWith("..", StringComparison.CurrentCulture))
{
path = Path.Combine(
string.Join("\\",
currentDir.Split('\\').Take(currentDir.Split('\\').Count() - path.Split('\\').Count(p => p == "..")).ToArray()
),
string.Join("\\", path.Split('\\').Where(f => f != "..").ToArray()));
}
else if (path.StartsWith(".", StringComparison.CurrentCulture))
{
path = Path.Combine(currentDir, path.Substring(2));
}
else
{
path = Path.Combine(currentDir, path);
}
}
return path;
}
}
}
关于powershell - 无法使用 FileInfo 从二进制模块通过管道传输到 Get-Content,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67351188/