You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

Windows 10启动脚本移除预设App:数组对比问题求助

问题分析与解决方案:Windows 10预装应用移除脚本的数组对比问题

咱们先聊聊你最初脚本里卡壳的地方,然后给出修正方案,顺便说说你后来改的脚本为啥能跑通。

最初脚本的核心问题

你最初的思路是对的:先获取所有预装应用的DisplayName和PackageName,再过滤出在$RemovalList里的项,但两个关键步骤出了问题:

  1. 对象构建错误:你用$Apps = "" | select DisplayName,PackageName然后直接把数组赋值给它的属性,这会让$Apps变成单个对象,而不是包含多个应用条目的数组。后续的$array += $Apps完全没起到构建集合的作用。
  2. 数组对比逻辑错误:你把$RemovalList赋值给$RemovalList1.DisplayName,然后用Where {$_.DisplayName -eq $RemovalList1.DisplayName}来过滤。这里-eq是用来对比单个值的,而你右边是一个数组,只会返回和数组完全匹配的单个条目(基本不可能),正确的做法应该用-contains或者-in来判断当前DisplayName是否在移除列表里。

修正后的最初思路脚本

下面是调整后的脚本,完美实现你最初的需求:用DisplayName对比过滤,再执行移除:

$RemovalList = @(
    'Microsoft.Messaging'
    'Microsoft.MicrosoftOfficeHub'
    'Microsoft.MicrosoftSolitaireCollection'
    'Microsoft.Office.OneNote'
    'Microsoft.SkypeApp'
    'microsoft.windowscommunicationsapps'
    'Microsoft.XboxApp'
    'Microsoft.XboxGameOverlay'
    'Microsoft.XboxIdentityProvider'
    'Microsoft.XboxSpeechToTextOverlay'
    'Microsoft.ZuneMusic'
    'Microsoft.ZuneVideo'
)

# 获取DISM返回的预装应用原始数据
$dismRaw = (DISM /Online /Get-ProvisionedAppxPackages)

# 提取PackageName和DisplayName列表
$PNList = ($dismRaw | Select-string PackageName) -replace "PackageName : ", ""
$DNList = ($dismRaw | Select-string DisplayName) -replace "DisplayName : ", ""

# 构建正确的应用对象数组:每个条目对应一个DisplayName和PackageName
$Apps = for ($i=0; $i -lt $DNList.Count; $i++) {
    [PSCustomObject]@{
        DisplayName = $DNList[$i]
        PackageName = $PNList[$i]
    }
}

# 过滤出需要移除的应用(DisplayName在RemovalList中)
$AppsToRemove = $Apps | Where-Object { $RemovalList -contains $_.DisplayName }

# 循环执行移除命令
$AppsToRemove.PackageName | ForEach-Object {
    Write-Output "正在移除预装应用: $_"
    dism /Online /Remove-ProvisionedAppxPackage /PackageName:$_
}

你新脚本的优势说明

你后来改用PackageName前缀匹配的思路非常聪明!因为Windows预装应用的PackageName格式固定为[厂商].[应用名]_[版本]_[架构]_[ID],拆分后第一个部分正好对应DisplayName的核心标识。这个方法反而比直接对比DisplayName更稳定——毕竟有些应用的DisplayName可能存在大小写差异或者本地化后缀,而PackageName的前缀是统一的。

不过要注意,PowerShell的-contains默认不区分大小写,所以你$RemovalList里的小写名称(比如microsoft.windowscommunicationsapps)也能匹配到实际的大写前缀,这点不用担心。

额外补充

关于你提到的Remove-ProvisionedAppxPackage cmdlet在启动脚本中无法运行的问题,确实在OOBE或者早期启动阶段,DISM命令的兼容性更好,因为它是底层系统工具,不依赖PowerShell的某些未完全初始化的组件,所以用DISM命令是更稳妥的选择。

内容的提问来源于stack exchange,提问作者Irenicus

火山引擎 最新活动