【问题标题】:Powershell Get-Content failing spuriouslyPowershell Get-Content 虚假失败
【发布时间】:2019-02-03 22:42:49
【问题描述】:

我有一个相当简单的 PS 脚本,它运行良好,但现在突然开始出错。我已将问题部分缩小到几个 Get-Content 语句。以下是脚本受影响部分的样子:

$pathSource = "D:\FileDirectory"
Set-Location -Path $pathSource
Get-Content -Encoding UTF8 -Path FilesA*.txt | Out-File -Encoding ASCII FilesA_Digest.txt
Get-Content -Encoding UTF8 -Path FilesB*.txt | Out-File -Encoding ASCII FilesB_Digest.txt

这部分脚本收集了一组同名文件并将它们连接成一个文本文件以上传到 FTP 站点。需要 Get-Content/Out-File,因为 FTP 站点的原始文件编码不正确。该脚本运行良好,每晚运行一次,持续数周。现在,当到达 Get-Content 语句时,它会收到以下错误:

Get-Content : A parameter cannot be found that matches parameter name 'Encoding'.
At D:\FileDirectory\Script.ps1

环境是 Windows Server 2016。我在 Get-Content 参数上尝试了不同的变体,但没有任何效果。我知道有一个错误会影响网络映射驱动器,但这里不是这种情况——所有文件都是本地文件。

有什么想法/建议吗?

【问题讨论】:

  • -Path FilesA*.txt 将在连续运行中包含 Out-File FilesA_Digest.txt
  • 顺便说一句:将-Encoding ASCII 应用于(最初)UTF-8 编码的数据可能会导致信息丢失:输入中的任何字符都在 ASCII 之外范围将被音译为 literal ? 字符。 (相比之下,如果原始数据包含 only ASCII 范围的字符,则根本不需要转码,因为 UTF-8 是 ASCII 的 超集。)
  • @LotPings -- 这是我的错字,因为我使用的虚拟文件名实际上与原始脚本不匹配。原始脚本不存在这个问题。
  • @mklelement0 -- 我意识到可能存在数据丢失问题,但事实是不会有,因为源文件不包含标准 ASCII 集之外的任何字符。
  • @npowroz:我明白了,但这与您的说法“原始文件编码不正确”相矛盾:如果您可以使用 -Encoding UTF8 正确读取它们并且它们只包含 ASCII -range 字符,你根本不需要任何转码。

标签: powershell


【解决方案1】:

我能想到的唯一合理的解释是 custom Get-Content 命令缺少 -Encoding 参数是 遮蔽(覆盖)标准Get-Content cmdlet 在执行脚本的 PowerShell 会话中。

演示:

# Define a custom Get-Content command (function) that accepts only 
# a (positional) -Path parameter, not also -Encoding.
function Get-Content { [CmdletBinding()] param([string] $Path) }

# Now try to use Get-Content -Encoding
Get-Content -Encoding Utf8 FilesA*.txt

您将看到与您的问题相同的错误消息。

使用Get-Command Get-Content -All查看所有名为Get-Content的命令有效命令列在最前面。

然后检查任何自定义命令可能来自哪里;例如,您的 $PROFILE 脚本可能包含一个。

排除 $PROFILE 是罪魁祸首,请在不加载配置文件脚本的情况下启动 PowerShell,然后检查 Get-Content

powershell -noprofile  # Windows PowerShell
pwsh -noprofile        # PowerShell Core

一种排除自定义覆盖的简单方法临时通过其模块限定名称调用命令强>:

Microsoft.Powershell.Management\Get-Content ...

您可以按如下方式确定内置 cmdlet 的模块来源名称:

PS> (Get-Command Get-Content -All)[-1].ModuleName
Microsoft.PowerShell.Management

在紧要关头,您还可以推断帮助主题的URL

【讨论】:

  • 我已经尝试了你所有的建议,但仍然遇到同样的错误,所以现在我真的很茫然。我知道我使用的是内置的 Get-Content,没有覆盖,没有自定义,没有什么特别的。这真的很奇怪。
  • @npowroz:因此,如果您从以-noprofile 开始的PowerShell 实例运行*.ps1 脚本并报告Microsoft.PowerShell.Management for (Get-Command Get-Content).ModuleName,您仍然会收到相同的错误吗?
  • @npowroz:如果您使用Format-Hex <your-script>,您的文件中是否存在任何不可见的控制字符?
  • 在我使用 -noprofile 启动后,执行“Get-Command Get-Content”会返回“Version 3.1.0.0 / Source Microsoft.PowerShell.Management”。我已经使用 Format-Hex 丢弃了它,但我没有看到任何突出的东西。
  • @npowroz:查看问题是否特定于具有给定 PowerShell / OS 版本的给定机器。
【解决方案2】:

out 命令似乎有问题。你能试试下面的代码吗:

$pathSource = "D:\FileDirectory"
Set-Location -Path $pathSource
Get-Content -Encoding UTF8 -Path FilesA*.txt | Set-Content  -Encoding ASCII -path FilesA_Digest.txt
Get-Content -Encoding UTF8 -Path FilesB*.txt | Set-Content  -Encoding ASCII -path FilesB_Digest.txt

【讨论】:

  • Out-File 不是问题,因为 OP 的错误消息明确提到 Get-Content 作为有问题的 cmdlet:Get-Content : A parameter cannot be found that matches parameter name 'Encoding'.
【解决方案3】:

好吧,我不知道它为什么失败,但我可以说我已经完全重写了脚本,现在它可以工作了。我必须注意,鉴于正在发生的错误,我也不知道为什么它现在可以工作。

我对 Get-Content 命令行开关使用完全相同的调用,带有 -Encoding 参数和带有自己的 -Encoding 参数的 Out-File 管道。我正在执行与先前版本的脚本完全相同的操作。唯一明显不同的部分是执行已处理文件的 FTP 传输的部分。我现在只使用 PowerShell 而不是 CuteFTP 来执行传输,而且一切似乎都正常工作。

感谢所有做出贡献的人。

干杯 规范

【讨论】:

    【解决方案4】:

    不确定它是否有帮助,但我遇到了同样的问题:

    $n = ni '[hi]' -value 'some text'
    gc $n -Encoding Byte
    $f = ls *hi*
    $f.where{$_.name -eq '[hi]'}.Delete()
    

    看起来已经有一系列关于这个已知错误see this answer的 SO

    【讨论】:

      猜你喜欢
      • 2018-06-26
      • 2016-02-27
      • 2011-03-21
      • 2014-11-26
      • 2018-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多