打开文件时在 Powershell 上使用 Get-Filehash 时出错处理问题

Error handling problem with use Get-Filehash on Powershell when a file is open

提问人:JJ01 提问时间:11/11/2023 最后编辑:mklement0JJ01 更新时间:11/11/2023 访问量:56

问:

我创建了一个命令来查找 Powershell 中文件夹上的重复文件(带有文件长度信息),该命令工作正常,但是当我分析的文件打开时遇到问题。

这是命令:

Get-ChildItem -Recurse |
select-object length, fullname, @{n="Hash";e={get-filehash -algorithm MD5 -path $_.FullName -ErrorAction SilentlyContinue | Select-object -expandproperty Hash}} | 
Group -Property Hash |
where {$_.Count -gt 1} |
foreach { $_.Group | select fullname, hash, length} |
Export-Csv -Path c:\temp\filelist.csv -Delimiter "`t" -NoTypeInformation

当文件打开时,我收到以下错误:

Group : Object reference not set to an instance of an object.
At line:2 char:164
+ ... tinue | Select-object -expandproperty Hash}} | Group -Property Hash |
+                                                    ~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Group-Object], NullReferenceException
    + FullyQualifiedErrorId : System.NullReferenceException,Microsoft.PowerShell.Commands.GroupObjectCommand

问题是 Get-FileHash 失败,并且在打开文件时执行停止。

我只想让打开的文件忽略并命令继续。 我尝试了许多解决方案()但没有成功。 请你帮帮我吗? 谢谢。-ErrorAction SilentlyContinue

PowerShell 错误处理 组对象 get-filehash

评论


答:

2赞 Santiago Squarzon 11/11/2023 #1

使用循环而不是错误处理来更改代码,以跳过 Get-FileHash 无法获取哈希的文件:Select-Object

# Add `-File` to ensure the cmdlet outputs files only
Get-ChildItem -Recurse -File -ErrorAction SilentlyContinue |
    ForEach-Object {
        try {
            [pscustomobject]@{
                Length   = $_.Length
                Fullname = $_.FullName
                Hash     = ($_ | Get-FileHash -Algorithm MD5 -ErrorAction Stop).Hash
            }
        }
        catch {
            Write-Warning $_
        }
    } |
    Group-Object -Property Hash |
    Where-Object Count -GT 1 |
    ForEach-Object Group |
    Export-Csv -Path c:\temp\filelist.csv -Delimiter "`t" -NoTypeInformation

另一种可行的替代方法是使用 -PipelineVariable 公共参数

Get-ChildItem -Recurse -File -ErrorAction SilentlyContinue -PipelineVariable pv |
    # Change `-ErrorAction` to `Continue` if you want errors to be displayed
    Get-FileHash -Algorithm MD5 -ErrorAction SilentlyContinue |
    Select-Object *, @{ N='Length'; E={ $pv.Length }} -ExcludeProperty Algorithm |
    Group-Object Hash |
    Where-Object Count -GT 1 |
    ForEach-Object Group |
    Export-Csv ....
2赞 mklement0 11/11/2023 #2

前言:

  • Santiago 的有用答案提供了更好的命令重新表述绕过了原来的问题。

  • 下面的答案解释了您面临的问题(这是由于 Windows PowerShell 错误造成的),并提供了使命令正常工作所需的即时修复


取代:

get-filehash -algorithm MD5 -path $_.FullName -ErrorAction SilentlyContinue | Select-object -expandproperty Hash

跟:

(get-filehash -algorithm MD5 -path $_.FullName -ErrorAction SilentlyContinue).Hash

通过使用属性访问 (),如果命令失败且不产生任何输出,则表达式结果变为,而随之变为类似 null 的“可枚举 null”,又名“自动化 Null”值(表示缺少命令输出的特殊 [System.Management.Automation.Internal.AutomationNull]::Value] 单例)。.Hash$nullGet-FileHashSelect-Object -ExpandProperty

由于 Windows PowerShell 中的 bug,后者会导致问题。请继续阅读了解详情。


你在 Group-ObjectWindows PowerShell 实现中看到了一个 bug,该 bug 已在 PowerShell (Core) 7+ 中修复:

如果输入对象中的分组属性值恰好是前面提到的“可枚举 null”,则会发生您看到的错误。

下面是一个简化的示例,使用(即执行一个空脚本块)来创建“可枚举的 null”:& {}

# !! In *Windows PowerShell only*, the following error occurs:
#    Group-Object : Object reference not set to an instance of an object.
[pscustomobject] @{ Foo = 42 }, [pscustomobject] @{ Foo = & {} } |
  Group-Object Foo