How to get the Hash of a file with PowerShell

When downloading files from the internet, its important to be sure that the file hasn’t been modified in anyway. Certain websites will profile a ‘hash’ of the file either on the website, or sometimes in a separate text file that can also be downloaded.

Once the file has been downloaded to your workstation, you need to create your own hash of the file, then compare the two to make sure they match. If one tiny change has been made to the file, even an extra space somewhere, the hash will be completely different.

To get the hash of a file, you can use the script below. Copy the text into PowerShell_ISE and save it as Get-FileHash.ps1 (or something along those lines).

[CmdLetBinding()]
param
(
    [Parameter(Mandatory=$true)]
    [string]$FilePath,

    [Parameter()]
    [ValidateSet('MD5','SHA1','SHA256','SHA384','SHA512')]
    [string]$HashingAlgorithm = 'SHA256'
)

$FileStream = [System.IO.File]::OpenRead($FilePath)

switch ($HashingAlgorithm)
{
    'SHA512' { $Alg = [System.Security.Cryptography.SHA512]::Create() }
    'SHA384' { $Alg = [System.Security.Cryptography.SHA384]::Create() }
    'SHA256' { $Alg = [System.Security.Cryptography.SHA256]::Create() }
    'SHA1'   { $Alg = [System.Security.Cryptography.SHA1]::Create()   }
    'MD5'    { $Alg = [System.Security.Cryptography.MD5]::Create()    }
}

$ComputedHash = $Alg.ComputeHash($FileStream)

$FileStream.Dispose()

$Output = ""
foreach ($byte in $ComputedHash)
{
    $Output += $byte.ToString('x2')
}

Write-Output $Output

Parameters
-FilePath
This is a Mandatory parameter
This is the path to the file that you want to create the hash of.

-HashingAlgorithm
This is NOT mandatory, but if not specified, the default option of SHA256 will be used
This is the Algorithm used when encrypting your file to create the hash.
Valid options are MD5, SHA1, SHA256, SHA384 and SHA512.

Example Usage

Default options, just specifying a path to a file.

PS C:\> .\Get-FileHash.ps1 -FilePath 'C:\Temp\MyTestFile.txt'
4c9b6eae194fb3bed597835d70f6e94c2f692872e03410d637bcef657e7d6934

Specifying a different Hashing Algorithm.

PS C:\> .\Get-FileHash.ps1 -FilePath 'C:\Temp\MyTestFile.txt' -HashingAlgorithm 'MD5'
cdadd8ba84d98f033656acbf3219bc8d

Test if PowerShell has been run as Administrator

A quick utility function to add into your scripts to test whether or not PowerShell has been run as Administrator.

The function returns a boolean value ($True or $False).

function Test-IsAdmin 
{
    $CurrentIdentity = [Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()

    $IsAdmin = $CurrentIdentity.IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")

    Write-Output $IsAdmin
}

Example Usage

if (Test-IsAdmin)
{
    <#
        PowerShell is running as administrator.

        Crack on and do other scripty stuff. :)
    #>
}
else
{
    <#
        PowerShell is NOT running as Administrator.

        Throw some useful error or warning, advising the users to
        run PowerShell again, but run as administrator.
    #>
}

Monty Hall Problem – Test Script

A quick script knocked up to test the theories in the Monty Hall Problem. Defaults to run 1000 tests, but this can be adjusted using the $NumberOfTests parameter.

A second parameter controls the choice of whether to switch doors, or stick with the same one. This is the $Choice parameter and can accept the following options. The default option is LetFateDecide.

  • StickWithDoor
  • SwitchDoor
  • LetFateDecide

Examples

Runs 1000 instances of the Monty Hall Problem

./Test-MontyHallProblem.ps1

Runs 1000 instances of the Monty Hall Problem where the door gets switched every time

./Test-MontyHallProblem.ps1 -Choice 'SwitchDoor'

Runs 5000 instances of the Monty Hall Problem, sticking with the same door everytime.

./Test-MontyHallProblem.ps1 -NumberOfTests 5000 -Choice 'StickWithDoor'


Full ScriptTest-MontyHallProblem.ps1

[CmdLetBinding()]
param
(
    [Parameter()]
    [int]$NumberOfTests = 1000,

    [Parameter()]
    [ValidateSet('StickWithDoor','SwitchDoor','LetFateDecide')]
    [string]$Choice = 'LetFateDecide'
)

$gameShowClass = @"
public class GameShow
{
    public GameShow()
    {
        this.Door1 = "Goat";
        this.Door2 = "Goat";
        this.Door3 = "Goat";
    }

    public string Door1 { get; set; }
    public string Door2 { get; set; }
    public string Door3 { get; set; }
}
"@
Add-Type -TypeDefinition $gameShowClass

$resultsClass = @"
public class GameShowResults
{
    public int TestNumber { get; set; }
    public string FirstChoice { get; set; }
    public string DoorRemoved { get; set; }
    public string FinalChoice { get; set; }
    public string Decision { get; set; }
    public string Prize { get; set; }
}
"@
Add-Type -TypeDefinition $resultsClass

function New-GameShow
{
    $gameShow = New-Object -TypeName 'GameShow'

    $prizeDoor = Get-Random -Minimum 1 -Maximum 4

    switch ($prizeDoor)
    {
        1 { $gameShow.Door1 = "Car" }
        2 { $gameShow.Door2 = "Car" }
        3 { $gameShow.Door3 = "Car" }
    }

    Write-Output $gameShow
}

function Test-MontyHallProblem
{
    param
    (
        [int]$TestNumber,
        [string]$Choice
    )

    $GameShow = New-GameShow
    $Results = New-Object -TypeName GameShowResults

    $Results.TestNumber = $TestNumber

    $PrizeDoor = 1..3 | ForEach-Object {
        $Property = "Door$($_)"
        if ($GameShow.$Property -eq 'Car') { $_ }
    }

    $FirstChoice = Get-Random -Minimum 1 -Maximum 4
    $Results.FirstChoice = "Door$($FirstChoice)"

    $RemainingDoors = 1..3 | Where { $_ -ne $FirstChoice }

    $DoorRemoved = Get-Random -InputObject ($RemainingDoors | Where { $_ -ne $PrizeDoor })
    $Results.DoorRemoved = "Door$($DoorRemoved)"

    switch ($Choice)
    {
        'LetFateDecide'
        {
            $FinalChoice = Get-Random -InputObject (1..3 | Where { $_ -ne $DoorRemoved })
        }

        'StickWithDoor'
        {
            $FinalChoice = $FirstChoice
        }

        'SwitchDoor'
        {
            $FinalChoice = 1..3 | Where { $_ -ne $DoorRemoved -and $_ -ne $FirstChoice }
        }
    }

    $Results.FinalChoice = "Door$($FinalChoice)"

    if ($FirstChoice -eq $FinalChoice)
    {
        $Results.Decision = 'Stick'
    }
    else
    {
        $Results.Decision = 'Switch'
    }

    $FinalDoor = "Door$($FinalChoice)"

    $Results.Prize = $GameShow.$FinalDoor

    Write-Output $Results
}

Clear-Host

$ResultsArray = @()

$Counter = 1

1..$NumberOfTests | ForEach-Object {
    
    Write-Progress -Activity 'Testing the Monty Hall Problem' 
                   -Status "Running Test Number $($_)" 
                   -PercentComplete (($Counter / $NumberOfTests) * 100)

    $ResultsArray += Test-MontyHallProblem -TestNumber $Counter -Choice $Choice

    $Counter++
}

$NumberOfSticks = ($ResultsArray | Where { $_.Decision -eq 'Stick' }).Count
$NumberOfStickWins = ($ResultsArray | Where { $_.Decision -eq 'Stick' -and $_.Prize -eq 'Car' }).Count
$NumberOfSwitches = ($ResultsArray | Where { $_.Decision -eq 'Switch' }).Count
$NumberOfSwitchWins = ($ResultsArray | Where { $_.Decision -eq 'Switch' -and $_.Prize -eq 'Car' }).Count

$global:TestResults = $null
$global:TestResults = $ResultsArray

Write-Host
Write-Host "Monty Hall Problem Tester" -ForegroundColor Yellow
Write-Host "----- ---- ------- ------" -ForegroundColor White
Write-Host
Write-Host "Number of Tests Run: " -ForegroundColor Yellow -NoNewline
Write-Host $NumberOfTests -ForegroundColor White

if ($Choice -match "(LetFateDecide|StickWithDoor)")
{
    Write-Host
    Write-Host "Number of Times Staying with the Same Door: " -ForegroundColor Yellow -NoNewline
    Write-Host ("$($NumberOfSticks) ({0:N2} %)" -f $(($NumberOfSticks / $NumberOfTests) * 100)) -ForegroundColor White
    Write-Host "Number of Times Staying with the Same Door Won the Car: " -ForegroundColor Yellow -NoNewline
    if ($NumberOfStickWins)
    {
        Write-Host ("$($NumberOfStickWins) ({0:N2} %)" -f (($NumberOfStickWins / $NumberOfSticks) * 100)) -ForegroundColor White
    }
    else
    {
        Write-Host "$($NumberOfStickWins) (0.00 %)" -ForegroundColor White
    }
}

if ($Choice -match "(LetFateDecide|SwitchDoor)")
{
    Write-Host
    Write-Host "Number of Times Switching Doors: " -ForegroundColor Yellow -NoNewline
    Write-Host ("$($NumberOfSwitches) ({0:N2} %)" -f $(($NumberOfSwitches / $NumberOfTests) * 100)) -ForegroundColor White
    Write-Host "Number of Times Switching Doors Won the Car: " -ForegroundColor Yellow -NoNewline
    if ($NumberOfSwitchWins)
    {
        Write-Host ("$($NumberOfSwitchWins) ({0:N2} %)" -f (($NumberOfSwitchWins / $NumberOfSwitches) * 100)) -ForegroundColor White
    }
    else
    {
        Write-Host "$($NumberOfSwitchWins) (0.00 %)" -ForegroundColor White
    }
}
Write-Host
Write-Host
Write-Host "To view all Test Results run the following command:" -ForegroundColor Yellow
Write-Host
Write-Host "    `$TestResults | Out-GridView" -ForegroundColor White
Write-Host
Write-Host