Change Get-FileHash to close file handles before writing output (#12474)

This commit is contained in:
HumanEquivalentUnit
2020-04-30 20:54:20 +05:00
committed by GitHub
parent 20a1e1cc3d
commit 9e3b34035f
2 changed files with 71 additions and 40 deletions
@@ -126,49 +126,10 @@ namespace Microsoft.PowerShell.Commands
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);
}
catch (IOException ioException)
{
var errorRecord = new ErrorRecord(
ioException,
"FileReadError",
ErrorCategory.ReadError,
path);
WriteError(errorRecord);
}
finally
{
openfilestream?.Dispose();
}
}
}
@@ -190,6 +151,61 @@ namespace Microsoft.PowerShell.Commands
}
}
/// <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>
@@ -77,4 +77,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
}
}
}