Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/powershell/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Powershell 无法通过管道使用FileInfo从二进制模块获取内容_Powershell - Fatal编程技术网

Powershell 无法通过管道使用FileInfo从二进制模块获取内容

Powershell 无法通过管道使用FileInfo从二进制模块获取内容,powershell,Powershell,我很难通过管道传输文件来获取内容(PS 5.1版) 模块代码: [Cmdlet(VerbsDiagnostic.Test, "FilePiping")] public class PSTestFilePiping : PSCmdlet { [Parameter(Position = 0, Mandatory = true)] public string FileName { get; set; } protected override void Pr

我很难通过管道传输文件来获取内容(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=测试文件管道。\readme.txt

$y=gci。\readme.txt

(为了简单起见,我使用了相对路径)

根据
GetType()
$x
$y
都是
FileInfo
对象:

但我不能这样做:

$x | gc

无法将输入对象绑定到该命令的任何参数,因为该命令不接受管道输入,或者输入及其属性与接受管道输入的任何参数都不匹配。

但我可以做到:

$y|gc

这让我很困惑


我哪里出错了?

希望这能帮助您识别错误:

PS /> 'Hello world!' > test.txt
PS /> $reader = [System.IO.FileInfo]::new('test.txt')
如果我尝试通过管道将此对象直接传输到
获取内容
,它将抛出与您得到的错误相同的错误:

使用此选项:

或者这个:

结果:

这是因为
[System.IO.FileInfo]
返回的属性与
获取内容
接受为
值fromPipelineByPropertyName
的参数不匹配:

PS /> $reader | gm -MemberType Property

   TypeName: System.IO.FileInfo

Name              MemberType Definition
----              ---------- ----------
Attributes        Property   System.IO.FileAttributes Attributes {get;set;}
CreationTime      Property   datetime CreationTime {get;set;}
CreationTimeUtc   Property   datetime CreationTimeUtc {get;set;}
Directory         Property   System.IO.DirectoryInfo Directory {get;}
DirectoryName     Property   string DirectoryName {get;}
Exists            Property   bool Exists {get;}
Extension         Property   string Extension {get;}
FullName          Property   string FullName {get;}
IsReadOnly        Property   bool IsReadOnly {get;set;}
LastAccessTime    Property   datetime LastAccessTime {get;set;}
LastAccessTimeUtc Property   datetime LastAccessTimeUtc {get;set;}
LastWriteTime     Property   datetime LastWriteTime {get;set;}
LastWriteTimeUtc  Property   datetime LastWriteTimeUtc {get;set;}
Length            Property   long Length {get;}
Name              Property   string Name {get;}
但是,如果我们使用我在评论中提到的任何属性创建一个对象,
Get Content
将接受它作为输入并毫无问题地读取它:

PS /> [PSCustomObject]@{ Path = $reader.FullName } | Get-Content
Hello world!

PS /> [PSCustomObject]@{ LiteralPath = $reader.FullName } | Get-Content
Hello world!

PS /> [PSCustomObject]@{ PSPath = $reader.FullName } | Get-Content
Hello world!
Get ChildItem
工作正常,因为返回的对象具有PSPath属性

确定哪些参数被PipelineByPropertyName接受为
值的最佳方法是依靠:

-文字路径 类型 字符串[] 别名 私人有限公司 位置 命名 默认值 没有一个 接受管道输入 真的 接受通配符 假的 除此之外,这里还有两件事值得注意:

  • Get Item
    Get ChildItem
    这样的PowerShell命令不仅仅是为文件系统生成的,因此会返回相关提供程序的信息,而PSPath等值正是来自于这些提供程序
  • 使用
    newfileinfo()
    定位相对路径可能找不到所需的文件,因此我们应该获取完整路径以防万一
这可以在cmdlet中实现,以便它返回
Get Content
所需的
PSPath
属性

样本:

dotnet新类库-o PSSample-n PSSample
cd-PSSample
dotnet添加包PowerShellStandard.Library--版本5.1.0
代码#我正在使用VSC-在目录中打开编辑器。
#在.csproj中将目标框架设置为netstandard2.0
#将下面的内容复制并粘贴到Class1.cs
网络还原
网络构建
ipmo.\bin\Debug\netstandard2.0\PSSample.dll
测试文件管道-文件名。\Class1.cs | FL*
测试文件管道-文件名。\Class1.cs |获取内容
Cmdlet类:

使用系统;
使用System.IO;
使用System.Linq;
使用系统、管理、自动化;
名称空间PSSample
{
[Cmdlet(VerbsDiagnostic.Test,“文件管道”)]
公共类PSTestFilePiping:PSCmdlet
{
[参数(位置=0,强制=true)]
公共字符串文件名{get;set;}
受保护的覆盖无效ProcessRecord()
{
字符串filePath=GetRelativePath(文件名);
var item=InvokeProvider.item.Get(文件路径);
WriteObject(item,true);//true枚举集合,因为InvokeProvider.item.Get()返回集合。
}
受保护的字符串GetRelativePath(字符串路径)
{
字符串currentDir=GetVariableValue(“PWD”).ToString();
if(Path.IsPathRooted(Path)==true | | Path.StartsWith(“\\”,StringComparison.CurrentCulture))
{
//这里没什么可看的。
}
其他的
{
如果(路径==”)
{
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));
}
其他的
{
path=path.Combine(currentDir,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
文件系统
装饰了
System.IO.FileSystemInfo
实例(和),并使用PowerShell的

管道输入对象的
.PSPath
属性值绑定到cmdlet的
-LiteralPath
参数,例如,由于所述参数是用
值fromPipelineByPropertyName
属性声明的,并且
LiteralPath
是用
[别名(“PSPath”)]
属性修饰的;也就是说,
PSPath
LiteralPath
的别名

在撰写本文时,PowerShell提供程序将这些ETS属性添加为实例属性,这就是直接构造的
System.IO.FileInfo
没有这些属性的原因,从而导致出现您看到的症状(由于缺少
.PSPath
属性,无法绑定到
-LiteralPath
参数)

如果提供程序要使用类型
Get-Content: 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.
PS /> $reader | gm -MemberType Property

   TypeName: System.IO.FileInfo

Name              MemberType Definition
----              ---------- ----------
Attributes        Property   System.IO.FileAttributes Attributes {get;set;}
CreationTime      Property   datetime CreationTime {get;set;}
CreationTimeUtc   Property   datetime CreationTimeUtc {get;set;}
Directory         Property   System.IO.DirectoryInfo Directory {get;}
DirectoryName     Property   string DirectoryName {get;}
Exists            Property   bool Exists {get;}
Extension         Property   string Extension {get;}
FullName          Property   string FullName {get;}
IsReadOnly        Property   bool IsReadOnly {get;set;}
LastAccessTime    Property   datetime LastAccessTime {get;set;}
LastAccessTimeUtc Property   datetime LastAccessTimeUtc {get;set;}
LastWriteTime     Property   datetime LastWriteTime {get;set;}
LastWriteTimeUtc  Property   datetime LastWriteTimeUtc {get;set;}
Length            Property   long Length {get;}
Name              Property   string Name {get;}
PS /> [PSCustomObject]@{ Path = $reader.FullName } | Get-Content
Hello world!

PS /> [PSCustomObject]@{ LiteralPath = $reader.FullName } | Get-Content
Hello world!

PS /> [PSCustomObject]@{ PSPath = $reader.FullName } | Get-Content
Hello world!
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;
        }
    }
}