I have found myself needing fully featured functions for mounting and dismounting registry hives and accounting for all the variables that come with that. This is usually when needing to get information from mounting Windows Images. This way, you can get details like the Image Release ID (1709, 1803, 1809, etc) and more from your imagination
Function Mount-RegistryHive
{
[CmdletBinding(SupportsShouldProcess=$True)]
Param
(
[Parameter(Mandatory=$True, ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True)]
[ValidateNotNullOrEmpty()]
[ValidateScript({(Test-Path -Path $_)})]
[String]$Path,
[Parameter(Mandatory=$False, ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True)]
[ValidateNotNullOrEmpty()]
[ValidateScript({($_ -ilike "HKU\*") -or ($_ -ilike "HKLM\*")})]
[String]$MountPath,
[Parameter(Mandatory=$False)]
[Switch]$CopyHive
)
Begin
{
[String]$CmdletName = $MyInvocation.MyCommand.Name
Write-FunctionHeaderOrFooter -CmdletName "$($CmdletName)" -CmdletBoundParameters $PSBoundParameters -Header
Write-Log -Message "Function `'$($CmdletName)`' is beginning. Please Wait..." -Severity 2 -LogType CMTrace -Source "$($CmdletName)" -ContinueOnError:$True
}
Process
{
Try
{
[System.IO.FileInfo]$PathProperties = $Path
$RandomGUID = "$([System.GUID]::NewGuid().ToString().ToUpper())"
If ($CopyHive.IsPresent -eq $True)
{
$HiveDestination = "$($EnvTemp.TrimEnd('\'))\$($RandomGUID)"
If (!(Test-Path -Path $HiveDestination)) {New-Folder -Path $HiveDestination -Verbose -ContinueOnError:$False}
Copy-File -Path "$($Path)" -Destination "$($HiveDestination)"
$Path = "$($HiveDestination)\$($PathProperties.Name)"
[System.IO.FileInfo]$PathProperties = $Path
}
If ((!($PSBoundParameters.ContainsKey('MountPath'))) -and ([String]::IsNullOrEmpty($MountPath)))
{
$MountPath = "HKLM\$($RandomGUID)"
}
$LogMessage = "Mount Path: `'$($MountPath)`'"
Write-Log -Message $LogMessage -Severity 1 -LogType CMTrace -Source "$($CmdletName)" -ContinueOnError:$True
$MountPathConverted = Convert-RegistryPath -Key "$($MountPath)"
$LogMessage = "Mount Path Converted: `'$($MountPathConverted)`'"
Write-Log -Message $LogMessage -Severity 1 -LogType CMTrace -Source "$($CmdletName)" -ContinueOnError:$True
$LogMessage = "Attempting to mount registry hive `'$($PathProperties.FullName)`' into the following mount path `'$($MountPath)`'. Please Wait..."
Write-Log -Message $LogMessage -Severity 1 -LogType CMTrace -Source "$($CmdletName)" -ContinueOnError:$True
$MountRegistryHive = Execute-Process -Path "reg.exe" -Parameters "Load `"$($MountPath)`" `"$($PathProperties.FullName)`"" -CreateNoWindow -PassThru
If ($MountRegistryHive.ExitCode -iin @('0'))
{
$LogMessage = "Mounting of registry hive `'$($PathProperties.FullName)`' into the following mount path `'$($MountPath)`' was successful"
Write-Log -Message $LogMessage -Severity 1 -LogType CMTrace -Source "$($CmdletName)" -ContinueOnError:$True
}
Else
{
$ErrorMessage = "Failed to mount registry hive `'$($PathProperties.FullName)`' into the following mount path `'$($MountPath)`'"
Write-Log -Message $ErrorMessage -Severity 3 -LogType CMTrace -Source "$($CmdletName)" -ContinueOnError:$True
Throw "$($ErrorMessage)"
}
$ResultantProperties = New-Object -TypeName 'PSObject'
$ResultantProperties | Add-Member -Name "ParentPath" -Value "$($PathProperties.Directory)" -MemberType NoteProperty
$ResultantProperties | Add-Member -Name "Path" -Value "$($PathProperties.FullName)" -MemberType NoteProperty
$ResultantProperties | Add-Member -Name "FileName" -Value "$($PathProperties.Name)" -MemberType NoteProperty
$ResultantProperties | Add-Member -Name "MountPath" -Value "$($MountPath)" -MemberType NoteProperty
$ResultantProperties | Add-Member -Name "MountPathConverted" -Value "$($MountPathConverted)" -MemberType NoteProperty
$ResultantProperties | Add-Member -Name "GUID" -Value "$($RandomGUID)" -MemberType NoteProperty
$ResultantProperties | Add-Member -Name "ExitCode" -Value "$($MountRegistryHive.ExitCode)" -MemberType NoteProperty
$ResultantProperties | Add-Member -Name "StdOut" -Value "$($MountRegistryHive.StdOut)" -MemberType NoteProperty
$ResultantProperties | Add-Member -Name "StdErr" -Value "$($MountRegistryHive.StdErr)" -MemberType NoteProperty
}
Catch
{
$ErrorMessage = "$($_.Exception.Message)"
Write-Log -Message $ErrorMessage -Severity 3 -LogType CMTrace -Source "$($CmdletName)" -ContinueOnError:$True
}
Write-Output -InputObject $ResultantProperties
}
End
{
Write-Log -Message "Function `'$($CmdletName)`' is completed." -Severity 2 -LogType CMTrace -Source "$($CmdletName)" -ContinueOnError:$True
Write-FunctionHeaderOrFooter -CmdletName "$($CmdletName)" -Footer
}
}
Function Dismount-RegistryHive
{
[CmdletBinding(SupportsShouldProcess=$True)]
Param
(
[Parameter(Mandatory=$True, ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True)]
[ValidateNotNullOrEmpty()]
[ValidateScript({($_ -ilike "HKU\*") -or ($_ -ilike "HKLM\*")})]
[String]$MountPath,
[Parameter(Mandatory=$False)]
[Switch]$RemoveHive,
[Parameter(Mandatory=$True, ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True)]
[ValidateNotNullOrEmpty()]
[ValidateScript({(Test-Path -Path $_)})]
[String]$Path,
[Parameter(Mandatory=$False)]
[Switch]$Recurse
)
Begin
{
[String]$CmdletName = $MyInvocation.MyCommand.Name
Write-FunctionHeaderOrFooter -CmdletName "$($CmdletName)" -CmdletBoundParameters $PSBoundParameters -Header
Write-Log -Message "Function `'$($CmdletName)`' is beginning. Please Wait..." -Severity 2 -LogType CMTrace -Source "$($CmdletName)" -ContinueOnError:$True
}
Process
{
Try
{
$LogMessage = "Mount Path: `'$($MountPath)`'"
Write-Log -Message $LogMessage -Severity 1 -LogType CMTrace -Source "$($CmdletName)" -ContinueOnError:$True
$MountPathConverted = Convert-RegistryPath -Key "$($MountPath)"
$LogMessage = "Mount Path Converted: `'$($MountPathConverted)`'"
Write-Log -Message $LogMessage -Severity 1 -LogType CMTrace -Source "$($CmdletName)" -ContinueOnError:$True
$LogMessage = "Attempting to dismount the associated registry hive from the following mount path `'$($MountPath)`'. Please Wait..."
Write-Log -Message $LogMessage -Severity 1 -LogType CMTrace -Source "$($CmdletName)" -ContinueOnError:$True
[Void][GC]::Collect()
[Void][GC]::WaitForPendingFinalizers()
$DismountRegistryHive = Execute-Process -Path "reg.exe" -Parameters "Unload `"$($MountPath)`"" -CreateNoWindow -PassThru
If ($DismountRegistryHive.ExitCode -iin @('0'))
{
$LogMessage = "Dismounting of the associated registry hive from the following mount path `'$($MountPath)`' was successful"
Write-Log -Message $LogMessage -Severity 1 -LogType CMTrace -Source "$($CmdletName)" -ContinueOnError:$True
}
Else
{
$ErrorMessage = "Failed to dismount registry hive: $($DismountRegistryHive.StdErr)"
Write-Log -Message $ErrorMessage -Severity 3 -LogType CMTrace -Source "$($CmdletName)" -ContinueOnError:$True
Throw ""
}
If ($RemoveHive.IsPresent -eq $True)
{
If ((!([String]::IsNullOrEmpty($Path))))
{
$PathProperties = Get-Item -Path $Path -Force
If (($Recurse.IsPresent -eq $True) -and ($PathProperties.GetType().Name -ieq 'DirectoryInfo'))
{
Remove-Folder -Path "$($PathProperties.FullName)" -Verbose -ContinueOnError:$False
}
ElseIf (($PathProperties.GetType().Name -ieq 'FileInfo'))
{
Remove-File -Path "$($PathProperties.FullName)" -Verbose -ContinueOnError:$False
}
}
}
$ResultantProperties = New-Object -TypeName 'PSObject'
$ResultantProperties | Add-Member -Name "MountPath" -Value "$($MountPath)" -MemberType NoteProperty
$ResultantProperties | Add-Member -Name "MountPathConverted" -Value "$($MountPathConverted)" -MemberType NoteProperty
$ResultantProperties | Add-Member -Name "ExitCode" -Value "$($DismountRegistryHive.ExitCode)" -MemberType NoteProperty
$ResultantProperties | Add-Member -Name "StdOut" -Value "$($DismountRegistryHive.StdOut)" -MemberType NoteProperty
$ResultantProperties | Add-Member -Name "StdErr" -Value "$($DismountRegistryHive.StdErr)" -MemberType NoteProperty
}
Catch
{
$ErrorMessage = "$($_.Exception.Message)"
Write-Log -Message $ErrorMessage -Severity 3 -LogType CMTrace -Source "$($CmdletName)" -ContinueOnError:$True
}
Write-Output -InputObject $ResultantProperties
}
End
{
Write-Log -Message "Function `'$($CmdletName)`' is completed." -Severity 2 -LogType CMTrace -Source "$($CmdletName)" -ContinueOnError:$True
Write-FunctionHeaderOrFooter -CmdletName "$($CmdletName)" -Footer
}
}
$HivePath = “C:\Users\Default\NTUser.dat”
MountPathProperties = Mount-RegistryHive -Path "($HivePath)" -CopyHive
$RegistryKeyPath = “Microsoft\Windows NT\CurrentVersion”
$RegistryKeyValue = “ReleaseID”
[String]ReleaseID = Get-RegistryKey -Key "($MountPathProperties.MountPathConverted)$(RegistryKeyPath)" -Value "($RegistryKeyValue)" -DoNotExpandEnvironmentNames
Test = Dismount-RegistryHive -MountPath "(MountPathProperties.MountPath)" -RemoveHive -Path "($MountPathProperties.ParentPath)" -Recurse