Public/Remove-MSIXVirtualRegistryValue.ps1
|
function Remove-MSIXVirtualRegistryValue { <# .SYNOPSIS Removes a value from a key in an MSIX registry hive file (Registry.dat / User.dat). .DESCRIPTION Loads the hive file given by -HiveFilePath with RegLoadAppKey and deletes -ValueName from -KeyPath (relative to the hive root: 'REGISTRY\MACHINE\SOFTWARE\...' in Registry.dat, 'Software\...' in User.dat whose root is HKCU). A missing key or value is not an error - the call is idempotent. .EXAMPLE Remove-MSIXVirtualRegistryValue -HiveFilePath "$pkg\Registry.dat" -KeyPath 'REGISTRY\MACHINE\SOFTWARE\Policies\Adobe\Acrobat Reader\DC\FeatureLockDown' -ValueName 'bEnableProtectedModeAppContainer' .NOTES RegLoadAppKey works on the hive file directly (no reg load). The keys in package hives usually allow writing only from an elevated PowerShell; reading - and a removal with nothing to remove - works without. https://www.nick-it.de Andreas Nick, 2024 #> [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [string]$HiveFilePath, [Parameter(Mandatory = $true)] [string]$KeyPath, [Parameter(Mandatory = $true)] [string]$ValueName ) # Check read-only first: a missing key or value needs no write access, so the idempotent case # also works without elevation (package hives usually allow writing only when elevated). $hKey = [IntPtr]::Zero $result = [Win32Apis]::RegLoadAppKey($HiveFilePath, [ref]$hKey, 0x20019, 0, 0) # KEY_READ if ($result -ne 0) { throw "Failed to load hive '$HiveFilePath' (Win32 error $(Format-MSIXWin32Error $result))." } $present = $true try { $subKeyHandle = [IntPtr]::Zero $result = [Win32Apis]::RegOpenKeyEx($hKey, $KeyPath, 0, 0x20019, [ref]$subKeyHandle) if ($result -eq 2) { $present = $false } elseif ($result -eq 0) { $subKey = [Microsoft.Win32.RegistryKey]::FromHandle((New-Object Microsoft.Win32.SafeHandles.SafeRegistryHandle $subKeyHandle, $true)) try { $present = $subKey.GetValueNames() -contains $ValueName } finally { $subKey.Dispose() } } } finally { $null = [Win32Apis]::RegCloseKey($hKey) } if (-not $present) { Write-Verbose "Value '$KeyPath\$ValueName' not present in '$HiveFilePath' - nothing to remove." return } if (-not $PSCmdlet.ShouldProcess("$HiveFilePath : $KeyPath\$ValueName", 'Remove value')) { return } $hKey = [IntPtr]::Zero $result = [Win32Apis]::RegLoadAppKey($HiveFilePath, [ref]$hKey, 0xF003F, 0, 0) # KEY_ALL_ACCESS if ($result -ne 0) { $hint = '' if ($result -eq 5) { $hint = ' Writing to package hives usually requires an elevated PowerShell.' } throw "Failed to load hive '$HiveFilePath' (Win32 error $(Format-MSIXWin32Error $result)).$hint" } try { $subKeyHandle = [IntPtr]::Zero $result = [Win32Apis]::RegOpenKeyEx($hKey, $KeyPath, 0, 0xF003F, [ref]$subKeyHandle) if ($result -eq 2) { Write-Verbose "Key '$KeyPath' not present in '$HiveFilePath' - nothing to remove." return } if ($result -ne 0) { throw "Failed to open key '$KeyPath' in hive '$HiveFilePath' (Win32 error $(Format-MSIXWin32Error $result))." } try { $result = [Win32Apis]::RegDeleteValue($subKeyHandle, $ValueName) if ($result -eq 2) { Write-Verbose "Value '$ValueName' not present in '$KeyPath' - nothing to remove." } elseif ($result -ne 0) { throw "Failed to delete value '$ValueName' from '$KeyPath' in hive '$HiveFilePath' (Win32 error $(Format-MSIXWin32Error $result))." } else { Write-Verbose "Removed value '$KeyPath\$ValueName' from '$HiveFilePath'." } } finally { $null = [Win32Apis]::RegCloseKey($subKeyHandle) } } finally { $null = [Win32Apis]::RegCloseKey($hKey) } } |