upload successful

前两周有个 EPM 实施项目,客户是在厦门那边,我本以为过去一周内可以解决回来,没想到在操作系统部署这块踩了超多坑,最后待了两周才解决,这里记录一下

# 无 DHCP 服务器

上来面对的第一个坑就是客户端环境中没有 DHCP 服务器,所有的客户端都需要手动配置 IP 地址

正常情况下,操作系统部署是通过 PXE 网络引导加载 WinPE , 然后在 WinPE 中跟服务器建立通信,读取服务器上的部署模板信息

在没有 DHCP 的情况下根本无法从网络中加载 WinPE , 那就只能在服务器上生成 WinPE ISO 镜像,通过刻录软件将其刻录到 U 盘,然后用 U 盘引导进入 WinPE 环境

# 修改 boot.wim 文件

在创建 WinPE 镜像之前,我们需要挂载 WinPE 文件,添加中文字体,让其支持中文显示,否则部署模板中的中文会显示乱码,并且修改 startnet.cmd 文件,让 WinPE 初始化的时候可以手动配置 IP 地址

WinPE 文件默认路径为 C:\Program Files\LANDesk\ManagementSuite\LANDesk\vboot 下的 boot.wimboot_x64.wim , 其中 boot.wim 为 32 位 BIOS 引导文件, boot_x64.wimUEFI 64 位引导文件

我们先修改第一个 boot.wim 文件,以管理员权限打开 cmd 命令行

  1. 创建一个空目录用于挂载 WIM 文件
l
mkdir c:\mount

upload successful

  1. 挂载 boot.wim 到 c:\mount 目录
l
DISM.exe /mount-wim /wimfile:"C:\Program Files\LANDesk\ManagementSuite\LANDesk\vboot\boot.wim" /index:1 /mountdir:C:\mount

upload successful

  1. 修改 WinPE 初始化脚本

编辑 C:\mount\Windows\System32\startnet.cmd 脚本文件,在 @echo off 后面插入静态 IP 配置命令

l
echo.
echo       If using static ip,press 1
echo       If using DHCP,press 2
echo       If exit,press 3
echo.
set /p choice=      your choice:
echo.
if "%choice%"=="1" goto ip1
if "%choice%"=="2" goto ip2
if "%choice%"=="3" goto end
goto end
:ip1
netsh interface show interface
echo.
set /p name=	please enter your NIC name:
set /p ldip=      please enter your static ip address:
set /p ldmask=      please enter your netmask:
set /p ldgw=      please enter your gateway:
echo.
echo  IP config starting....
echo.
echo  starting config ip and gateway
netsh interface ip set address name=%name% source=static addr=%ldip% mask=%ldmask% gateway=%ldgw%
echo  config success!
goto end
:ip2
echo  IP auto config start....
echo.
netsh interface ip set address name = %name% source = dhcp
echo  starting DNS....
netsh interface ip set dns name = %name% source = dhcp 
echo  config success!
:end

upload successful

  1. 添加 hosts 文件解析

为了减少用户的操作,上面的启动脚本我没有添加配置 DNS 的命令,而是直接将 EPM 服务器的解析记录添加到 WinPEhosts 文件进行解析

notepad 打开 C:\mount\Windows\System32\drivers\etc\hosts 添加服务器解析记录

upload successful

  1. 添加中文包

WinPE 默认是不支持中文的,如果部署模板中有中文字符会变成乱码,根据当前 WinPE 的版本下载对应的 ADK 安装到电脑中,执行下面的命令添加中文语言包

l
DISM.exe  /Add-Package /Image:C:\mount /PackagePath:"C:\Program Files (x86)\Windows Kits\10\Assessment and Deployment Kit\Windows Preinstallation Environment\x86\WinPE_OCs\WinPE-FontSupport-ZH-CN.cab"
DISM.exe /Add-Package /Image:C:\mount /PackagePath:"C:\Program Files (x86)\Windows Kits\10\Assessment and Deployment Kit\Windows Preinstallation Environment\x86\WinPE_OCs\zh-cn\lp.cab"
Dism.exe /image:C:\mount /Get-Intl
Dism.exe /image:C:\mount /Set-UILang:ZH-CN
Dism.exe /image:C:\mount /Set-AllIntl:ZH-CN

upload successful

  1. 保存镜像

完成上面的步骤后,关闭任何已打开的镜像相关文件包括目录,否则保存时会无法完全卸载挂载目录

l
Dism.exe /unmount-Wim /MountDir:c:\mount /Commit

upload successful

卸载后重复上面的 2 - 6 的操作,将第 2 歩的挂载镜像改成 boot_x64, 第 5 步的中文包路径又 x86 改成 amd64

l
DISM.exe /mount-wim /wimfile:"C:\Program Files\LANDesk\ManagementSuite\LANDesk\vboot\boot_x64.wim" /index:1 /mountdir:C:\mount
DISM.exe  /Add-Package /Image:C:\mount /PackagePath:"C:\Program Files (x86)\Windows Kits\10\Assessment and Deployment Kit\Windows Preinstallation Environment\amd64\WinPE_OCs\WinPE-FontSupport-ZH-CN.cab"
DISM.exe /Add-Package /Image:C:\mount /PackagePath:"C:\Program Files (x86)\Windows Kits\10\Assessment and Deployment Kit\Windows Preinstallation Environment\amd64\WinPE_OCs\zh-cn\lp.cab"

# 生成 ISO 镜像

修改好 WinPE 文件后,返回控制台,在操作系统部署这里创建一个镜像文件

upload successful

创建好后用刻录软件将镜像文件写入到优盘,我这里为了方便演示就直接用虚拟机光驱加载镜像模拟优盘启动,测试该镜像是否能够在没有 DHCP 的环境下正常工作

开机进入引导菜单,选择 WinPE 的启动设备

upload successful

进入初始化界面,选择 1 使用静态 IP,这里会列出所有网卡接口的信息,由用户输入对应的网卡接口名称进行配置

upload successful

配置好 IP 地址信号后回车,如果网络能够正常跟服务器通信,此时便能看到部署程序

upload successful

这里弹出需要身份认证,后续可以取消掉,先输入核心服务器的管理员账号密码登录

upload successful

登录后弹出部署模板选择,但是目前我并没有配置部署模板,所以这里没有模板

目前看来 WinPE 跟核心服务器通信是正常的,我们先返回核心服务器配置部署模板

# 模板部署

在控制台操作系统部署界面选择 Preboot > PXE Boot Options , 勾选上 Allow anonymous login for public templates , 这样下次我们在 WinPE 进入模板选择的界面就不需要身份认证了

upload successful

需要注意的是,需要将部署模板创建在 Public 分组才能让匿名用户查看并选择部署

  1. 由于用户希望部署时能够自动分配计算机名,这里需要添加设备名称规则,使用 LD+Mac 地址 确保设备名称的唯一性

upload successful

  1. 编写分区脚本,由于用户目前还有 Windows 7 系统,所以需要写一个 GPT 分区脚本和一个 MBR 分区脚本
  • GPT
l
rem == CreatePartitions-UEFI ==
rem == These commands are used with DiskPart to
rem create five partitions
rem for a UEFI/GPT-based PC.
rem Adjust the partition sizes to fill the drive
rem as necessary. ==
select disk 0
clean
convert gpt
rem == 1. Windows RE tools partition ===============
rem create partition primary size=900
rem format quick fs=ntfs label="Windows RE tools"
rem assign letter="T"
rem set id="de94bba4-06d1-4d40-a16a-bfd50179d6ac"
rem gpt attributes=0x8000000000000001
rem == 2. System partition =========================
create partition efi size=260
rem NOTE: For Advanced Format 4Kn drives,
rem change this value to size = 260
format quick fs=fat32 label="System"
assign letter="S"
rem == 3. Microsoft Reserved (MSR) partition =======
create partition msr size=128
rem == 4. Windows partition ========================
rem == a. Create the Windows partition size=102407(100GB) ==========
create partition primary size=102407
rem == c. Prepare the Windows partition =========
format quick fs=ntfs label="Windows"
assign letter="C"
rem === 5. User data partition ================
create partition primary size=210000
rem Use all remaining space to create user data partition===
format quick fs=ntfs label="Data"
assign letter="D"
rem === 5. User document partition ================
create partition primary
rem Use all remaining space to create user data partition===
format quick fs=ntfs label="Document"
assign letter="E"
list volume
exit
  • MBR
l
select disk 0
clean
convert mbr
create partition primary size=100000
format fs=ntfs quick label="Windows"
assign letter="C"
create partition primary size=200000
format fs=ntfs quick label="Data"
assign letter="D"
create partition primary
format fs=ntfs quick label="Document"
assign letter="E"
list volume
exit
  1. 将相关脚本、镜像、部署工具、软件包放到共享目录

upload successful

  1. 创建部署模板

upload successful

  1. 开始测试

客户端开机进入 WinPE 环境

a. 选择部署模板

upload successful

b. 部署执行阶段

upload successful

c. 部署完成

安装完操作系统后重启会自动执行后续动作

upload successful

# 问题总结

  1. DHCPless

第一次接触无 DHCP 的环境,刚开始毫无思绪,因为之前客户操作系统部署都是通过网络 PXE 引导部署,我知道可以通过控制台生成 ISO 镜像刻录到优盘,由优盘启动可以不需要 PXEDHCP ,但是我们的 WinPE 不像网络上的第三方 WinPE 那样具备有图形化界面,所以我不知道在进入 PE 环境后如何给当前系统配置一个 IP 地址

后来问了群里的一些大佬,得知 WinPE 进入系统后默认执行 c:\windows\system32\startnet.cmd 进行初始化,可以通过修改这个脚本预先配置好 IP 信息,最终通过添加 netsh 命令解决这个问题

  1. 磁盘分区

一开始我用系统自带的分区模板进行分区测试,发现不是很好用,在创建第二个分区的时候很容易报错,我对自带的分区模板一些字段定义也不是了解,在官网也找不到相关的文档可以用于参考

upload successful

最终决定用 diskpart 命令进行分区

upload successful

  1. Win7 UEFI 引导

这个是最让我最奔溃的问题,用户主要的用的操作系统是 Win7 , 但是他们购买的新机器不支持 Legacy 引导,只能以 UEFI 方式引导,硬件上已经完全不支持 Win7

我尝试过从网上下载很多标题注明支持新机器的 Win7 镜像,并且自己也尝试封装了几个镜像,但是都有着各种各样的问题

  •   a. 安装完操作系统重启后不认盘
  •   b. 安装完操作系统重启后一直卡在 Windows Logo
  •   c. 安装完操作系统后进入登录界面,键盘鼠标无法使用
  •   d. 能够正常安装系统并进入到桌面,但是在安装完软件后执行 sysprep 进行二次封装,再部署又会出现卡 logo 的现象

最终为了进度,我只能跟用户商量如果新机器要安装 Win7 ,就不能用 EPM 的部署方式,可以用网络上第三方 WinPE 系统进行安装,因为第三方 WinPE 可以解决 Win7Logo 这个问题

upload successful

  1. 多硬盘如何区分系统盘

这个问题最终也没有办法完美解决,多硬盘的情况下,比较理想的是判断分区中是否存在 Windows 目录,如果有则认为是系统盘

但是实际上会有很多其它的情况,下面列出我当前已经遇到的情况:

  • a. 用户之前的电脑是单硬盘,并且存在系统,后面加装了一个硬盘,但是前面的系统盘并没有格式化,就会出现一个以上分区存在 Windows 目录
  • b. 系统盘损坏或被格式化,所有分区下都找不到 Windows 目录
  • c. 后续新增硬盘,以新硬盘为系统盘,一般情况下新硬盘可能连格式化的步骤都没有做,连分区都没有,根本无法识别

最主要的是 WinPE 只支持少部分的 cmd 命令,不支持 Powershell , 所以真的很难用 cmd 脚本去做判断,只能说即使有想法也很难仅靠 cmd 命令实现

最终是给出两个部署模板,由用户自行选择

  • 一个是新硬盘部署,重新格式化并分区分配盘符,将操作系统安装在 C 盘

  • 一个是重装系统,重装系统分为 GPT 和 MBR 两个模板,固定第 0 个磁盘为系统盘,GPT 分区下格式化第三个分区,并分配 C 驱动器号,MBR 分区下格式化第一个分区,并分配 C 驱动器号


最后再吐槽一下,操作系统部署的实施真的很折磨人,本来整个部署流程顺利跑下来都需要一个多小时,遇到问题就得修改后重新跑一遍,我虽然没有统计自己跑了多少遍部署流程,但是肯定不少于 50 次

在测 Win7 的时候真的感觉人要奔溃,我大部分的时间都浪费在这上面,当时真的很希望能够有个人可以一起分析研究这个问题

哎,就酱吧,无力吐槽


# 最后更新

八月底又去了一趟客户现场,主要是上次六月份部署完后客户一直没有使用,现在基本上已经忘记了如何使用,而且客户对目前的操作系统部署方案也不是很满意,尤其是硬盘分区这一块,我本次过去就是重新教他们使用并尽可能的优化部署方案

# 磁盘分区

分区的问题我之前是用脚本去执行的,脚本执行就无法避免可能会分错区造成数据丢失,上一次过来的时候因为被 Win7 UEFI 引导的问题搞得我没法静下心来思考其它的事情,我也不知道当初为什么死磕脚本来完成这个分区动作

这次过来,我已经明白靠脚本是无法满足用户的需求,这种情况只能用图形化的分区工具让用户自行选择磁盘进行分区

我在服务器下载了 DiskGenius 并解压放到共享目录,在 PE 映射服务器的共享目录,执行 DiskGenius 可以正常跑起来,这样分区的问题就解决了

upload successful

不管用户有几个磁盘和分区,我只要求用户将需要安装操作系统的分区分配 C 盘符即可

现在回过头想想上次过来为什么会没有想到用图形化工具分区,真的被自己蠢哭了,看来人一着急就容易钻牛角尖

# 系统配置模板不生效

安装完操作系统第一次开机登录系统界面,连上网络后会自动执行系统配置后面的步骤,但是如果设备无法自动连接到网络,并且客户长时间没有操作导致设备进入休眠状态,唤醒后系统配置模板可能不会工作

正常情况下,在部署模板执行完 Configure Taget OS 便会自动重启 WinPE,进入操作系统安装配置步骤,要知道系统配置模板为什么不生效,就需要知道 Configure Taget OS 这一步具体做了什么事情

按照官方文档对 CTOS 的描述,执行 CTOS 步骤后会将后续需要的文件复制到客户端的 C:\ldprovisioning 目录,并在 %WINDIR%\Setup\Scripts\SetupComplete.cmd 脚本中调用 %WINDIR%\ldprovisioning\ldprovisioning.cmd, 下面简单描述一下 SetupComplete.cmdldprovisioning.cmd 这两个 CMD 批处理文件

# SetupComplete.cmd

SetupComplete.cmdWindows 操作系统安装结束后,用户登录到桌面的时候立即启动,该脚本以 system 权限执行

  • 执行顺序如下:
  1. 安装完 Windows 操作系统后,在显示登录屏幕显示之前,系统会在 %WINDIR%\Setup\Scripts 目录中搜索 SetupComplete.cmd

  2. 如果找到 SetupComplete.cmd 文件便会执行,并将执行操作记录在 %WINDIR%\Windows\Panther\UnattendGC\Setupact.log

  3. 设备在安装过程中加域,为了确保域策略不会干预脚本运行,在完成 SetupComplete.cmd 之前,域策略不会应用到于计算机

参考文档:https://learn.microsoft.com/zh-cn/windows-hardware/manufacture/desktop/add-a-custom-script-to-windows-setup?view=windows-10

# ldprovisioning.cmd

前面的 SetupComplete.cmd 脚本调用 ldprovisioning.cmd 后 , ldprovisioning.cmd 会安装基本的 Ivanti CBA 代理服务并启动

upload successful

启动代理服务后,客户端调用 C:\ldprovision\ldprovision.exe 程序向核心服务器报告 CTOS 步骤执行成功,接着继续执行后续部署模板

# 处理方法

知道 CTOS 的动作后事情便简单多了,已知 SetupComplete.cmd 在登录桌面时调用 ldprovisioning.cmd ,此时如果网络不通,则安装 Ivanti CBA 代理失败,客户端无法向服务器报告 CTOS 的状态,服务器的部署模板历史记录会一直停留在 CTOS ,另外, ldprovisioning.cmd 执行后会删除 C:\ldprovision 目录,这样用户就无法继续执行 ldprovisioning.cmd 安装 Ivanti CBA 代理

处理方案:

将客户端的 C:\ldprovision 目录文件拷贝到共享服务器,在系统安装模板中将共享服务器上的 ldprovision 目录复制到客户端上(不能放在系统盘根目录哦

这样后续无论是什么原因导致系统配置模板没有生效,用户都可以在联网状态下,手动将 ldprovision 目录复制到 %systemdrive% 根目录下执行 ldprovisioning.cmd 继续后面的部署模板

# 其它问题

还有其它一些小问题也一并帮用户优化了,例如修改系统启动等待时间、关闭 UAC、激活 Windows、驱动安装等,这里就不一一列举了,最终的部署效果用户还是很满意的

经过本次的项目实施,自己也收获了许多系统部署的经验,EPM 操作系统部署这块后续不会再更新了

✿✿ヽ (°▽°) ノ✿✿