4
\$\begingroup\$

I created a function to get the hash value of a file. Normally the output is 3 lines. My function does 3 things:

  1. extracts the hash value
  2. removes the spaces in between the hash value
  3. 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.

\$\endgroup\$
4
\$\begingroup\$

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.)
\$\endgroup\$
  • \$\begingroup\$ Using powershell 4 and Get-FileHash returns the checksum without spaces. \$\endgroup\$ – jes516 Dec 29 '15 at 5:19
3
\$\begingroup\$

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.

\$\endgroup\$
  • \$\begingroup\$ Hey ... I am guessing this was a typo or muscle memory but echo -> Write-Output \$\endgroup\$ – Matt Feb 16 '16 at 1:19
  • \$\begingroup\$ @Matt wow nope, it was plain old ignorance! Thanks for catching this; won't make that mistake again. \$\endgroup\$ – briantist Feb 17 '16 at 15:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.