Public/File/Out-FileHash.ps1
using namespace System.Security.Cryptography using namespace System.IO function Out-FileHash { param( [Parameter(Mandatory,Position=0,ValueFromPipeline)] [String[]] $Path, [Parameter(ValueFromPipelineByPropertyName)] [ValidateSet('ALL','SHA1','SHA256','SHA384','SHA512','MD5')] [string] $Algorithm = 'SHA256', [int64] $BufferSize = 1mb, [switch] $NoProgress = $false ) begin { $AlgorithmObject = [HashAlgorithm]::Create($Algorithm); $ErrorOccurred = $false; } process { foreach ($File in $Path) { $FullFilepath = [Path]::GetFullPath($File) $FileStream = [File]::OpenRead($FullFilepath); $CryptoStream = [CryptoStream]::new(([Stream]::Null), $AlgorithmObject, "Write"); $Buffer = New-Object Byte[] $BufferSize; while ($BytesRead = $FileStream.Read($Buffer, 0, $BufferSize)){ if (!$NoProgress) { $Filename = [System.IO.Path]::GetFileNameWithoutExtension($File) [Decimal] $ProgressRaw = $FileStream.Position / $FileStream.Length [String] $Status = "Progress: {0:P2}" -f $ProgressRaw $PercentComplete = $ProgressRaw * 100 $CurrentOperation = "{0} of {1} bytes hashed" -f $FileStream.Position, $FileStream.Length $WriteProgressSplat = @{ Id = 2 Activity = "Out-FileHash is processing $Filename ($Algorithm)..." Status = $Status PercentComplete = $PercentComplete CurrentOperation = $CurrentOperation } Write-Progress @WriteProgressSplat } # Write to the Stream from the buffer and then flush the CryptoStream block queue. $CryptoStream.Write($Buffer, 0, $BytesRead); $CryptoStream.Flush(); } $FileStream.Close(); $FileStream.Dispose(); # Finalize the CryptoStream, store the result into the table, and then dispose of # the CryptoStream and HashAlgorithm provider. $CryptoStream.FlushFinalBlock(); $FinalFileObject = Get-Item -Path $FullFilepath -Force $FinalFileHash = ($AlgorithmObject.Hash | ForEach-Object { $_.ToString("X2") }) -join '' $FinalFileRelativeName = ($FinalFileObject.FullName).Replace($FullFilepath, ".\") $FinalFileTimespanStart = [timezone]::CurrentTimeZone.ToLocalTime([datetime]'1/1/1970') $FinalFileTimespan = New-TimeSpan -Start $FinalFileTimespanStart -End $FinalFileObject.LastWriteTime $FinalFileLastWriteTime = $FinalFileTimespan.TotalMilliseconds -as [Int64] $FinalFileSize = $FinalFileObject.Length $FT = [PSCustomObject]@{ FullName = ($FinalFileObject.FullName) RelativeName = $FinalFileRelativeName Size = $FinalFileSize LastWriteTime = $FinalFileLastWriteTime Hash = $FinalFileHash }; $FileStream.Close() $FileStream.Dispose() $CryptoStream.Close() $CryptoStream.Dispose() $AlgorithmObject.Dispose(); } } end { if (($Combine -And ($ErrorOccurred -Eq $false)) -Or ((-Not $Combine) -And ($ErrorOccurred -Eq $false))) { $result = $FT; } else { $result = $null; } $result } } |