powershell - 无法使用 FileInfo 从二进制模块通过管道传输到 Get-Content

标签 powershell

我很难将文件传送到 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$yFileInfo对象根据 GetType() :
IsPublic IsSerial Name                                     BaseType
True     True     FileInfo                                 System.IO.FileSystemInfo
然而我不能这样做:$x | gcThe 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 ,这里有两点值得注意:

  • PowerShell 命令,如 Get-ItemGet-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/

    相关文章:

    powershell - 如何在powershell中传递多个参数文件

    powershell - PowerShell 中是否有字符串连接快捷方式?

    powershell - 如何以管理员身份运行 powershell 脚本?

    Powershell 在启动时挂起

    date - 键盘上的Powershell日期

    powershell - ssh-keygen: 系统找不到指定的路径

    windows - 如何查找 checkout 的文件

    powershell - 使用 PowerShell 以管理员身份运行命令?

    python - Powershell 无法将 conda 识别为 cmdlet、函数或可运行程序

    azure - 有人创建了 ARM 模板来注册应用程序并在 Azure AD 中创建客户端 key 吗?