How to check which files are corrupted in PowerShell

Welcome to Programming Tutorial official website. Today - we are going to cover how to solve / find the solution of this error How to check which files are corrupted in PowerShell on this date .

I often run chkdsk /f X:(X here stands for actual drive letters), to check and fix filesystem errors, but it doesn’t report which files are corrupted.

I use PSCore7.1 on Windows 10 20H2 x64, I want to check which files are corrupted by comparing hash and timestamp of a file against recorded hash and timestamp of that path, if the hash has changed and timestamp hasn’t changed, then the file is corrupted.

PowerShell has builtin functions to get hash code, but it isn’t SHA-256, I can use

Get-ChildItem -Path $path -Force -File -Recurse

To get files, .Fullname to get full path of files and .LastWriteTime to get timestamp, but here I am talking about whole disks so I want it to be as fast as possible.

But I don’t know how to get SHA-256, though it shouldn’t be hard.

Then my idea is to create a [PSCustomObject] with three noteproperties: Fullname, LastWriteTime and SHA-256, I can do this, then export it directly to a database file (append), unfortunately currently I only managed to export to txt files, and it would be difficult to query txt files.

Finally if the database doesn’t exist, create it and exit, else if it does exist, get content of the database, create a new one in console and look for corrupted files.

I can use [System.IO.File]::Exists() to check if file exists, Convertfrom-String to convert txt to pscustomobject array, though it’s buggy, or loop through file by index using for loop, in each iteration get values by regex match then create a PSCustomObject and add to array using +=, though this might be slow.

The final step to find corrupted files would be:

for ($i=0;$i -lt $NewDB.count;$i++) {
    $Database | Where-Object{$_.Fullname -eq $NewDB[$i].Fullname -and $_.LastWriteTime -eq $NewDB[$i].LastWriteTime -and $_.SHA256 -ne $NewDB[$i].SHA256}
}

I am not dumb, I am just inexperienced, currently there are there things required by this script which I am unable to do:

1, Get all files of a drive as fast as possible

2, Get SHA-256 of files

3, Export and import data

Please help me complete the script! Any help would be appreciated, I would be very grateful, and the answer may also help many other people, I say thanks in advance.

Update: Now I am looking for ways to export data to csv format, do I just use Out-File *.csv? Will it format data automatically? How do I control the format? And how to convert csv directly into an array of PSCustomObject?

Edit: fixed the missing index in the where line. Re-Edit: completed the for loop and where-object process to make it actually working, just in case someone would doubt my abilities or someone else who sees this and don’t know how to do it.

Answer

Getting hashes of a file, even the SHA level is a common thing and can be done natively in PowerShell, no need for 3rdP software. Always look at the help file full details first.

As for this…

I often run chkdsk /f X:(X here stands for actual drive letters), to check and fix filesystem errors, but it doesn’t report which files are corrupted.

… because that is not what that tool is for. It’s to as documented.

https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/chkdsk

As for this…

…I want to check which files are corrupted by comparing hash and timestamp of a file against recorded hash and timestamp of that path, if the hash has changed and timestamp hasn’t changed, then the file is corrupted.

… your PowerShell version has nothing to do with this use case. File hash change does not necessarily mean corruption. It means the content in the file was changed. A corrupt file in normal cases is not accessible because it’s damaged..

As for …

…PowerShell has built-in functions to get hash code, but it isn’t SHA-256…

… not true, this defined in the help files.

As for…

Get-ChildItem -Path $path -Force -File -Recurse

… it does not matter, because performance is controlled by the number of files targets, drive size, drive performance, CPU performance, ram, other processes impacting operational state (AV, etc), etc. Btw, doing this hash check will slow it down even more.

This means you break this up into chunks, PowerShell jobs, PowerShell workflows, Parallel processing to get some better performance.

As for…

But I don’t know how to get SHA-256…

… the DPAPI of windows filesystem defaults to SHA-256, unless the programmer, data owner defined it otherwise using the DPAPI.

Yet, if you absolutely want to see that, the built-in cmdlet, Get-FileHash allows you to do this. It’s defined in the help files.

# Get specifics for a module, cmdlet, or function
(Get-Command -Name Get-FileHash).Parameters
(Get-Command -Name Get-FileHash).Parameters.Keys
Get-help -Name Get-FileHash -Examples
# Results
<#
Get-FileHash $pshomepowershell.exe | Format-List
Get-FileHash C:UsersAndrisDownloadsContoso8_1_ENT.iso -Algorithm SHA384 | Format-List
#>
Get-help -Name Get-FileHash -Full
Get-help -Name Get-FileHash -Online



Get-ChildItem -Path D:Temp | 
ForEach{Get-FileHash -Path $PSItem.FullName}
# Results
<#
Algorithm       Hash                   Path                                                                                                      
---------       ----                    ----                                                                                                      
SHA256          84F07167E6A9E3...      D:Temp(MSINFO32) command-line...                                                        
SHA256          A3CB4415D3FAAA...      D:Temp23694d1213305764-revisi... 
...
#>

See also:

Carbon Black Defense: How to get a SHA 256 hash of a file on Windows and Mac

Steps for Windows – Powershell Open Windows Powershell Enter the following command (replace <path/to/file> with the absolute path of the file or application you want to get the hash from):

As for…

Then my idea is to create a [PSCustomObject] with three noteproperties: Fullname, LastWriteTime and SHA-256,…

… This:

Get-ChildItem -Path D:Temp | 
ForEach{
    [PSCustomObject] @{
        FileName      = $PSItem.FullName
        LastWriteTIme = $PSItem.LastWriteTime
        ShaVersion    = (Get-FileHash -Path $PSItem.FullName).Algorithm 
        Hash          = (Get-FileHash -Path $PSItem.FullName).Hash 
    }
}
# Results
<#
FileName                        LastWriteTIme      ShaVersion Hash                                             
--------                        -------------      ---------- ----                                             
D:Temp(MSINFO32) command...   06-Aug-16 18:25:22 SHA256     84F07167E6A9E3...
D:Temp23694d1213305764-r...   06-Feb-20 14:02:47 SHA256     A3CB4415D3FAAA...
D:Temp5 Free Software Yo...   29-Dec-19 21:50:56 SHA256     3427AD8DC44986...
#>

Update as per your comment ‘how to export to and import from csv’

Get-ChildItem -Path D:Temp | 
ForEach{
    [PSCustomObject] @{
        FileName      = $PSItem.FullName
        LastWriteTIme = $PSItem.LastWriteTime
        ShaVersion    = (Get-FileHash -Path $PSItem.FullName).Algorithm 
        Hash          = (Get-FileHash -Path $PSItem.FullName).Hash 
    } | Export-Csv -Path 'D:TempFileMoniotReport.csv' -NoTypeInformation -Append
}
Import-Csv -Path 'D:TempFileMoniotReport.csv'