Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

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

I created a command to find duplicate file on folders (with file length information) in Powershell that works fine but I have problem when a file that I analyze is open.

This is the command:

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

When the file is open I receive this error:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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

The problem is that Get-FileHash fails and the execution stop when a file is open.

I want only that the files that is open ignore and the command continue.
I tried many solutions (-ErrorAction SilentlyContinue) without success.
Please can you help me?
Thank you.

>Solution :

Change your code using a loop instead of Select-Object and error handling to skip files where Get-FileHash fails to obtain the hash:

# 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

Another alternative that should work would be using -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 ....
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading