Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Change Get-FileHash to close file handles before writing output (#12474)
Browse files Browse the repository at this point in the history
# Conflicts:
#	src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetHash.cs
HumanEquivalentUnit authored and TravisEz13 committed Jun 8, 2020
1 parent c3cd9d4 commit 359cdee
Showing 2 changed files with 71 additions and 31 deletions.
Original file line number Diff line number Diff line change
@@ -126,40 +126,10 @@ protected override void ProcessRecord()

foreach (string path in pathsToProcess)
{
byte[] bytehash = null;
string hash = null;
Stream openfilestream = null;

try
if (ComputeFileHash(path, out string hash))
{
openfilestream = File.OpenRead(path);
bytehash = hasher.ComputeHash(openfilestream);

hash = BitConverter.ToString(bytehash).Replace("-", string.Empty);
WriteHashResult(Algorithm, hash, path);
}
catch (FileNotFoundException ex)
{
var errorRecord = new ErrorRecord(
ex,
"FileNotFound",
ErrorCategory.ObjectNotFound,
path);
WriteError(errorRecord);
}
catch (UnauthorizedAccessException ex)
{
var errorRecord = new ErrorRecord(
ex,
"UnauthorizedAccessError",
ErrorCategory.InvalidData,
path);
WriteError(errorRecord);
}
finally
{
openfilestream?.Dispose();
}
}
}

@@ -181,6 +151,61 @@ protected override void EndProcessing()
}
}

/// <summary>
/// Read the file and calculate the hash.
/// </summary>
/// <param name="path">Path to file which will be hashed.</param>
/// <param name="hash">Will contain the hash of the file content.</param>
/// <returns>Boolean value indicating whether the hash calculation succeeded or failed.</returns>
private bool ComputeFileHash(string path, out string hash)
{
byte[] bytehash = null;
Stream openfilestream = null;

hash = null;

try
{
openfilestream = File.OpenRead(path);

bytehash = hasher.ComputeHash(openfilestream);
hash = BitConverter.ToString(bytehash).Replace("-", string.Empty);
}
catch (FileNotFoundException ex)
{
var errorRecord = new ErrorRecord(
ex,
"FileNotFound",
ErrorCategory.ObjectNotFound,
path);
WriteError(errorRecord);
}
catch (UnauthorizedAccessException ex)
{
var errorRecord = new ErrorRecord(
ex,
"UnauthorizedAccessError",
ErrorCategory.InvalidData,
path);
WriteError(errorRecord);
}
catch (IOException ioException)
{
var errorRecord = new ErrorRecord(
ioException,
"FileReadError",
ErrorCategory.ReadError,
path);
WriteError(errorRecord);
}
finally
{
openfilestream?.Dispose();
}

return hash != null;
}

/// <summary>
/// Create FileHashInfo object and output it.
/// </summary>
Original file line number Diff line number Diff line change
@@ -70,4 +70,19 @@ Describe "Get-FileHash" -Tags "CI" {
$result.Path | Should -Be $testDocument
}
}

Context "File should be closed before Get-FileHash writes pipeline output" {
It "Should be able to edit the file without 'file is in use' exceptions" {
# This test runs against a copy of the document
# because it involves renaming it,
# and that might break tests added later on.
$testDocumentCopy = "${testDocument}-copy"
Copy-Item -Path $testdocument -Destination $testDocumentCopy

$newPath = Get-FileHash -Path $testDocumentCopy | Rename-Item -NewName {$_.Hash} -PassThru
$newPath.FullName | Should -Exist

Remove-Item -Path $testDocumentCopy -Force
}
}
}

0 comments on commit 359cdee

Please sign in to comment.