1. # Get-FileHash.ps1
  2. # Written by Bill Stewart (bstewart@iname.com)
  3.  
  4. #requires -version 2
  5.  
  6. <#
  7. .SYNOPSIS
  8. Outputs the MD5 or SHA1 hash for one or more files.
  9.  
  10. .DESCRIPTION
  11. Outputs the MD5 or SHA1 hash for one or more files.
  12.  
  13. .PARAMETER Path
  14. Specifies the path to one or more files. Wildcards are permitted.
  15.  
  16. .PARAMETER LiteralPath
  17. Specifies a path to the file. Unlike Path, the value of LiteralPath is used exactly as it is typed. No characters are interpreted as wildcards. If the path includes escape characters, enclose it in single quotation marks.
  18.  
  19. .PARAMETER HashType
  20. The hash type to compute; either MD5 or SHA1. The default is MD5.
  21.  
  22. .INPUTS
  23. System.String, System.IO.FileInfo
  24.  
  25. .OUTPUTS
  26. PSObjects containing the file paths and hash values
  27.  
  28. .EXAMPLE
  29. PS C:\> Get-FileHash C:\Windows\Notepad.exe
  30. Outputs the MD5 hash for the specified file.
  31.  
  32. .EXAMPLE
  33. PS C:\> Get-FileHash C:\Windows\Explorer.exe,C:\Windows\Notepad.exe -HashType SHA1
  34. Outputs the SHA1 hash for the specified files.
  35.  
  36. .EXAMPLE
  37. PS C:\> Get-ChildItem C:\Scripts\*.ps1 | Get-FileHash
  38. Outputs the MD5 hash for the specified files.
  39.  
  40. .EXAMPLE
  41. PS C:\> Get-FileHash Download1.exe,Download2.exe -HashType SHA1
  42. Outputs the SHA1 hash for two files. You can compare the hash values to determine if the files are identical.
  43. #>
  44.  
  45. [CmdletBinding(DefaultParameterSetName="Path")]
  46. param(
  47.   [Parameter(ParameterSetName="Path",Position=0,Mandatory=$TRUE,ValueFromPipeline=$TRUE)]
  48.     [String[]] $Path,
  49.   [Parameter(ParameterSetName="LiteralPath",Position=0,Mandatory=$TRUE)]
  50.     [String[]] $LiteralPath,
  51.   [Parameter(Position=1)]
  52.     [String] $HashType="MD5"
  53. )
  54.  
  55. begin {
  56.   switch ($HashType) {
  57.     "MD5" {
  58.       $Provider = new-object System.Security.Cryptography.MD5CryptoServiceProvider
  59.       break
  60.     }
  61.     "SHA1" {
  62.       $Provider = new-object System.Security.Cryptography.SHA1CryptoServiceProvider
  63.       break
  64.     }
  65.     default {
  66.       throw "HashType must be one of the following: MD5 SHA1"
  67.     }
  68.   }
  69.  
  70.   # If the Path parameter is not bound, assume input comes from the pipeline.
  71.   if ($PSCMDLET.ParameterSetName -eq "Path") {
  72.     $PIPELINEINPUT = -not $PSBOUNDPARAMETERS.ContainsKey("Path")
  73.   }
  74.  
  75.   # Returns an object containing the file's path and its hash as a hexadecimal string.
  76.   # The Provider object must have a ComputeHash method that returns an array of bytes.
  77.   function get-filehash2($file) {
  78.     if ($file -isnot [System.IO.FileInfo]) {
  79.       write-error "'$($file)' is not a file."
  80.       return
  81.     }
  82.     $hashstring = new-object System.Text.StringBuilder
  83.     $stream = $file.OpenRead()
  84.     if ($stream) {
  85.       foreach ($byte in $Provider.ComputeHash($stream)) {
  86.         [Void] $hashstring.Append($byte.ToString("X2"))
  87.       }
  88.       $stream.Close()
  89.     }
  90.     "" | select-object @{Name="Path"; Expression={$file.FullName}},
  91.       @{Name="$($Provider.GetType().BaseType.Name) Hash"; Expression={$hashstring.ToString()}}
  92.   }
  93. }
  94.  
  95. process {
  96.   if ($PSCMDLET.ParameterSetName -eq "Path") {
  97.     if ($PIPELINEINPUT) {
  98.       get-filehash2 $_
  99.     }
  100.     else {
  101.       get-item $Path -force | foreach-object {
  102.         get-filehash2 $_
  103.       }
  104.     }
  105.   }
  106.   else {
  107.     $file = get-item -literalpath $LiteralPath
  108.     if ($file) {
  109.       get-filehash2 $file
  110.     }
  111.   }
  112. }