本文提供有关在作系统更新期间保留语言资源和按需功能的问题的一些背景信息,并提供指导来帮助你在短期内继续前进并为长期做好准备。
更新作系统时,务必将语言资源和按需功能 (FOD) 。 许多商业组织使用Configuration Manager或其他管理工具来分发和协调使用本地 Windows 映像或 WIM 文件 (基于媒体或基于任务序列的更新) 的 Windows 客户端设置。 其他人则通过使用Windows Server Update Services (WSUS) 、Configuration Manager或等效工具 (基于服务的更新) ,使用批准的 Windows 客户端功能更新进行就地更新。
这两种方法均不包含用户设备可能需要的完整 Windows 可选功能集,因此这些功能不会迁移到新的作系统。 过去,这些功能在Configuration Manager或 WSUS 中不可用,在功能更新后无法在本地获取。
什么是可选内容?
可选内容包括以下项:
- 常规按需功能也称为 FOD (例如,Windows Mixed Reality)
- 基于语言的 FOD 和区域 FOD (例如 Language.Basicл ja-jp~0.0.1.0)
- 本地体验包
- 语言包
默认情况下,Windows 映像文件中不包含可选内容,该文件是批量许可服务中心 (VLSC) 中提供的作系统介质的一部分。 相反,它作为 VLSC 上的附加 ISO 文件发布。 从作系统介质中提供这些功能并单独交付,可减少 Windows 的磁盘占用量。 此方法为用户的数据提供更多空间。 此外,无论是安装每月质量更新还是升级到较新版本,它都减少了为作系统提供服务所需的时间。 较小的默认 Windows 映像还意味着通过网络传输的数据更少。
为什么获取可选内容具有挑战性?
围绕可选内容的挑战通常分为两组:
作系统更新不完整
第一个挑战与功能更新期间的内容迁移相关。 当 Windows 安装程序执行就地更新时,新作系统将连同临时文件夹中的旧版本一起写入用户的磁盘,其中安装了第二个干净作系统,并准备供用户 移动到其中。 作发生时,Windows 安装程序会枚举已安装在当前版本中的可选内容,并计划在新的作系统中安装此内容的新版本。
Windows 安装程序需要访问可选内容。 由于可选内容默认不在 Windows 映像中,Windows 安装程序必须查找其他位置才能获取 Windows 包、暂存这些包,然后在新的作系统中安装它们。 当找不到内容时,结果是设备上缺少功能的更新、最终用户感到沮丧,并且可能是技术支持呼叫。 此痛点有时称为 在更新期间迁移可选内容失败。 对于基于媒体的更新,Windows 将在新作系统启动时自动重试。 我们称之为 这种潜在收购。
用户启动的功能获取失败
第二个挑战涉及用户请求功能时无法获取功能。 假设一个用户使用新版本的 Windows 客户端运行设备,方法是使用全新安装或就地更新。 用户访问 “设置”,并尝试安装第二种语言、更多语言体验功能或其他可选内容。 同样,由于这些功能不在作系统中,因此需要获取包。 对于具有 Internet 访问权限的典型用户,Windows 从附近的Microsoft内容分发网络获取功能,并且一切按设计工作。 对于商业用户,某些用户可能没有 Internet 访问权限,或者有阻止通过 Internet 获取的策略。 在这些情况下,Windows 必须从备用位置获取内容。 当找不到内容时,用户会感到沮丧,并可能导致另一个技术支持呼叫。 此痛点有时称为 无法获取可选内容。
用于获取可选内容的选项
大多数商业组织都了解上面概述的痛点,讨论通常从他们询问哪些计划可用于应对这些挑战开始。 下表包含多个选项以供考虑,具体取决于当前部署 Windows 客户端的方式。 表标题中使用以下定义:
- 迁移:支持更新期间的可选内容迁移。
- 获取:支持可选的内容获取 (,即由用户) 启动的。
- 媒体:适用于基于媒体的部署。
- 服务:适用于基于服务的部署。
方法 | 迁移 | 购置 | Media | 维护 |
---|---|---|---|---|
选项 1:使用Windows 更新 | 是 | 是 | 否 | 是 |
选项 2:将 WSUS 与 UUP 集成配合使用 | 是 | 是 | 否 | 是 |
选项 3:启用动态更新 | 是 | 否 | 是 | 是 |
选项 4:在部署之前自定义 Windows 映像 | 是 | 否 | 是 | 否 |
选项 5:在部署期间安装语言功能 | 部分 | 否 | 是 | 否 |
选项 6:部署后安装可选内容 | 是 | 否 | 是 | 是 |
选项 7:为按需功能配置替代源 | 否 | 部分 | 是 | 是 |
选项 1:使用Windows 更新
Windows 更新客户端策略解决可选内容问题。 可选内容已发布,可供 Windows 安装程序从附近的Microsoft内容分发网络获取,并使用统一更新平台获取。 仅当设备连接到使用统一更新平台的更新服务(例如Windows 更新或Windows 更新客户端策略)时,可选内容迁移和获取方案才起作用。 如果由于某种原因,语言包在更新期间无法安装,则更新将自动回滚。
统一更新平台是基础 Windows 更新技术的改进,它使下载大小更小,协议更高效,用于检查更新、获取和安装所需的包,并在一个更新步骤中获取最新。 该技术是统一的,因为它汇集了 Windows 客户端、Windows Server和其他产品(如 HoloLens)的更新堆栈。
请考虑迁移到Windows 更新客户端策略。 可选内容方案不仅可以像现在) 的消费类设备一样无缝地 (工作,还可以获得更小的下载大小的全部优势。 此外,当作系统安装语言无意中更改为新语言时,设备不会受到升级 Windows 的挑战。 否则,当安装介质具有其他安装语言时,任何将来基于媒体的功能更新都可能会失败。 有关此问题的详细信息,请参阅使用不同于原始 OS 安装语言的安装媒体升级Windows 10设备。
选项 2:将 WSUS 与 UUP 集成配合使用
从 2023 年 3 月开始,UUP 已与 WSUS 集成,Configuration Manager将Windows 更新的相同可选内容和获取优势引入本地管理解决方案。 例如:
FOD 和语言将自动迁移用于使用 WSUS 中批准的Windows 11版本 22H2 客户端功能更新执行就地更新的设备。 同样,更新(如组合累积更新、安装程序更新和安全 OS 更新)也包括在内,并且根据批准功能更新的月份进行更新。
使用本地 Windows 映像升级但使用 WSUS 或Configuration Manager批准合并累积更新的设备将受益于在更新后的 Windows OS 中支持可选内容获取以及作系统自我修复。
启用此功能所需的内容将通过 WSUS 或Configuration Manager获取,客户端终结点不需要 Internet 连接。 若要实现此改进,每次 Windows 主要版本一次,需要大量下载到 WSUS 内容目录或分发点。 这包括支持 FOD 和语言获取的包,以及用于由于损坏而启用 OS 自我修复的包。 有关详细信息,请参阅 规划 WSUS 部署。
选项 3:启用动态更新
如果尚未准备好移动到Windows 更新,另一个选项是在功能更新期间启用动态更新。 一旦 Windows 功能更新启动,无论是通过基于媒体的更新还是基于 WSUS 的功能更新,动态更新都是首先调用的步骤之一。 Windows 安装程序连接到Microsoft托管的面向 Internet 的 URL 以获取动态更新内容,然后将这些更新应用于作系统安装媒体。 获取的内容包括以下内容:
- 安装程序更新:修复了 Setup.exe 二进制文件或安装程序用于功能更新的任何文件。
- 安全 OS 更新:用于更新 Windows 恢复环境 (WinRE) 的安全 OS 的修补程序。
- 服务堆栈更新:解决 Windows 服务堆栈问题所需的修补程序,因此需要完成功能更新。
- 最新累积更新:安装最新的累积质量更新。
- 驱动程序更新:制造商已发布到Windows 更新的适用驱动程序的最新版本,专用于动态更新。
除了新作系统的这些更新之外,动态更新还会在更新过程中获取可选内容,以确保设备在更新完成时具有此内容。 因此,尽管设备未连接到Windows 更新,但它从附近的Microsoft内容下载网络 (CDN) 提取内容。 此方法通过可选内容(而不是用户发起的获取)解决了第一个痛点。 默认情况下, 动态更新 由 Windows 安装程序启用。 可以使用 Windows 安装程序中的 /DynamicUpdate 选项启用或禁用动态更新。 如果使用基于服务的方法,则可以使用 setupconfig.ini
设置此值。 有关详细信息 ,请参阅 Windows 安装程序自动化概述 。
可以使用其他选项配置动态更新。 例如,你可能希望获得可选内容迁移的好处,而无需自动获取最新的质量更新。 可以使用 Windows 安装程序的 /DynamicUpdate NoLCU 选项执行此作。 之后,你将单独遵循现有的流程来测试和批准每月更新。 此方法的缺点是设备会再次重新启动以获取最新的累积更新,因为它在功能更新期间不可用。
使用动态更新时,另一个注意事项是对网络的影响。 此方法的主要阻碍因素之一是担心每个设备会分别从Microsoft提取此内容。 安装程序使用传递优化(如果可用)下载动态更新内容。 对于未连接到 Internet 的设备,可以使用 WSUS 和 Microsoft 目录获取动态更新内容的子集。
选项 4:在部署之前自定义 Windows 映像
对于许多组织,部署工作流涉及执行基于媒体的更新的Configuration Manager任务序列。 某些客户没有 Internet 连接,或者连接性较差,因此无法启用动态更新。 在这些情况下,我们建议在部署之前安装可选内容。 此活动有时称为自定义安装媒体。
可以通过以下方式自定义 Windows 映像:
- 应用累积更新
- 将更新应用于服务堆栈
- 将更新应用于
Setup.exe
安装程序用于功能更新的二进制文件或其他文件 - 应用用于 Windows 恢复环境 的安全作系统 (SafeOS) 的更新
- 添加或删除语言
- 按需添加或删除功能
此选项的优点是通过一次性更新映像,Windows 映像可以包括这些其他语言、语言体验功能和其他按需功能。 然后,可以在涉及的现有任务序列或自定义部署 Setup.exe
中使用它们。 此方法的缺点是需要提前准备映像,包括使用 DISM 编写脚本以安装其他包。 这也意味着映像对于使用它的所有设备都是相同的,并且可能包含比某些用户所需的更多功能。 有关自定义媒体的详细信息,请参阅使用动态更新包更新Windows 10媒体。 与动态更新一样,你仍具有迁移可选内容的解决方案,但不支持用户发起的可选内容获取。 此外,此选项有一个变体,即在安装前 在设备上 更新媒体。 此选项允许根据当前安装的内容自定义特定于设备的映像。
选项 5:在部署期间安装语言功能
解决升级期间无法迁移可选内容的第一个痛点的部分解决方案是在升级过程中注入一部分可选内容。 此方法使用 Windows 安装程序选项 /InstallLangPacks 从包含包的文件夹添加语言包和语言功能,例如文本到语音识别。 此方法允许 IT 专业人员获取一部分可选内容,并将其暂存到其网络中。 如果使用基于服务的方法,则可以使用 setupconfig.ini
配置 InstallLangPacks。 有关详细信息,请参阅 Windows 安装程序自动化概述。
安装程序运行时,会在安装过程中将这些包注入到新的作系统中。 它可以替代在部署前启用动态更新或自定义作系统映像。 必须使用此方法,因为无法重命名包。 此外,内容来自两个单独的发布媒体 ISO。 关键是将 FOD 包和 FOD 元数据 .cab 从 FOD ISO 复制到 文件夹中,以及体系结构特定的语言包 .cab LPLIP ISO 中的文件。 我们将 InstallLangPacks 失败视为致命故障,并回滚整个升级。 其思路是不要使用户处于不良状态,因为基于媒体的升级不会迁移 FOD 和语言 (,除非) 启用了动态更新。
此方法有一些有趣的好处。 无需修改原始 Windows 映像,可能会节省时间和编写脚本。
选项 6:部署后安装可选内容
此选项与选项 4 类似,可在部署后使用更多可选内容自定义作系统映像。 IT 专业人员可以通过在功能更新期间和之后运行自己的自定义作脚本来扩展 Windows 安装程序的行为。 有关详细信息 ,请参阅在功能更新期间运行自定义作 。 使用此方法,可以捕获作系统中安装的可选内容,然后保存此列表以在新作系统中安装相同的可选内容,从而创建特定于设备的可选内容迁移。 与选项 5 一样,可在内部托管包含可选内容包源的网络共享。 然后,在设备上执行安装程序期间,从源作系统捕获已安装的可选内容列表并保存。 稍后,在安装程序完成后,使用列表安装可选内容,这会使用户设备不丢失功能。
选项 7:为可选内容配置备用源
其中几个选项解决了就地更新期间解决可选内容迁移问题的方法。 若要解决在用户发起的情况下轻松获取可选内容的第二个痛点,可以使用指定可选组件安装和组件修复组策略设置来配置每个设备。 此策略设置指定用于修复作系统损坏和启用已删除其有效负载文件的可选功能的网络位置。 这种方法的缺点是,除了作系统映像之外,网络 (可能仍在部署到某些客户端) 但具有获取网络内内容的优势。 有关此策略的一些提醒:
- 备用源的文件路径必须是完全限定的路径;多个位置可以用分号分隔。
- 此设置不支持从备用源文件路径安装语言包,仅支持按需功能。 如果策略配置为从Windows 更新获取内容,则将获取语言包。
- 如果未配置或禁用此设置,则会从默认Windows 更新位置(例如,Windows 更新客户端策略或 WSUS)下载文件。
有关详细信息,请参阅配置 Windows 修复源和如何在使用 WSUS 或 Configuration Manager 时使按需功能和语言包可用。
更多资源
有关统一更新平台和本文中概述的方法的详细信息,请参阅以下资源:
- 规划 WSUS 部署
- /InstallLangPacks
- /DynamicUpdate
- 配置 Windows 修复源
- 在功能更新期间运行自定义作
- 统一更新平台
- 使用动态更新包更新 Windows 安装媒体
- Windows 安装程序自动化概述
示例脚本
选项 4 和 6 涉及的脚本最多。 选项 4 的示例脚本已存在,因此让我们查看 选项 6 的示例脚本:部署后安装可选内容。
创建可选内容存储库
首先,我们在网络共享上生成可选内容和主机的存储库。 此内容是每个版本随附的 FOD 和语言包 ISO 中内容的子集。 我们使用 DISM/Export 配置此存储库或存储库,仅使用组织所需的 FOD。 例如,基于在现有设备上安装的可选功能的清单的超集。 在本例中,我们将排除Windows Mixed Reality功能。 此外,我们会将所有语言包复制到存储库的根目录中。
# Declare media for FOD and LPs
$LP_ISO_PATH = "C:\_IMAGE\2004_ISO\CLIENTLANGPACKDVD_OEM_MULTI.iso"
$FOD_ISO_PATH = "C:\_IMAGE\2004_ISO\FOD-PACKAGES_OEM_PT1_amd64fre_MULTI.iso"
# Declare folders
$WORKING_PATH = "C:\_IMAGE\BuildRepo"
$MEDIA_PATH = "C:\_IMAGE\2004_SETUP"
$MAIN_OS_MOUNT = $WORKING_PATH + "\MainOSMount"
$REPO_PATH = $WORKING_PATH + "\Repo"
# Create folders for mounting image optional content repository
if (Test-Path $MAIN_OS_MOUNT) {
Remove-Item -Path $MAIN_OS_MOUNT -Force -Recurse -ErrorAction stop| Out-Null
}
if (Test-Path $REPO_PATH) {
Remove-Item -Path $REPO_PATH -Force -Recurse -ErrorAction stop| Out-Null
}
New-Item -ItemType Directory -Force -Path $MAIN_OS_MOUNT -ErrorAction stop| Out-Null
New-Item -ItemType Directory -Force -Path $REPO_PATH -ErrorAction stop| Out-Null
# Mount the main OS, I'll use this throughout the script
Write-Host "Mounting main OS"
Mount-WindowsImage -ImagePath $MEDIA_PATH"\sources\install.wim" -Index 1 -Path $MAIN_OS_MOUNT -ErrorAction stop| Out-Null
# Mount the LP ISO
Write-Host "Mounting LP ISO"
$LP_ISO_DRIVE_LETTER = (Mount-DiskImage -ImagePath $LP_ISO_PATH -ErrorAction stop | Get-Volume).DriveLetter
# Declare language related cabs
$OS_LP_PATH = $LP_ISO_DRIVE_LETTER + ":\x64\langpacks\" + "*.cab"
# Mount the FOD ISO
Write-Host "Mounting FOD ISO"
$FOD_ISO_DRIVE_LETTER = (Mount-DiskImage -ImagePath $FOD_ISO_PATH -ErrorAction stop | Get-Volume).DriveLetter
$FOD_PATH = $FOD_ISO_DRIVE_LETTER + ":\"
# Export the FODs from the ISO that we are interested in
Write-Host "Exporting FODs to Repo"
DISM /image:$MAIN_OS_MOUNT /export-source /source:$FOD_PATH /target:$REPO_PATH `
/capabilityname:Accessibility.Braille~~~~0.0.1.0 `
/capabilityname:App.StepsRecorder~~~~0.0.1.0 `
/capabilityname:App.WirelessDisplay.Connect~~~~0.0.1.0 `
/capabilityname:Browser.InternetExplorer~~~~0.0.11.0 `
/capabilityname:DirectX.Configuration.Database~~~~0.0.1.0 `
/capabilityname:Language.Basic~~~af-za~0.0.1.0 `
/capabilityname:Language.Basic~~~ar-sa~0.0.1.0 `
/capabilityname:Language.Basic~~~as-in~0.0.1.0 `
/capabilityname:Language.Basic~~~az-latn-az~0.0.1.0 `
/capabilityname:Language.Basic~~~ba-ru~0.0.1.0 `
/capabilityname:Language.Basic~~~be-by~0.0.1.0 `
/capabilityname:Language.Basic~~~bg-bg~0.0.1.0 `
/capabilityname:Language.Basic~~~bn-bd~0.0.1.0 `
/capabilityname:Language.Basic~~~bn-in~0.0.1.0 `
/capabilityname:Language.Basic~~~bs-latn-ba~0.0.1.0 `
/capabilityname:Language.Basic~~~ca-es~0.0.1.0 `
/capabilityname:Language.Basic~~~cs-cz~0.0.1.0 `
/capabilityname:Language.Basic~~~cy-gb~0.0.1.0 `
/capabilityname:Language.Basic~~~da-dk~0.0.1.0 `
/capabilityname:Language.Basic~~~de-ch~0.0.1.0 `
/capabilityname:Language.Basic~~~de-de~0.0.1.0 `
/capabilityname:Language.Basic~~~el-gr~0.0.1.0 `
/capabilityname:Language.Basic~~~en-au~0.0.1.0 `
/capabilityname:Language.Basic~~~en-ca~0.0.1.0 `
/capabilityname:Language.Basic~~~en-gb~0.0.1.0 `
/capabilityname:Language.Basic~~~en-in~0.0.1.0 `
/capabilityname:Language.Basic~~~en-us~0.0.1.0 `
/capabilityname:Language.Basic~~~es-es~0.0.1.0 `
/capabilityname:Language.Basic~~~es-mx~0.0.1.0 `
/capabilityname:Language.Basic~~~es-us~0.0.1.0 `
/capabilityname:Language.Basic~~~et-ee~0.0.1.0 `
/capabilityname:Language.Basic~~~eu-es~0.0.1.0 `
/capabilityname:Language.Basic~~~fa-ir~0.0.1.0 `
/capabilityname:Language.Basic~~~fi-fi~0.0.1.0 `
/capabilityname:Language.Basic~~~fil-ph~0.0.1.0 `
/capabilityname:Language.Basic~~~fr-be~0.0.1.0 `
/capabilityname:Language.Basic~~~fr-ca~0.0.1.0 `
/capabilityname:Language.Basic~~~fr-ch~0.0.1.0 `
/capabilityname:Language.Basic~~~fr-fr~0.0.1.0 `
/capabilityname:Language.Basic~~~ga-ie~0.0.1.0 `
/capabilityname:Language.Basic~~~gd-gb~0.0.1.0 `
/capabilityname:Language.Basic~~~gl-es~0.0.1.0 `
/capabilityname:Language.Basic~~~gu-in~0.0.1.0 `
/capabilityname:Language.Basic~~~ha-latn-ng~0.0.1.0 `
/capabilityname:Language.Basic~~~haw-us~0.0.1.0 `
/capabilityname:Language.Basic~~~he-il~0.0.1.0 `
/capabilityname:Language.Basic~~~hi-in~0.0.1.0 `
/capabilityname:Language.Basic~~~hr-hr~0.0.1.0 `
/capabilityname:Language.Basic~~~hu-hu~0.0.1.0 `
/capabilityname:Language.Basic~~~hy-am~0.0.1.0 `
/capabilityname:Language.Basic~~~id-id~0.0.1.0 `
/capabilityname:Language.Basic~~~ig-ng~0.0.1.0 `
/capabilityname:Language.Basic~~~is-is~0.0.1.0 `
/capabilityname:Language.Basic~~~it-it~0.0.1.0 `
/capabilityname:Language.Basic~~~ja-jp~0.0.1.0 `
/capabilityname:Language.Basic~~~ka-ge~0.0.1.0 `
/capabilityname:Language.Basic~~~kk-kz~0.0.1.0 `
/capabilityname:Language.Basic~~~kl-gl~0.0.1.0 `
/capabilityname:Language.Basic~~~kn-in~0.0.1.0 `
/capabilityname:Language.Basic~~~kok-deva-in~0.0.1.0 `
/capabilityname:Language.Basic~~~ko-kr~0.0.1.0 `
/capabilityname:Language.Basic~~~ky-kg~0.0.1.0 `
/capabilityname:Language.Basic~~~lb-lu~0.0.1.0 `
/capabilityname:Language.Basic~~~lt-lt~0.0.1.0 `
/capabilityname:Language.Basic~~~lv-lv~0.0.1.0 `
/capabilityname:Language.Basic~~~mi-nz~0.0.1.0 `
/capabilityname:Language.Basic~~~mk-mk~0.0.1.0 `
/capabilityname:Language.Basic~~~ml-in~0.0.1.0 `
/capabilityname:Language.Basic~~~mn-mn~0.0.1.0 `
/capabilityname:Language.Basic~~~mr-in~0.0.1.0 `
/capabilityname:Language.Basic~~~ms-bn~0.0.1.0 `
/capabilityname:Language.Basic~~~ms-my~0.0.1.0 `
/capabilityname:Language.Basic~~~mt-mt~0.0.1.0 `
/capabilityname:Language.Basic~~~nb-no~0.0.1.0 `
/capabilityname:Language.Basic~~~ne-np~0.0.1.0 `
/capabilityname:Language.Basic~~~nl-nl~0.0.1.0 `
/capabilityname:Language.Basic~~~nn-no~0.0.1.0 `
/capabilityname:Language.Basic~~~nso-za~0.0.1.0 `
/capabilityname:Language.Basic~~~or-in~0.0.1.0 `
/capabilityname:Language.Basic~~~pa-in~0.0.1.0 `
/capabilityname:Language.Basic~~~pl-pl~0.0.1.0 `
/capabilityname:Language.Basic~~~ps-af~0.0.1.0 `
/capabilityname:Language.Basic~~~pt-br~0.0.1.0 `
/capabilityname:Language.Basic~~~pt-pt~0.0.1.0 `
/capabilityname:Language.Basic~~~rm-ch~0.0.1.0 `
/capabilityname:Language.Basic~~~ro-ro~0.0.1.0 `
/capabilityname:Language.Basic~~~ru-ru~0.0.1.0 `
/capabilityname:Language.Basic~~~rw-rw~0.0.1.0 `
/capabilityname:Language.Basic~~~sah-ru~0.0.1.0 `
/capabilityname:Language.Basic~~~si-lk~0.0.1.0 `
/capabilityname:Language.Basic~~~sk-sk~0.0.1.0 `
/capabilityname:Language.Basic~~~sl-si~0.0.1.0 `
/capabilityname:Language.Basic~~~sq-al~0.0.1.0 `
/capabilityname:Language.Basic~~~sr-cyrl-rs~0.0.1.0 `
/capabilityname:Language.Basic~~~sr-latn-rs~0.0.1.0 `
/capabilityname:Language.Basic~~~sv-se~0.0.1.0 `
/capabilityname:Language.Basic~~~sw-ke~0.0.1.0 `
/capabilityname:Language.Basic~~~ta-in~0.0.1.0 `
/capabilityname:Language.Basic~~~te-in~0.0.1.0 `
/capabilityname:Language.Basic~~~tg-cyrl-tj~0.0.1.0 `
/capabilityname:Language.Basic~~~th-th~0.0.1.0 `
/capabilityname:Language.Basic~~~tk-tm~0.0.1.0 `
/capabilityname:Language.Basic~~~tn-za~0.0.1.0 `
/capabilityname:Language.Basic~~~tr-tr~0.0.1.0 `
/capabilityname:Language.Basic~~~tt-ru~0.0.1.0 `
/capabilityname:Language.Basic~~~ug-cn~0.0.1.0 `
/capabilityname:Language.Basic~~~uk-ua~0.0.1.0 `
/capabilityname:Language.Basic~~~ur-pk~0.0.1.0 `
/capabilityname:Language.Basic~~~uz-latn-uz~0.0.1.0 `
/capabilityname:Language.Basic~~~vi-vn~0.0.1.0 `
/capabilityname:Language.Basic~~~wo-sn~0.0.1.0 `
/capabilityname:Language.Basic~~~xh-za~0.0.1.0 `
/capabilityname:Language.Basic~~~yo-ng~0.0.1.0 `
/capabilityname:Language.Basic~~~zh-cn~0.0.1.0 `
/capabilityname:Language.Basic~~~zh-hk~0.0.1.0 `
/capabilityname:Language.Basic~~~zh-tw~0.0.1.0 `
/capabilityname:Language.Basic~~~zu-za~0.0.1.0 `
/capabilityname:Language.Fonts.Arab~~~und-Arab~0.0.1.0 `
/capabilityname:Language.Fonts.Beng~~~und-Beng~0.0.1.0 `
/capabilityname:Language.Fonts.Cans~~~und-Cans~0.0.1.0 `
/capabilityname:Language.Fonts.Cher~~~und-Cher~0.0.1.0 `
/capabilityname:Language.Fonts.Deva~~~und-Deva~0.0.1.0 `
/capabilityname:Language.Fonts.Ethi~~~und-Ethi~0.0.1.0 `
/capabilityname:Language.Fonts.Gujr~~~und-Gujr~0.0.1.0 `
/capabilityname:Language.Fonts.Guru~~~und-Guru~0.0.1.0 `
/capabilityname:Language.Fonts.Hans~~~und-Hans~0.0.1.0 `
/capabilityname:Language.Fonts.Hant~~~und-Hant~0.0.1.0 `
/capabilityname:Language.Fonts.Hebr~~~und-Hebr~0.0.1.0 `
/capabilityname:Language.Fonts.Jpan~~~und-Jpan~0.0.1.0 `
/capabilityname:Language.Fonts.Khmr~~~und-Khmr~0.0.1.0 `
/capabilityname:Language.Fonts.Knda~~~und-Knda~0.0.1.0 `
/capabilityname:Language.Fonts.Kore~~~und-Kore~0.0.1.0 `
/capabilityname:Language.Fonts.Laoo~~~und-Laoo~0.0.1.0 `
/capabilityname:Language.Fonts.Mlym~~~und-Mlym~0.0.1.0 `
/capabilityname:Language.Fonts.Orya~~~und-Orya~0.0.1.0 `
/capabilityname:Language.Fonts.PanEuropeanSupplementalFonts~~~0.0.1.0 `
/capabilityname:Language.Fonts.Sinh~~~und-Sinh~0.0.1.0 `
/capabilityname:Language.Fonts.Syrc~~~und-Syrc~0.0.1.0 `
/capabilityname:Language.Fonts.Taml~~~und-Taml~0.0.1.0 `
/capabilityname:Language.Fonts.Telu~~~und-Telu~0.0.1.0 `
/capabilityname:Language.Fonts.Thai~~~und-Thai~0.0.1.0 `
/capabilityname:Language.Handwriting~~~af-za~0.0.1.0 `
/capabilityname:Language.Handwriting~~~bs-latn-ba~0.0.1.0 `
/capabilityname:Language.Handwriting~~~ca-es~0.0.1.0 `
/capabilityname:Language.Handwriting~~~cs-cz~0.0.1.0 `
/capabilityname:Language.Handwriting~~~cy-gb~0.0.1.0 `
/capabilityname:Language.Handwriting~~~da-dk~0.0.1.0 `
/capabilityname:Language.Handwriting~~~de-de~0.0.1.0 `
/capabilityname:Language.Handwriting~~~el-gr~0.0.1.0 `
/capabilityname:Language.Handwriting~~~en-gb~0.0.1.0 `
/capabilityname:Language.Handwriting~~~en-us~0.0.1.0 `
/capabilityname:Language.Handwriting~~~es-es~0.0.1.0 `
/capabilityname:Language.Handwriting~~~es-mx~0.0.1.0 `
/capabilityname:Language.Handwriting~~~eu-es~0.0.1.0 `
/capabilityname:Language.Handwriting~~~fi-fi~0.0.1.0 `
/capabilityname:Language.Handwriting~~~fr-fr~0.0.1.0 `
/capabilityname:Language.Handwriting~~~ga-ie~0.0.1.0 `
/capabilityname:Language.Handwriting~~~gd-gb~0.0.1.0 `
/capabilityname:Language.Handwriting~~~gl-es~0.0.1.0 `
/capabilityname:Language.Handwriting~~~hi-in~0.0.1.0 `
/capabilityname:Language.Handwriting~~~hr-hr~0.0.1.0 `
/capabilityname:Language.Handwriting~~~id-id~0.0.1.0 `
/capabilityname:Language.Handwriting~~~it-it~0.0.1.0 `
/capabilityname:Language.Handwriting~~~ja-jp~0.0.1.0 `
/capabilityname:Language.Handwriting~~~ko-kr~0.0.1.0 `
/capabilityname:Language.Handwriting~~~lb-lu~0.0.1.0 `
/capabilityname:Language.Handwriting~~~mi-nz~0.0.1.0 `
/capabilityname:Language.Handwriting~~~ms-bn~0.0.1.0 `
/capabilityname:Language.Handwriting~~~ms-my~0.0.1.0 `
/capabilityname:Language.Handwriting~~~nb-no~0.0.1.0 `
/capabilityname:Language.Handwriting~~~nl-nl~0.0.1.0 `
/capabilityname:Language.Handwriting~~~nn-no~0.0.1.0 `
/capabilityname:Language.Handwriting~~~nso-za~0.0.1.0 `
/capabilityname:Language.Handwriting~~~pl-pl~0.0.1.0 `
/capabilityname:Language.Handwriting~~~pt-br~0.0.1.0 `
/capabilityname:Language.Handwriting~~~pt-pt~0.0.1.0 `
/capabilityname:Language.Handwriting~~~rm-ch~0.0.1.0 `
/capabilityname:Language.Handwriting~~~ro-ro~0.0.1.0 `
/capabilityname:Language.Handwriting~~~ru-ru~0.0.1.0 `
/capabilityname:Language.Handwriting~~~rw-rw~0.0.1.0 `
/capabilityname:Language.Handwriting~~~sk-sk~0.0.1.0 `
/capabilityname:Language.Handwriting~~~sl-si~0.0.1.0 `
/capabilityname:Language.Handwriting~~~sq-al~0.0.1.0 `
/capabilityname:Language.Handwriting~~~sr-cyrl-rs~0.0.1.0 `
/capabilityname:Language.Handwriting~~~sr-latn-rs~0.0.1.0 `
/capabilityname:Language.Handwriting~~~sv-se~0.0.1.0 `
/capabilityname:Language.Handwriting~~~sw-ke~0.0.1.0 `
/capabilityname:Language.Handwriting~~~tn-za~0.0.1.0 `
/capabilityname:Language.Handwriting~~~tr-tr~0.0.1.0 `
/capabilityname:Language.Handwriting~~~wo-sn~0.0.1.0 `
/capabilityname:Language.Handwriting~~~xh-za~0.0.1.0 `
/capabilityname:Language.Handwriting~~~zh-cn~0.0.1.0 `
/capabilityname:Language.Handwriting~~~zh-hk~0.0.1.0 `
/capabilityname:Language.Handwriting~~~zh-tw~0.0.1.0 `
/capabilityname:Language.Handwriting~~~zu-za~0.0.1.0 `
/capabilityname:Language.LocaleData~~~zh-tw~0.0.1.0 `
/capabilityname:Language.OCR~~~ar-sa~0.0.1.0 `
/capabilityname:Language.OCR~~~bg-bg~0.0.1.0 `
/capabilityname:Language.OCR~~~bs-latn-ba~0.0.1.0 `
/capabilityname:Language.OCR~~~cs-cz~0.0.1.0 `
/capabilityname:Language.OCR~~~da-dk~0.0.1.0 `
/capabilityname:Language.OCR~~~de-de~0.0.1.0 `
/capabilityname:Language.OCR~~~el-gr~0.0.1.0 `
/capabilityname:Language.OCR~~~en-gb~0.0.1.0 `
/capabilityname:Language.OCR~~~en-us~0.0.1.0 `
/capabilityname:Language.OCR~~~es-es~0.0.1.0 `
/capabilityname:Language.OCR~~~es-mx~0.0.1.0 `
/capabilityname:Language.OCR~~~fi-fi~0.0.1.0 `
/capabilityname:Language.OCR~~~fr-ca~0.0.1.0 `
/capabilityname:Language.OCR~~~fr-fr~0.0.1.0 `
/capabilityname:Language.OCR~~~hr-hr~0.0.1.0 `
/capabilityname:Language.OCR~~~hu-hu~0.0.1.0 `
/capabilityname:Language.OCR~~~it-it~0.0.1.0 `
/capabilityname:Language.OCR~~~ja-jp~0.0.1.0 `
/capabilityname:Language.OCR~~~ko-kr~0.0.1.0 `
/capabilityname:Language.OCR~~~nb-no~0.0.1.0 `
/capabilityname:Language.OCR~~~nl-nl~0.0.1.0 `
/capabilityname:Language.OCR~~~pl-pl~0.0.1.0 `
/capabilityname:Language.OCR~~~pt-br~0.0.1.0 `
/capabilityname:Language.OCR~~~pt-pt~0.0.1.0 `
/capabilityname:Language.OCR~~~ro-ro~0.0.1.0 `
/capabilityname:Language.OCR~~~ru-ru~0.0.1.0 `
/capabilityname:Language.OCR~~~sk-sk~0.0.1.0 `
/capabilityname:Language.OCR~~~sl-si~0.0.1.0 `
/capabilityname:Language.OCR~~~sr-cyrl-rs~0.0.1.0 `
/capabilityname:Language.OCR~~~sr-latn-rs~0.0.1.0 `
/capabilityname:Language.OCR~~~sv-se~0.0.1.0 `
/capabilityname:Language.OCR~~~tr-tr~0.0.1.0 `
/capabilityname:Language.OCR~~~zh-cn~0.0.1.0 `
/capabilityname:Language.OCR~~~zh-hk~0.0.1.0 `
/capabilityname:Language.OCR~~~zh-tw~0.0.1.0 `
/capabilityname:Language.Speech~~~da-dk~0.0.1.0 `
/capabilityname:Language.Speech~~~de-de~0.0.1.0 `
/capabilityname:Language.Speech~~~en-au~0.0.1.0 `
/capabilityname:Language.Speech~~~en-ca~0.0.1.0 `
/capabilityname:Language.Speech~~~en-gb~0.0.1.0 `
/capabilityname:Language.Speech~~~en-in~0.0.1.0 `
/capabilityname:Language.Speech~~~en-us~0.0.1.0 `
/capabilityname:Language.Speech~~~es-es~0.0.1.0 `
/capabilityname:Language.Speech~~~es-mx~0.0.1.0 `
/capabilityname:Language.Speech~~~fr-ca~0.0.1.0 `
/capabilityname:Language.Speech~~~fr-fr~0.0.1.0 `
/capabilityname:Language.Speech~~~it-it~0.0.1.0 `
/capabilityname:Language.Speech~~~ja-jp~0.0.1.0 `
/capabilityname:Language.Speech~~~pt-br~0.0.1.0 `
/capabilityname:Language.Speech~~~zh-cn~0.0.1.0 `
/capabilityname:Language.Speech~~~zh-hk~0.0.1.0 `
/capabilityname:Language.Speech~~~zh-tw~0.0.1.0 `
/capabilityname:Language.TextToSpeech~~~ar-eg~0.0.1.0 `
/capabilityname:Language.TextToSpeech~~~ar-sa~0.0.1.0 `
/capabilityname:Language.TextToSpeech~~~bg-bg~0.0.1.0 `
/capabilityname:Language.TextToSpeech~~~ca-es~0.0.1.0 `
/capabilityname:Language.TextToSpeech~~~cs-cz~0.0.1.0 `
/capabilityname:Language.TextToSpeech~~~da-dk~0.0.1.0 `
/capabilityname:Language.TextToSpeech~~~de-at~0.0.1.0 `
/capabilityname:Language.TextToSpeech~~~de-ch~0.0.1.0 `
/capabilityname:Language.TextToSpeech~~~de-de~0.0.1.0 `
/capabilityname:Language.TextToSpeech~~~el-gr~0.0.1.0 `
/capabilityname:Language.TextToSpeech~~~en-au~0.0.1.0 `
/capabilityname:Language.TextToSpeech~~~en-ca~0.0.1.0 `
/capabilityname:Language.TextToSpeech~~~en-gb~0.0.1.0 `
/capabilityname:Language.TextToSpeech~~~en-ie~0.0.1.0 `
/capabilityname:Language.TextToSpeech~~~en-in~0.0.1.0 `
/capabilityname:Language.TextToSpeech~~~en-us~0.0.1.0 `
/capabilityname:Language.TextToSpeech~~~es-es~0.0.1.0 `
/capabilityname:Language.TextToSpeech~~~es-mx~0.0.1.0 `
/capabilityname:Language.TextToSpeech~~~fi-fi~0.0.1.0 `
/capabilityname:Language.TextToSpeech~~~fr-ca~0.0.1.0 `
/capabilityname:Language.TextToSpeech~~~fr-ch~0.0.1.0 `
/capabilityname:Language.TextToSpeech~~~fr-fr~0.0.1.0 `
/capabilityname:Language.TextToSpeech~~~he-il~0.0.1.0 `
/capabilityname:Language.TextToSpeech~~~hi-in~0.0.1.0 `
/capabilityname:Language.TextToSpeech~~~hr-hr~0.0.1.0 `
/capabilityname:Language.TextToSpeech~~~hu-hu~0.0.1.0 `
/capabilityname:Language.TextToSpeech~~~id-id~0.0.1.0 `
/capabilityname:Language.TextToSpeech~~~it-it~0.0.1.0 `
/capabilityname:Language.TextToSpeech~~~ja-jp~0.0.1.0 `
/capabilityname:Language.TextToSpeech~~~ko-kr~0.0.1.0 `
/capabilityname:Language.TextToSpeech~~~ms-my~0.0.1.0 `
/capabilityname:Language.TextToSpeech~~~nb-no~0.0.1.0 `
/capabilityname:Language.TextToSpeech~~~nl-be~0.0.1.0 `
/capabilityname:Language.TextToSpeech~~~nl-nl~0.0.1.0 `
/capabilityname:Language.TextToSpeech~~~pl-pl~0.0.1.0 `
/capabilityname:Language.TextToSpeech~~~pt-br~0.0.1.0 `
/capabilityname:Language.TextToSpeech~~~pt-pt~0.0.1.0 `
/capabilityname:Language.TextToSpeech~~~ro-ro~0.0.1.0 `
/capabilityname:Language.TextToSpeech~~~ru-ru~0.0.1.0 `
/capabilityname:Language.TextToSpeech~~~sk-sk~0.0.1.0 `
/capabilityname:Language.TextToSpeech~~~sl-si~0.0.1.0 `
/capabilityname:Language.TextToSpeech~~~sv-se~0.0.1.0 `
/capabilityname:Language.TextToSpeech~~~ta-in~0.0.1.0 `
/capabilityname:Language.TextToSpeech~~~th-th~0.0.1.0 `
/capabilityname:Language.TextToSpeech~~~tr-tr~0.0.1.0 `
/capabilityname:Language.TextToSpeech~~~vi-vn~0.0.1.0 `
/capabilityname:Language.TextToSpeech~~~zh-cn~0.0.1.0 `
/capabilityname:Language.TextToSpeech~~~zh-hk~0.0.1.0 `
/capabilityname:Language.TextToSpeech~~~zh-tw~0.0.1.0 `
/capabilityname:MathRecognizer~~~~0.0.1.0 `
/capabilityname:Microsoft.Onecore.StorageManagement~~~~0.0.1.0 `
/capabilityname:Microsoft.WebDriver~~~~0.0.1.0 `
/capabilityname:Microsoft.Windows.MSPaint~~~~0.0.1.0 `
/capabilityname:Microsoft.Windows.Notepad~~~~0.0.1.0 `
/capabilityname:Microsoft.Windows.PowerShell.ISE~~~~0.0.1.0 `
/capabilityname:Microsoft.Windows.StorageManagement~~~~0.0.1.0 `
/capabilityname:Microsoft.Windows.WordPad~~~~0.0.1.0 `
/capabilityname:Msix.PackagingTool.Driver~~~~0.0.1.0 `
/capabilityname:NetFX3~~ `
/capabilityname:Network.Irda~~~~0.0.1.0 `
/capabilityname:OneCoreUAP.OneSync~~~~0.0.1.0 `
/capabilityname:OpenSSH.Client~~~~0.0.1.0 `
/capabilityname:OpenSSH.Server~~~~0.0.1.0 `
/capabilityname:Print.EnterpriseCloudPrint~~~~0.0.1.0 `
/capabilityname:Print.Fax.Scan~~~~0.0.1.0 `
/capabilityname:Print.Management.Console~~~~0.0.1.0 `
/capabilityname:Print.MopriaCloudService~~~~0.0.1.0 `
/capabilityname:RasCMAK.Client~~~~0.0.1.0 `
/capabilityname:RIP.Listener~~~~0.0.1.0 `
/capabilityname:Rsat.ActiveDirectory.DS-LDS.Tools~~~~0.0.1.0 `
/capabilityname:Rsat.BitLocker.Recovery.Tools~~~~0.0.1.0 `
/capabilityname:Rsat.CertificateServices.Tools~~~~0.0.1.0 `
/capabilityname:Rsat.DHCP.Tools~~~~0.0.1.0 `
/capabilityname:Rsat.Dns.Tools~~~~0.0.1.0 `
/capabilityname:Rsat.FailoverCluster.Management.Tools~~~~0.0.1.0 `
/capabilityname:Rsat.FileServices.Tools~~~~0.0.1.0 `
/capabilityname:Rsat.GroupPolicy.Management.Tools~~~~0.0.1.0 `
/capabilityname:Rsat.IPAM.Client.Tools~~~~0.0.1.0 `
/capabilityname:Rsat.LLDP.Tools~~~~0.0.1.0 `
/capabilityname:Rsat.NetworkController.Tools~~~~0.0.1.0 `
/capabilityname:Rsat.NetworkLoadBalancing.Tools~~~~0.0.1.0 `
/capabilityname:Rsat.RemoteAccess.Management.Tools~~~~0.0.1.0 `
/capabilityname:Rsat.RemoteDesktop.Services.Tools~~~~0.0.1.0 `
/capabilityname:Rsat.ServerManager.Tools~~~~0.0.1.0 `
/capabilityname:Rsat.Shielded.VM.Tools~~~~0.0.1.0 `
/capabilityname:Rsat.StorageMigrationService.Management.Tools~~~~0.0.1.0 `
/capabilityname:Rsat.StorageReplica.Tools~~~~0.0.1.0 `
/capabilityname:Rsat.SystemInsights.Management.Tools~~~~0.0.1.0 `
/capabilityname:Rsat.VolumeActivation.Tools~~~~0.0.1.0 `
/capabilityname:Rsat.WSUS.Tools~~~~0.0.1.0 `
/capabilityname:ServerCore.AppCompatibility~~~~0.0.1.0 `
/capabilityname:SNMP.Client~~~~0.0.1.0 `
/capabilityname:Tools.DeveloperMode.Core~~~~0.0.1.0 `
/capabilityname:Tools.Graphics.DirectX~~~~0.0.1.0 `
/capabilityname:Windows.Client.ShellComponents~~~~0.0.1.0 `
/capabilityname:Windows.Desktop.EMS-SAC.Tools~~~~0.0.1.0 `
/capabilityname:WMI-SNMP-Provider.Client~~~~0.0.1.0 `
/capabilityname:XPS.Viewer~~~~0.0.1.0
# This one is large, lets skip for now
#/capabilityname:Analog.Holographic.Desktop~~~~0.0.1.0 `
# Copy language caps to the repo
Copy-Item -Path $OS_LP_PATH -Destination $REPO_PATH -Force -ErrorAction stop | Out-Null
# Dismount OS image
Dismount-WindowsImage -Path $MAIN_OS_MOUNT -Discard -ErrorAction ignore | Out-Null
# Dismount ISO images
Write-Host "Dismounting ISO images"
Dismount-DiskImage -ImagePath $LP_ISO_PATH -ErrorAction ignore | Out-Null
Dismount-DiskImage -ImagePath $FOD_ISO_PATH -ErrorAction ignore | Out-Null
在源作系统中保存可选内容
为了在源作系统中保存可选内容状态,我们创建一个自定义作脚本,以在作系统安装之前运行。 在此脚本中,我们将可选功能和语言资源保存到文件中。 我们还创建存储库的本地副本,其中仅包含基于源作系统上安装的语言所需的文件。 此作限制要复制的文件。
$OUTPUT_PATH = "C:\TEMP\"
$LOG_PATH = $OUTPUT_PATH + "log.txt"
$OUTPUT_PATH = "C:\TEMP\"
$LOG_PATH = $OUTPUT_PATH + "log.txt"
$LANG_PATH = $OUTPUT_PATH + "sourceLang.txt"
$CAP_PATH = $OUTPUT_PATH + "sourceCapability.txt"
$OSVERSION_PATH = $OUTPUT_PATH + "sourceVersion.txt"
$REPO_PATH = "Z:\Repo\"
$LOCAL_REPO_PATH = $OUTPUT_PATH + "Local_Repo\"
Function Get-TS { return "{0:HH:mm:ss}" -f (Get-Date) }
Function Log
{
param (
[Parameter(Mandatory=$True)]
[string]$MESSAGE
)
$M = "$(Get-TS): PreInstall: $MESSAGE"
Write-Host $M
Add-Content -Path $LOG_PATH -Value $M
}
Function IsLangFile
{
param (
[Parameter(Mandatory=$True)]
[string]$PATH
)
if (($PATH -match '[-_~]ar[-_~]') -or ($PATH -match '[-_~]bg[-_~]') -or ($PATH -match '[-_~]cs[-_~]') -or `
($PATH -match '[-_~]da[-_~]') -or ($PATH -match '[-_~]de[-_~]') -or ($PATH -match '[-_~]el[-_~]') -or `
($PATH -match '[-_~]en[-_~]') -or ($PATH -match '[-_~]es[-_~]') -or ($PATH -match '[-_~]et[-_~]') -or `
($PATH -match '[-_~]fi[-_~]') -or ($PATH -match '[-_~]fr[-_~]') -or ($PATH -match '[-_~]he[-_~]') -or `
($PATH -match '[-_~]hr[-_~]') -or ($PATH -match '[-_~]hu[-_~]') -or ($PATH -match '[-_~]it[-_~]') -or `
($PATH -match '[-_~]ja[-_~]') -or ($PATH -match '[-_~]ko[-_~]') -or ($PATH -match '[-_~]lt[-_~]') -or `
($PATH -match '[-_~]lv[-_~]') -or ($PATH -match '[-_~]nb[-_~]') -or ($PATH -match '[-_~]nl[-_~]') -or `
($PATH -match '[-_~]pl[-_~]') -or ($PATH -match '[-_~]pt[-_~]') -or ($PATH -match '[-_~]ro[-_~]') -or `
($PATH -match '[-_~]ru[-_~]') -or ($PATH -match '[-_~]sk[-_~]') -or ($PATH -match '[-_~]sl[-_~]') -or `
($PATH -match '[-_~]sv[-_~]') -or ($PATH -match '[-_~]th[-_~]') -or ($PATH -match '[-_~]tr[-_~]') -or `
($PATH -match '[-_~]uk[-_~]') -or ($PATH -match '[-_~]zh[-_~]') -or ($PATH -match '[-_~]sr[-_~]')) {
return $True
}
else {
return $False
}
}
# Remove the log
Remove-Item -Path $LOG_PATH -Force -ErrorAction ignore | Out-Null
Log "Starting"
# Remove state files, keep repo if it exists
Remove-Item -Path $LANG_PATH -Force -ErrorAction ignore | Out-Null
Remove-Item -Path $CAP_PATH -Force -ErrorAction ignore | Out-Null
Remove-Item -Path $OSVERSION_PATH -Force -ErrorAction ignore | Out-Null
# Get OS version, to use later for detecting compat scans versus OS installation
$OSINFO = Get-CimInstance Win32_OperatingSystem
Log "OS Version: $($OSINFO.Version)"
Add-Content -Path $OSVERSION_PATH -Value $OSINFO.Version
# Get installed languages from international settings
$INTL = DISM.exe /Online /Get-Intl /English
# Save only output lines with installed languages
$LANGUAGES = $INTL | Select-String -SimpleMatch 'Installed language(s)'
# Replace with null so we have a simple list of language codes
$LANGUAGES = $LANGUAGES | ForEach-Object {$_.Line.Replace("Installed language(s): ","")}
# Save System Language, save only output line with default system language
$SYSLANG = $INTL | Select-String -SimpleMatch 'Default system UI language'
# Replace with null so we have the language code
$SYSLANG = $SYSLANG | ForEach-Object {$_.Line.Replace("Default system UI language : ","")}
# Save these languages
Log "Default system UI language on source OS: $($SYSLANG)"
ForEach ($ITEM in $LANGUAGES) {
Log "Installed language on source OS: $($ITEM)"
Add-Content -Path $LANG_PATH -Value $ITEM
}
# Get and save installed packages, we'll use this for debugging
$PACKAGES = Get-WindowsPackage -Online
ForEach ($ITEM in $PACKAGES) {
if($ITEM.PackageState -eq "Installed") {
Log "Package $($ITEM.PackageName) is installed"
}
}
# Get and save capabilities
$CAPABILITIES = Get-WindowsCapability -Online
ForEach ($ITEM in $CAPABILITIES) {
if($ITEM.State -eq "Installed") {
Log "Capability $($ITEM.Name) is installed"
Add-Content -Path $CAP_PATH -Value $ITEM.Name
}
}
# Copy a subset of the Repo files locally, all neutral files and the languages needed
$REPO_FILES = Get-ChildItem $REPO_PATH -file -Recurse
ForEach ($FILE in $REPO_FILES) {
$PATH = ($FILE.DirectoryName + "\") -Replace [Regex]::Escape($REPO_PATH), $LOCAL_REPO_PATH
If (!(Test-Path $Path)) {
New-Item -ItemType Directory -Path $PATH -Force | Out-Null
}
If ((IsLangFile $FILE.Name)) {
# Only copy those files where we need the primary languages from the source OS
ForEach ($ITEM in $LANGUAGES) {
if ($FILE.Name -match $Item) {
If (!(Test-Path (Join-Path $Path $File.Name))) {
Copy-Item $FILE.FullName -Destination $PATH -Force
Log "Copied file $($FILE.FullName) to local repository"
}
else {
Log "File $($FILE.Name) already exists in local repository"
}
}
}
} Else {
# Copy all 'neutral files' and those language specific that are not in the core 38
If (!(Test-Path (Join-Path $Path $File.Name))) {
Copy-Item $FILE.FullName -Destination $PATH -Force
Log "Copied file $($FILE.FullName) to local repository"
}
else {
Log "File $($FILE.Name) already exists in local repository"
}
}
}
Log ("Exiting")
在目标作系统中添加可选内容
安装成功完成后,我们使用 success.cmd 从源作系统中检索可选内容状态,并仅在缺少该状态时才安装在新作系统中。 然后,应用最新的每月更新作为最后一步。
$OUTPUT_PATH = "C:\TEMP\"
$LOG_PATH = $OUTPUT_PATH + "log.txt"
$LANG_PATH = $OUTPUT_PATH + "sourceLang.txt"
$CAP_PATH = $OUTPUT_PATH + "sourceCapability.txt"
$OSVERSION_PATH = $OUTPUT_PATH + "sourceVersion.txt"
$LOCAL_REPO_PATH = $OUTPUT_PATH + "Local_Repo\"
$LCU_PATH = $OUTPUT_PATH + "Windows10.0-KB4565503-x64_PSFX.cab"
$PENDING = $false
Function Get-TS { return "{0:HH:mm:ss}" -f (Get-Date) }
Function Log
{
param (
[Parameter(Mandatory=$True)]
[string]$MESSAGE
)
$M = "$(Get-TS): PostInstall: $MESSAGE"
Write-Host $M
Add-Content -Path $LOG_PATH -Value $M
}
Log "Starting"
# Get OS version
$OSINFO = Get-CimInstance Win32_OperatingSystem
Log "OS Version: $($OSINFO.Version)"
# Check for source OS state, just to be sure
if (!(Test-Path $LANG_PATH) -or !(Test-Path $CAP_PATH) -or !(Test-Path $OSVERSION_PATH) ) {
Log "Source OS state is missing."
}
# If this script is executing and the OS version hasn't changed, let's exit out.
else {
# Retrive OS version from source OS
$SOURCE_OSVERSION = Get-Content -Path $OSVERSION_PATH
if ($OSINFO.Version -eq $SOURCE_OSVERSION) {
Log "OS Version hasn't changed."
}
else {
# Retrive language list from source OS
$SOURCE_LANGUAGES = Get-Content -Path $LANG_PATH
# Get installed languages from International Settings
$INTL = DISM.exe /Online /Get-Intl /English
# Save System Language, save only output line with default system language
$SYS_LANG = $INTL | Select-String -SimpleMatch 'Default system UI language'
# Replace with null so we have the language code
$SYS_LANG = $SYS_LANG | ForEach-Object {$_.Line.Replace("Default system UI language : ","")}
# Get and save installed packages, we'll use this for debugging
$PACKAGES = Get-WindowsPackage -Online
ForEach ($ITEM in $PACKAGES) {
if($ITEM.PackageState -eq "Installed") {
Log "Package $($ITEM.PackageName) is installed"
}
}
# Loop through source OS languages, and install if missing on target OS
ForEach ($SOURCE_ITEM in $SOURCE_LANGUAGES) {
if ($SOURCE_ITEM -ne $SYS_LANG) {
# add missing languages except the system language
Log "Adding language Microsoft-Windows-Client-Language-Pack_x64_$($SOURCE_ITEM).cab"
try {
Add-WindowsPackage -Online -PackagePath "$($LOCAL_REPO_PATH)\Microsoft-Windows-Client-Language-Pack_x64_$($SOURCE_ITEM).cab" -ErrorAction stop | Out-Null
}
catch {
Log $_.Exception.Message
}
}
}
# Retrieve capabilities from source OS and target OS
$SOURCE_CAPABILITIES = Get-Content -Path $CAP_PATH
$CAPABILITIES = Get-WindowsCapability -Online
# Loop through source OS capabilities, and install if missing on target OS
ForEach ($SOURCE_ITEM in $SOURCE_CAPABILITIES) {
$INSTALLED = $false
ForEach ($ITEM in $CAPABILITIES) {
if ($ITEM.Name -eq $($SOURCE_ITEM)) {
if ($ITEM.State -eq "Installed") {
$INSTALLED = $true
break
}
}
}
# Add if not already installed
if (!($INSTALLED)) {
Log "Adding capability $SOURCE_ITEM"
try {
Add-WindowsCapability -Online -Name $SOURCE_ITEM -Source $LOCAL_REPO_PATH -ErrorAction stop | Out-Null
}
catch {
Log $_.Exception.Message
}
}
else {
Log "Capability $SOURCE_ITEM is already installed"
}
}
# Add LCU, this is required after adding FODs and languages
Log ("Adding LCU")
Add-WindowsPackage -Online -PackagePath $LCU_PATH -NoRestart
# Get packages, we'll use this for debugging and to see if we need to restart to install
$PACKAGES = Get-WindowsPackage -Online
ForEach ($ITEM in $PACKAGES) {
Log "Package $($ITEM.PackageName) is $($ITEM.PackageState)"
if ($ITEM.PackageState -eq "InstallPending") {
$PENDING = $true
}
}
}
}
# Remove local repository and state files
Remove-Item -Path $LANG_PATH -Force -ErrorAction ignore | Out-Null
Remove-Item -Path $CAP_PATH -Force -ErrorAction ignore | Out-Null
Remove-Item -Path $OSVERSION_PATH -Force -ErrorAction ignore | Out-Null
Remove-Item -Path $LOCAL_REPO_PATH -Force -Recurse -ErrorAction ignore | Out-Null
# Restarting the computer to let setup process to exit cleanly
if ($PENDING) {
Log ("Install pending packages exists, restarting in 10 seconds")
Start-Process -FilePath cmd -ArgumentList "/C shutdown /r /t 10 /f"
}
Log ("Exiting")