5

我正在为 powershell 上的演示文稿编写一些简短的演示脚本,当然我自己的一个简单演示让我感到困惑。此演示的目的是展示在 powershell 中创建对象的不同方法。这是我的代码:

$file = ls 'C:\temp' | Where-Object {$_.Extension -eq '.txt'}
$file.FullName
$path = 'C:\temp\jdh.txt'
$newfile = New-Object -TypeName System.IO.FileInfo -ArgumentList $path
$newfile.FullName

$file.GetType()
$newfile.GetType()
$file
$newfile

$file | Get-Content | out-null
$newfile | Get-Content | out-null

简单吧?通过不同的方法创建两个 FileInfo 对象并读取它们。输出显示文件是相同的:

C:\temp\jdh.txt
C:\temp\jdh.txt

IsPublic IsSerial Name                                     BaseType                                                                               
-------- -------- ----                                     --------                                                                               
True     True     FileInfo                                 System.IO.FileSystemInfo                                                               
True     True     FileInfo                                 System.IO.FileSystemInfo                                                               

LastWriteTime : 4/10/2013 3:38:29 PM
Length        : 46046
Name          : jdh.txt


LastWriteTime : 4/10/2013 3:38:29 PM
Length        : 46046
Name          : jdh.txt

但是,当 Get-Content 尝试读取 $newfile 对象时,我收到以下错误:

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.
At line:16 char:12
+ $newfile | Get-Content | out-null
+            ~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (C:\temp\jdh.txt:PSObject) [Get-Content], ParameterBindingException
    + FullyQualifiedErrorId : InputObjectNotBound,Microsoft.PowerShell.Commands.GetContentCommand

所以我在错误中注意到它说 PSObject 让我感到困惑,因为在我的输出中似乎 $newfile 是一个 FileInfo 对象。所以我想做的下一个合乎逻辑的事情是将 $newfile 类型转换为类型 [System.IO.FileInfo]。这产生了同样的错误,除了现在而不是 PSObject 它显示 FileInfo 作为类型。那么,如果 $file 和 $newfile 看起来相同并且 get-content 在 $file 上工作,我怎么会收到该错误?使用 new-object 命令时是否有一些细微的差别?

4

2 回答 2

6

我跟踪了使用创建的对象的绑定,New-Object问题是Get-Content无法绑定到FileInfoinfo 对象上的任何属性。

您可以使用以下命令进行检查:

Trace-Command -psHost -Name ParameterBinding {$newFile | gc}
Trace-Command -psHost -Name ParameterBinding {$file | gc}

因此,当您查看成功绑定的跟踪时,您会看到 Literal path 绑定到以Microsoft.PowerShell.Core\FileSystem::PsPath 开头的属性。因此,通过仔细检查比较管道时的对象属性,Get-Member您会发现有效的对象具有这些注释属性,而创建的对象New-Object则没有 -

  • PSChildName
  • PSDrive
  • PSI容器
  • PSParentPath
  • PS路径
  • PSProvider

查看Get-Contentcmdlet 参数,我们可以看到它LiteralPath的别名为PsPath

(Get-Command -Name Get-Content).ParameterSets

  Parameter Name: LiteralPath
    ParameterType = System.String[]
    Position = 0
    IsMandatory = True
    IsDynamic = False
    HelpMessage =
    ValueFromPipeline = False
    ValueFromPipelineByPropertyName = True
    ValueFromRemainingArguments = False
    Aliases = {PSPath}
    Attributes =
      System.Management.Automation.AliasAttribute
      System.Management.Automation.ParameterAttribute

如果您将属性添加到New-Object创建的FileInfo它将起作用:

$newFile | Add-Member -MemberType NoteProperty -Name PsPath -Value 'Microsoft.PowerShell.Core\FileSystem::C:\temp\jdh.txt'
于 2013-04-15T13:50:28.330 回答
-1

请记住,New-Object 只是创建了一个 PowerShell 对象的实例……它没有将任何内容写入文件。使用

Test-Path $path 

显示该文件尚不存在。因此,添加一些代码来实际创建文件,然后分配回它,不会产生错误。

Test-Path $path

$stream = [System.IO.StreamWriter] $path
1..10 | % {
      $stream.WriteLine($s)
}
$stream.close()

$newfile = Get-Content $path

$file | Get-Content | out-null
$newfile | Get-Content | out-null

我们分配回 $newfile 因为它是一个参考。如果我们事后创建文件,它不会自动更新。

于 2013-04-15T13:47:19.507 回答