Calculating a Hash for Entire Optical Media Disc using PowerShell

3.1k Views Asked by At

I'm trying to find a way to create a checksum/hash of CD or DVD using PowerShell. I know Get-Filehash works very well on files, but I can't figure out how to do it for optical media. I was thinking I might be able to use Get-Content to get the bitstream and pipe it to Get-Filehash, but running Get-Content -Path D:\ (where D: is the disc) return an "Access to the path 'D:\'is denied. Get-Volume only seems to return an object with properties, not the bitstream.

I already have an ISO image file for the disc. Am trying to get the checksum on the whole original disc to compare to the ISO to make sure it was ripped correctly.

Any suggestions or pointers?

3

There are 3 best solutions below

2
On

I came up with the following method:

function Hash-Media([string]$drive, [string]$algorithm){
     <#
     .SYNOPSIS
         Hashes the entire drive letter using the provided algorithm
     .PARAMETER  $drive
         The drive letter, eg 'd:'
     .PARAMETER  $algorithm
         Any algorithm acceptable by Get-FileHash, eg SHA1, SHA256, etc
     .EXAMPLE
         PS> Hash-Media e: SHA256
         43E2B7D5142592222FFA39F7AB15706911B8D14AAF0186D2A44CA07581F5FEBA
     #>

     
     
     $raw_stream = [System.IO.File]::Open('\\.\' + $drive, 'open', 'Read', 'Read')
     $hash = Get-FileHash -InputStream $raw_stream -Algorithm $algorithm
     return $hash.Hash
}

This returns the same value as checking the ISO file directly before it was burned.

1
On

If I understand the question properly, you would like to get a hashvalue for everything on the CD (get the checksum on the whole original disc).

For this you can use the helper function below:

function Get-FolderHash {
    [CmdletBinding()]
    param(
        [Parameter(ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Position = 0)]
        [string]$Path,

        [ValidateSet('SHA1','SHA256','SHA384','SHA512','MD5')]
        [string]$Algorithm = 'MD5'
    )
    # create a new temporary file
    $temp=[System.IO.Path]::GetTempFileName()

    Get-ChildItem -Path $Path -File -Recurse | 
        Get-FileHash -Algorithm $Algorithm | 
        Select-Object -ExpandProperty Hash | 
        Out-File -FilePath $temp -NoNewline -Encoding ascii

    $hash = Get-FileHash -Path $temp -Algorithm $Algorithm
    $hash.Path = $Path

    Remove-Item -Path $temp

    return $hash
}

Get-FolderHash D:\

Hope that helps

4
On

From your example, Get-Content -Path D:\ fails because you're not pointing to a file. From the Get-Content documentation:

-Path

Specifies the path to an item where Get-Content gets the content. Wildcard characters are permitted. The paths must be paths to items, not to containers. For example, you must specify a path to one or more files, not a path to a directory.

I.e., the optical drive isn't the issue for that cmdlet; you'll see the same error if you tried that on your C:/ drive.

From the question I'm not sure if your optical drive contains the extracted ISO or just the ISO, but something like this should get you started:

Get-ChildItem -Path d:\ -Recurse -File | foreach { 
    Get-FileHash $_.FullName; 
}