win11系统无法安装codex,发现Microsoft Store 无法打开,用遍所有教程无效,分享自行修复过程!

系统环境:Windows 10/11,管理员 PowerShell。 现象是 Microsoft Store 可以打开或闪退,下载、安装、更新经常失败,日志里反复出现 StoreInstaller、StoreAgentSearchUpdatePackagesFailure1、80070005 之类的...
win11系统无法安装codex,发现Microsoft Store 无法打开,用遍所有教程无效,分享自行修复过程!
win11系统无法安装codex,发现Microsoft Store 无法打开,用遍所有教程无效,分享自行修复过程!

系统环境:Windows 10/11,管理员 PowerShell。
现象是 Microsoft Store 可以打开或闪退,下载、安装、更新经常失败,日志里反复出现 StoreInstaller、StoreAgentSearchUpdatePackagesFailure1、80070005 之类的错误。

80070005 基本就是拒绝访问,所以一开始我就怀疑不是商店界面本身坏了,而是后台服务或权限链路出问题。

先看系统版本:
Get-ComputerInfo | Select-Object WindowsProductName,WindowsVersion,OsBuildNumber,OsArchitecture

再看 Store 相关包还在不在:
$names = @(‘Microsoft.WindowsStore’,‘Microsoft.StorePurchaseApp’,‘Microsoft.DesktopAppInstaller’)
foreach ($n in $names) { Get-AppxPackage -AllUsers -Name $n | Select-Object Name,PackageFullName,Status,InstallLocation }

我的情况是 Microsoft.WindowsStore、Microsoft.StorePurchaseApp、Microsoft.DesktopAppInstaller 都存在,Status 也是 Ok,所以不是商店包被删了,而是更新/安装链路有问题。

继续看相关服务:
Get-Service InstallService,BITS,wuauserv,LicenseManager,ClipSVC,AppXSvc | Select-Object Name,Status,StartType | Format-Table -AutoSize
这里发现 wuauserv 也就是 Windows Update 服务是 Disabled。Microsoft Store 的安装和更新经常依赖 Windows Update、BITS、InstallService、ClipSVC、AppXSvc 这几条链路,所以 wuauserv 被禁用很可疑。

再看应用日志:
Get-EventLog -LogName Application -Newest 80 -ErrorAction SilentlyContinue | Where-Object { _.Source -match 'AppModel|Store|Windows Error Reporting|Application Error' -or _.Message -match ‘WindowsStore|Microsoft Store|WinStore|StoreInstaller’ } | Select-Object TimeGenerated,EntryType,Source,EventID,Message -First 8 | Format-List

日志里看到 StoreAgentSearchUpdatePackagesFailure1,Acquisition;StoreInstaller,错误码 80070005。这个和 wuauserv 被禁用能对上。

然后查策略:
reg query HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate /s

这里发现 AU 下面有 NoAutoUpdate=1,这个会禁用自动更新,也会影响 Store 的后台更新链路。

正常修法是删掉它:
reg delete HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU /v NoAutoUpdate /f
再尝试把 wuauserv 改回手动启动:
Set-Service -Name wuauserv -StartupType Manual
Start-Service wuauserv

如果成功,问题可能就比较简单。

但我这里失败了,提示 Access is denied。

于是继续看 wuauserv 当前配置:
reg query HKLM\SYSTEM\CurrentControlSet\Services\wuauserv /v Start
sc.exe qc wuauserv
Start=0x4,sc 里 START_TYPE 也是 4 DISABLED,说明服务确实被禁用了。

关键一步是看 wuauserv 注册表键权限:
$key = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey(‘SYSTEM\CurrentControlSet\Services\wuauserv’,[Microsoft.Win32.RegistryKeyPermissionCheck]::ReadSubTree,[System.Security.AccessControl.RegistryRights]::ReadPermissions)
$sec = $key.GetAccessControl()
$sec.GetOwner([System.Security.Principal.NTAccount]).Value
$sec.Access | Format-Table IdentityReference,RegistryRights,AccessControlType,IsInherited -AutoSize

我这里查出来非常不正常:NT AUTHORITY\SYSTEM 和 BUILTIN\Administrators 都只有 ReadKey。也就是说就算用管理员,甚至 SYSTEM,理论上也改不了这个键。这就是为什么服务启动类型死活改不回来。

下面是我用来修复 wuauserv 注册表 ACL 的脚本。
注意:需要管理员 PowerShell 执行,执行前最好先确认自己就是这个问题,不要无脑套。
$ErrorActionPreference = ‘Stop’
Add-Type -TypeDefinition @’
using System;
using System.Runtime.InteropServices;
public static class PrivilegeUtil {
[DllImport(“advapi32.dll”, SetLastError=true)] static extern bool OpenProcessToken(IntPtr ProcessHandle, UInt32 DesiredAccess, out IntPtr TokenHandle);
[DllImport(“advapi32.dll”, SetLastError=true, CharSet=CharSet.Unicode)] static extern bool LookupPrivilegeValue(string lpSystemName, string lpName, out LUID lpLuid);
[DllImport(“advapi32.dll”, SetLastError=true)] static extern bool AdjustTokenPrivileges(IntPtr TokenHandle, bool DisableAllPrivileges, ref TOKEN_PRIVILEGES NewState, UInt32 BufferLength, IntPtr PreviousState, IntPtr ReturnLength);
[DllImport(“kernel32.dll”)] static extern IntPtr GetCurrentProcess();
const UInt32 TOKEN_ADJUST_PRIVILEGES = 0x0020;
const UInt32 TOKEN_QUERY = 0x0008;
const UInt32 SE_PRIVILEGE_ENABLED = 0x00000002;
[StructLayout(LayoutKind.Sequential)] struct LUID { public UInt32 LowPart; public Int32 HighPart; }
[StructLayout(LayoutKind.Sequential)] struct TOKEN_PRIVILEGES { public UInt32 PrivilegeCount; public LUID Luid; public UInt32 Attributes; }
public static void Enable(string privilege) {
IntPtr token;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, out token)) throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
LUID luid;
if (!LookupPrivilegeValue(null, privilege, out luid)) throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
TOKEN_PRIVILEGES tp = new TOKEN_PRIVILEGES { PrivilegeCount = 1, Luid = luid, Attributes = SE_PRIVILEGE_ENABLED };
if (!AdjustTokenPrivileges(token, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero)) throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
}
}
'@
[PrivilegeUtil]::Enable(‘SeTakeOwnershipPrivilege’)
[PrivilegeUtil]::Enable(‘SeRestorePrivilege’)
[PrivilegeUtil]::Enable(‘SeBackupPrivilege’)
$path = ‘SYSTEM\CurrentControlSet\Services\wuauserv’
$adminsSid = New-Object System.Security.Principal.SecurityIdentifier(‘S-1-5-32-544’)
$systemSid = New-Object System.Security.Principal.SecurityIdentifier(‘S-1-5-18’)
$key = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey($path,[Microsoft.Win32.RegistryKeyPermissionCheck]::ReadWriteSubTree,[System.Security.AccessControl.RegistryRights]::TakeOwnership)
$secOwner = $key.GetAccessControl([System.Security.AccessControl.AccessControlSections]::Owner)
$secOwner.SetOwner($adminsSid)
$key.SetAccessControl($secOwner)
$key.Close()
$key = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey($path,[Microsoft.Win32.RegistryKeyPermissionCheck]::ReadWriteSubTree,[System.Security.AccessControl.RegistryRights]::ChangePermissions -bor [System.Security.AccessControl.RegistryRights]::ReadPermissions)
$sec = $key.GetAccessControl()
$sec.SetAccessRuleProtection($true, $false)
$inherit = [System.Security.AccessControl.InheritanceFlags]‘ContainerInherit,ObjectInherit’
$prop = [System.Security.AccessControl.PropagationFlags]::None
$allow = [System.Security.AccessControl.AccessControlType]::Allow
$ruleSpecs = @(
@(‘S-1-5-32-545’, [System.Security.AccessControl.RegistryRights]::ReadKey),
@(‘S-1-5-32-544’, [System.Security.AccessControl.RegistryRights]::FullControl),
@(‘S-1-5-18’, [System.Security.AccessControl.RegistryRights]::FullControl),
@(‘S-1-3-0’, [System.Security.AccessControl.RegistryRights]::FullControl),
@(‘S-1-15-2-1’, [System.Security.AccessControl.RegistryRights]::ReadKey),
@(‘S-1-15-3-1024-1065365936-1281604716-3511738428-1654721687-432734479-3232135806-4053264122-3456934681’, [System.Security.AccessControl.RegistryRights]::ReadKey)
)
foreach ($spec in $ruleSpecs) {
$sid = New-Object System.Security.Principal.SecurityIdentifier($spec[0])
$rule = New-Object System.Security.AccessControl.RegistryAccessRule -ArgumentList $sid, $spec[1], $inherit, $prop, $allow
$sec.AddAccessRule($rule) | Out-Null
}
$key.SetAccessControl($sec)
$key.Close()
$key = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey($path,[Microsoft.Win32.RegistryKeyPermissionCheck]::ReadWriteSubTree,[System.Security.AccessControl.RegistryRights]::TakeOwnership -bor [System.Security.AccessControl.RegistryRights]::ChangePermissions)
$sec = $key.GetAccessControl()
$sec.SetOwner($systemSid)
$key.SetAccessControl($sec)
$key.Close()
Write-Output ‘wuauserv registry ACL repaired’

权限修完以后,再把 Windows Update 服务改成手动并启动:
sc.exe config wuauserv start= demand
reg add HKLM\SYSTEM\CurrentControlSet\Services\wuauserv /v Start /t REG_DWORD /d 3 /f
Start-Service wuauserv

顺手把相关服务也拉起来:
foreach ($name in @(‘BITS’,‘wuauserv’,‘InstallService’,‘LicenseManager’,‘ClipSVC’,‘AppXSvc’,‘DoSvc’)) {
try { Start-Service -Name name -ErrorAction Stop; Write-Output "Started: {name}" } catch { Write-Output “Start skipped/failed: {name}: ($_.Exception.Message)” }
}
Get-Service InstallService,BITS,wuauserv,LicenseManager,ClipSVC,AppXSvc,DoSvc | Select-Object Name,Status,StartType | Format-Table -AutoSize

我这里最终看到 wuauserv 是 Running / Manual,BITS 是 Running / Automatic,InstallService、ClipSVC、AppXSvc 都是 Running / Manual,这一步算是把 Store 后台依赖链修回来了。

然后重新注册商店相关 AppX 包:
$names = @(‘Microsoft.WindowsStore’,‘Microsoft.StorePurchaseApp’,‘Microsoft.DesktopAppInstaller’)
foreach ($name in $names) {
$pkg = Get-AppxPackage -AllUsers -Name $name | Select-Object -First 1
if ($null -eq $pkg) { Write-Output “Package missing: $name”; continue }
$manifest = Join-Path $pkg.InstallLocation ‘AppxManifest.xml’
if (Test-Path -LiteralPath $manifest) {
Write-Output “Re-registering: $($pkg.PackageFullName)”
Add-AppxPackage -DisableDevelopmentMode -Register $manifest
} else {
Write-Output “Manifest missing: $manifest”
}
}

再清 Store 缓存:
$proc = Start-Process -FilePath “$env:SystemRoot\System32\WSReset.exe” -PassThru
$exited = $proc.WaitForExit(90000)
if (exited) { Write-Output "WSReset exited with code ($proc.ExitCode)" } else { Write-Output ‘WSReset still running after 90s; leaving it to finish/open Store UI.’ }
我这里 WSReset 返回 0,说明缓存重置正常。

最后验证 Store 源和应用启动:
winget source list
winget source update
Start-Process ‘ms-windows-store:’
Start-Sleep -Seconds 5
Get-Process | Where-Object { $_.ProcessName -match ‘WinStore|WindowsStore|ApplicationFrameHost’ } | Select-Object ProcessName,Id,StartTime | Format-Table -AutoSize
如果 winget 里能看到 msstore 源,source update 里 msstore 显示完成,并且进程里出现 WinStore.App,基本就修好了。

总结一下这次的根因:第一,wuauserv 被禁用;第二,WindowsUpdate 策略里有 NoAutoUpdate=1;第三,也是最关键的,wuauserv 注册表键 ACL 被改坏,SYSTEM 和 Administrators 都只有读取权限,导致服务无法从 Disabled 改回 Manual。修完权限、删掉 NoAutoUpdate、重新注册 Store 包、跑 WSReset 后,Microsoft Store 恢复正常。

建议最后重启一次电脑,再打开 Microsoft Store,到“库”里面点“获取更新”,确认下载和更新都恢复。

1 个帖子 - 1 位参与者

阅读完整话题

来源: LinuxDo 最新话题查看原文