无法通过 PowerShell 卸载通用应用程序

无法通过 PowerShell 卸载通用应用程序

当我遇到障碍时,我正在从新的 Windows 10 安装中卸载所有通用应用程序。

这不是我第一次这样做,而且每次都进展顺利。然而,这一次,每当我在 PowerShell 中写入

Get-AppxPackage -allusers | Remove-AppxPackage

或更具体的内容时,

Get-AppxPackage -allusers *windowscalculator* | Remove-AppxPackage

我都会收到以下消息:

Remove-AppxPackage:部署失败,HRESULT:0x80073CFA,删除失败。请联系您的软件供应商。(异常来自 HRESULT:0x80073CFA)错误 0x80070032:AppX 部署从 C:\Program Files\WindowsApps\Microsoft.WindowsCalculator_10.1605.1582.0_x64__8wekyb3d8bbwe 软件包中删除操作失败。

此应用是 Windows 的一部分,无法针对每个用户进行卸载。管理员可以尝试使用“打开或关闭 Windows 功能”从计算机中删除该应用。但是,可能无法卸载该应用。

注:如需更多信息,请在事件日志中查找 [ActivityId] 75c5fc31-fb20-0001-77fd-c57520fbd101,或使用命令行 Get-AppxLog -ActivityID 75c5fc31-fb20-0001-77fd-c57520fbd101

位于行:1 字符:49

+ Get-appxpackage -allusers *windowscalculator* | Remove-AppxPackage + ~~~~~~~~~~~~~~~~~~ + CategoryInfo : WriteError: (Microsoft.Windo...__8wekyb3d8bbwe:String) [Remove-AppxPackage], IOException + FullyQualifiedErrorId : DeploymentError,Microsoft.Windows.Appx.PackageManager.Commands.RemoveAppxPackageCommand


我尝试卸载每个应用程序时都会收到此消息,包括那些我知道可以完全卸载的应用程序,例如计算器或图像查看器,这种情况以前从未发生过。Powershell
运行速度加快,其他一切正常。

除了重新安装 Windows 之外,我还能做些什么吗?

答案1

从 Windows 10 周年更新开始,MicrosoftIsInbox在 SQLite 数据库中C:\ProgramData\Microsoft\Windows\AppRepository\StateRepository-Machine.srd为收件箱应用程序添加了一个新条目。尝试删除标记为的应用程序IsInbox失败0x80073CFA

但有一个不太好的解决办法,那就是2017 年 4 月发现

您需要下载并安装工具进程黑客SQLite 数据库浏览器

  • 以管理员身份运行 ProcessHacker 2,选择 a C:\Windows\System32\svchost.exe,右键单击并选择Misc->Run as this user

在此处输入图片描述

现在选择这里C:\Program Files\DB Browser for SQLite\DB Browser for SQLite.exe并启动它。在 SQLite 浏览器中,单击Open database

在此处输入图片描述

并打开文件C:\ProgramData\Microsoft\Windows\AppRepository\StateRepository-Machine.srd(将打开对话框中的文件类型更改为所有文件即可查看它)。

现在,单击Browse Data选项卡,并将表格更改为Package

在此处输入图片描述

现在选择您要删除的应用程序并将列的 1 更改为IsInbox,然后0保存更改。

在此处输入图片描述

对要删除的所有应用程序重复此操作,现在 PowerShell 命令应该可以正常工作了。

但作者写道,如果删除收件箱应用程序,微软将阻止升级到较新的 Windows 版本。所以请记住这一点。

答案2

帖子 彻底删除系统应用程序(绕过错误 0x80073CFA) 包含以下 PowerShell 脚本:

function Enable-Privilege {  
  param($Privilege)
  $Definition = @'
using System;  
using System.Runtime.InteropServices;  
public class AdjPriv {  
  [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
  internal static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall,
    ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr rele);
  [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
  internal static extern bool OpenProcessToken(IntPtr h, int acc, ref IntPtr phtok);
  [DllImport("advapi32.dll", SetLastError = true)]
  internal static extern bool LookupPrivilegeValue(string host, string name,
    ref long pluid);
  [StructLayout(LayoutKind.Sequential, Pack = 1)]
  internal struct TokPriv1Luid {
    public int Count;
    public long Luid;
    public int Attr;
  }
  internal const int SE_PRIVILEGE_ENABLED = 0x00000002;
  internal const int TOKEN_QUERY = 0x00000008;
  internal const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;
  public static bool EnablePrivilege(long processHandle, string privilege) {
    bool retVal;
    TokPriv1Luid tp;
    IntPtr hproc = new IntPtr(processHandle);
    IntPtr htok = IntPtr.Zero;
    retVal = OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
      ref htok);
    tp.Count = 1;
    tp.Luid = 0;
    tp.Attr = SE_PRIVILEGE_ENABLED;
    retVal = LookupPrivilegeValue(null, privilege, ref tp.Luid);
    retVal = AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero,
      IntPtr.Zero);
    return retVal;
  }
}
'@  
  $ProcessHandle = (Get-Process -id $pid).Handle
  $type = Add-Type $definition -PassThru
  $type[0]::EnablePrivilege($processHandle, $Privilege)
}

function Take-Over($path) {  
  $owner = [Security.Principal.NTAccount]'Administrators'

  $key = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey($path, 'ReadWriteSubTree', 'TakeOwnership')
  $acl = $key.GetAccessControl()
  $acl.SetOwner($owner)
  $key.SetAccessControl($acl)

  $acl = $key.getaccesscontrol()
  $rule = New-Object System.Security.AccessControl.RegistryAccessRule "Administrators", "FullControl", "ContainerInherit", "None", "Allow"
  $acl.SetAccessRule($rule)
  $key.SetAccessControl($acl)
}

do {} until (Enable-Privilege SeTakeOwnershipPrivilege)

function Remove-Package($name) {  
  $key = "SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\Packages\$name"
  Take-Over $key
  Remove-Item -Path HKLM:"$key\Owners" -Force -Recurse
  & C:\Windows\System32\PkgMgr.exe /up:$name /norestart /quiet
}

#Remove Feedback
$packageBase = "Microsoft-WindowsFeedback"
$packageNames = (dir ("HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\Packages\" + $packageBase + "*")).name

forEach ($package in $packageNames)
{   
    Remove-Package $package.substring($package.indexOf($packageBase))
}

关于使用该脚本,作者评论道:

您可以将 $packageBase 更改为不同的包名称。

我自己还没有尝试过这个脚本。

编辑:该脚本可能不再起作用,或可能需要调整。

答案3

Windows 周年更新进行了许多更改,阻止您关闭某些功能,例如 Cortana 或通过官方方式删除应用程序。某些应用程序(例如 xbox 应用程序)微软认为它是系统的重要应用程序,因此阻止官方方式将其删除。

如果您进入开始菜单,您可以右键单击它并单击卸载,相反,您可以右键单击开始按钮,转到设置,然后转到应用程序和功能,然后从那里卸载它。

现在,如果您坚持要删除这些应用程序。它们被保存在C:\windows\SystemApps因此您可以找到保存它的文件夹并删除该文件夹,或者更安全的选择是重命名它并在_名称末尾添加一个字符(例如下划线)。

补充一下,如果你删除了一个文件夹或者在 systemapps 文件夹内重命名它,这在技术上并不是卸载它,而只是强制删除它,如果你删除了该文件夹,可能会留下其他仍然安装的东西,如注册表项和它使用但不在 systemapps 文件夹中的其他地方的其他文件,或者如果你重命名该文件夹,则强制它不运行。

正如 Ryakna 在下面的评论中所说,使用其中任何两个选项都可能导致以后出现问题,但根据我的经验,我还没有遇到任何问题,包括更新。但仍然建议通过官方方式卸载,如果您熟悉 powershell,可以使用它,或者通过程序和功能选项或菜单选项。SystemApps不应重命名或删除该文件夹,因为如果您这样做,您很可能会遇到问题,而不是重命名或删除 systemapps 文件夹内的文件夹。

答案4

您需要-allUsers同时指定Get-AppXPackage Remove-AppXPackage。这就是为什么错误说您无法从用户帐户卸载 AllUsers 包;您获得了 AllUsers 的参考,但随后尝试为单个用户卸载它。

Get-AppXPackage -allUsers *windowscalculator* | Remove-AppXPackage -allUsers

相关内容