I created a function to get the hash value of a file. Normally the output is 3 lines. My function does 3 things:
- extracts the hash value
- removes the spaces in between the hash value
- prints hash value
Here is the output when using CertUtil -hashfile FILENAME.EXE SHA1
SHA1 hash of file FILENAME.EXE:
XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX
CertUtil: -hashfile command completed successfully.
My function:
function MyHash($file, $hashtype) {
$hash = CertUtil -hashfile $file $hashtype
$hashstring = $hash[1] -replace ' ',''
echo $hashstring
}
my output:
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Am I ok calling commands such as CertUtil
from within a function the way I am doing? Can the syntax and code be improved? I feel like I'm just throwing commands inside a function but it works.
2 Answers 2
I think your code is okay. Some notes:
- PowerShell 4 has a Get-FileHash command. Granted, most people don't have PS4 yet.
- Why reinvent the wheel when other people have already done it better? E.g.: Boe Prox's Get-FileHash.
- I believe the PowerShell Community Extensions also have a file hash command.
- The dependency on certutil is not ideal. Do we know that the output format from all versions of certutil will be same everywhere and for all time?
- You don't need the
echo
in the last line. The last line can consist of just$hashstring
by itself. Since that value is not being consumed, it will be placed in the pipeline. (It's important, by the way, to understand how the pipeline works to use PowerShell.)
-
\$\begingroup\$ Using powershell 4 and Get-FileHash returns the checksum without spaces. \$\endgroup\$jes516– jes5162015年12月29日 05:19:36 +00:00Commented Dec 29, 2015 at 5:19
I agree with all of Dangph's points.
The .Net framework also has classes built-in to do hashing and then you can choose your algorithm. Check out the Validate-Thumbprint
function I wrote here to see how to enumerate the hash algorithms available on the system.
Regarding the last point about echo
, it's more than just unnecessary to use it. As mentioned, it's better to return the item to the pipeline, so that the caller of the function can decide what to do with it.
echo
is also an alias for Write-Output
and I'm of the belief that in re-usable code you should not use aliases, positional parameters, or parameter abbreviations.
You should also use [CmdletBinding()]
to define your function as an advanced function so that it supports common parameters and other goodies. You can add pipeline support then as well.
Consider the longer function definition format with a param()
block and define the type of each of your parameters, validation, etc.
-
\$\begingroup\$ Hey ... I am guessing this was a typo or muscle memory but
echo -> Write-Output
\$\endgroup\$Matt– Matt2016年02月16日 01:19:56 +00:00Commented Feb 16, 2016 at 1:19 -
\$\begingroup\$ @Matt wow nope, it was plain old ignorance! Thanks for catching this; won't make that mistake again. \$\endgroup\$briantist– briantist2016年02月17日 15:47:52 +00:00Commented Feb 17, 2016 at 15:47