Zero-XAtlasHelp

Script library ›

Reset-ComponentStorePermission

Reset permissions on the component store. Saves, then resets, the permissions on WinSxS and SoftwareDistribution, and sets TrustedInstaller as the owner of WinSxS.

needs adminrestart advisedsupports -WhatIfrisk: mediumversion 1written by an assistant from cited pages
untested here · 0 fixed, 0 not

What it does

Use this only for update errors that mean access denied (0x80070005). It is not a general repair.

It runs the commands from Microsoft's article:

icacls "%windir%\WinSxS" /reset /t /c /q
icacls "%windir%\SoftwareDistribution" /reset /t /c /q
icacls "%windir%\WinSxS" /setowner "NT SERVICE\TrustedInstaller" /t /c /q

This changes permissions on system folders, so the script saves the current permissions first, to %ProgramData%\Zero-X\backup. To undo it, run the restore command the script prints. Restart afterwards and try the update again. It can take several minutes.

Examples

.\Reset-ComponentStorePermission.ps1 -WhatIf

Shows what would happen and changes nothing.

.\Reset-ComponentStorePermission.ps1

Saves the permissions, then resets them.

Microsoft's guidance

The script

Click the script to select all of it, then copy. Fingerprint of this text (SHA-256): 2677c889ca3cf97bec44ccc0a78f794a8c84906d4819ff7d93a806df5332af49. Updated 2026-10-21.

# Copyright (c) 2026 Owen Perry. All rights reserved.
#Requires -Version 5.1
#Requires -RunAsAdministrator

<#
.SYNOPSIS
Resets the permissions on the Windows component store and the update download folder.

.DESCRIPTION
Use this only for update errors that mean access denied (0x80070005). It is not a general repair.

It runs the commands from Microsoft's article:
  icacls "%windir%\WinSxS" /reset /t /c /q
  icacls "%windir%\SoftwareDistribution" /reset /t /c /q
  icacls "%windir%\WinSxS" /setowner "NT SERVICE\TrustedInstaller" /t /c /q

This changes permissions on system folders, so the script saves the current permissions first, to %ProgramData%\Zero-X\backup.
To undo it, run the restore command the script prints. Restart afterwards and try the update again. It can take several minutes.

.EXAMPLE
.\Reset-ComponentStorePermission.ps1 -WhatIf
Shows what would happen and changes nothing.

.EXAMPLE
.\Reset-ComponentStorePermission.ps1
Saves the permissions, then resets them.

.LINK
https://learn.microsoft.com/en-us/troubleshoot/windows-client/installing-updates-features-roles/troubleshoot-windows-update-error-0x80070005
#>

[CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'High')]
param()

$ErrorActionPreference = 'Stop'

$baseFolder = Join-Path $env:ProgramData 'Zero-X'
$logFolder = Join-Path $baseFolder 'logs'
$backupFolder = Join-Path $baseFolder 'backup'
New-Item -ItemType Directory -Path $logFolder, $backupFolder -Force -WhatIf:$false | Out-Null
$stamp = '{0:yyyyMMdd-HHmmss}' -f (Get-Date)

# Keep a log. -WhatIf:$false makes sure it is still written during a -WhatIf run.
$logging = $false
try {
    Start-Transcript -Path (Join-Path $logFolder "Reset-ComponentStorePermission-$stamp.log") -WhatIf:$false | Out-Null
    $logging = $true
} catch {
    Write-Warning "No log file: $($_.Exception.Message)"
}

$icacls = Join-Path $env:windir 'System32\icacls.exe'
$componentStore = Join-Path $env:windir 'WinSxS'
$dataStore = Join-Path $env:windir 'SoftwareDistribution'
$failed = $false

try {
    # Save the current permissions so they can be restored.
    foreach ($folder in $componentStore, $dataStore) {
        $saveFile = Join-Path $backupFolder ('{0}-permissions-{1}.txt' -f (Split-Path $folder -Leaf), $stamp)
        if ($PSCmdlet.ShouldProcess($folder, "Save the current permissions to $saveFile")) {
            & $icacls $folder /save $saveFile /t /c /q
            Write-Host "To undo: icacls `"$(Split-Path $folder -Parent)`" /restore `"$saveFile`""
        }
    }

    # Reset both folders to the permissions they inherit by default.
    foreach ($folder in $componentStore, $dataStore) {
        if ($PSCmdlet.ShouldProcess($folder, 'Reset permissions')) {
            & $icacls $folder /reset /t /c /q
            if ($LASTEXITCODE -ne 0) { $failed = $true; Write-Warning "icacls reset on $folder exited with $LASTEXITCODE" }
        }
    }

    # TrustedInstaller should own the component store.
    if ($PSCmdlet.ShouldProcess($componentStore, 'Set the owner to NT SERVICE\TrustedInstaller')) {
        & $icacls $componentStore /setowner 'NT SERVICE\TrustedInstaller' /t /c /q
        if ($LASTEXITCODE -ne 0) { $failed = $true; Write-Warning "icacls setowner exited with $LASTEXITCODE" }
    }
} finally {
    if ($logging) { Stop-Transcript | Out-Null }
}

if ($failed) { exit 1 }
if (-not $WhatIfPreference) {
    Write-Host 'Done. Restart the computer, then try the update again.'
}
Tested this in a lab? Record the result
(Enterprise subscription only)