环境

Windows Server 2012 Standard x64
Windows Server 2019 x64
Microsoft Deployment Toolkit 6.3.8456.1000
Windows 评估和部署工具包 Windows ADK 10.1.19041.1

测试机型

组装机 1 HDD
组装机 1 SSD + 1 HDD
戴尔 商用机 1 MS SSD + 1 HDD
戴尔 工作站 1 M2 SSD + 2 HDD
VMWare Workstation 17 虚拟机 2 SATA SSD
VMWare Workstation 17 虚拟机 1 M2 SSD + 1 SATA SSD
VMWare Workstation 17 虚拟机 2 M2 SSD + 1 SATA SSD
VMWare ESXi 6.7 U3 虚拟机 1 SAS SSD + 1 M2 SSD
VMWare ESXi 6.7 U3 虚拟机 2 SAS SSD + 1 M2 SSD

更新

2024-11-25

2024-11-21

  • 新增硬盘 SAS 种类支持,优先级(M2 SSD > SAS SSD > SATA SSD > HDD),自动选择最优硬盘为 OSDisk
  • 新增虚拟机支持(测试 Workstation 17,ESXi 6.7 U3)
  • 新增容量最优选择,将同样优先级情况下,将会设置容量最小的为 OSDisk

目的

实现 MDT 网络安装时,自动格式化所有硬盘,若有 SSD 固态硬盘,则自动部署/安装系统到 SSD 硬盘中,若有 M2,则优先安装到 M2,若有相同种类硬盘,则将系统优先安装到容量最小的硬盘当中。

优先级

  • SSD > HDD
  • M2 > SAS > SATA
  • 容量小的硬盘 > 容量大的硬盘

步骤

若不需要格式化所有硬盘,请前往我的 Github 主页,下载UserExit - AutoSelectOSDisk SSD M2 SAS SATA.vbs脚本代替UserExit01.vbs
理论仅支持 Windows 10 PE 以上。
Github 主页: https://github.com/Shankschn/MDT-Scripts
该脚本将会清理所有硬盘,并根据优先级选择最优硬盘进行安装操作系统。

以下自动UserExit - Auto SSD M2 SAS SATA.vbs作为UserExit01.vbs为例。

相关文件

UserExit01.vbs

点我展开、收缩

Function UserExit(sType, sWhen, sDetail, bSkip)
    oLogging.CreateEntry "entered UserExit ", LogTypeInfo
    UserExit=Success
End Function

Function SetOSDisk()
    Dim objShell, objFSO, objFile, scriptTmpFolder, strScriptFile, wmi
    Dim colDisks, objDisk, disks, disk, diskp1, diskp2, diskp3, d, e, f
    Dim diskid, objFile2

    Set objShell = CreateObject("WScript.Shell")
    Set objFSO = CreateObject("Scripting.FileSystemObject")
    scriptTmpFolder = "X:\Deploy\tmp"
    If Not objFSO.FolderExists(scriptTmpFolder) Then
        objFSO.CreateFolder(scriptTmpFolder)
    End If

    strScriptFile = scriptTmpFolder & "\CleanAllDisks.txt"
    Set objFile = objFSO.CreateTextFile(strScriptFile, True)
    Set wmi = GetObject("winmgmts:\\.\root\cimv2")
    Set colDisks = wmi.ExecQuery("Select * from Win32_DiskDrive")
    For Each objDisk In colDisks
        objFile.WriteLine("select disk " & objDisk.Index)
        objFile.WriteLine("clean")
    Next
    objFile.WriteLine("exit")
    objFile.Close

    checkErr = scriptTmpFolder & "\CheckErr.vbs"
    Set objFile2 = objFSO.CreateTextFile(checkErr, True)
    objFile2.WriteLine("Dim objShell, wmi, pl, p, pn, pnHas")
    objFile2.WriteLine("pn = ""TsProgressUI.exe""")
    objFile2.WriteLine("pnHas = False")
    objFile2.WriteLine("Set wmi = GetObject(""winmgmts:\\.\root\cimv2"")")
    objFile2.WriteLine("For i = 1 To 30")
    objFile2.WriteLine("    Set pl = wmi.ExecQuery(""SELECT * FROM Win32_Process WHERE Name = '"" & pn & ""'"")")
    objFile2.WriteLine("    If pl.Count > 0 Then")
    objFile2.WriteLine("        pnHas = True")
    objFile2.WriteLine("        Exit For")
    objFile2.WriteLine("    End If")
    objFile2.WriteLine("    WScript.Sleep 1000")
    objFile2.WriteLine("Next")
    objFile2.WriteLine("If Not pnHas Then")
    objFile2.WriteLine("    Set objShell = CreateObject(""WScript.Shell"")")
    objFile2.WriteLine("    objShell.Run ""wpeutil reboot"", 0, False")
    objFile2.WriteLine("End If")
    objFile2.Close
    objShell.Run "wscript.exe """ & checkErr & """", 0, False
    objShell.Run "diskpart /s " & strScriptFile, 1, True
    WScript.Sleep 3000

    set wmi=GetObject("Winmgmts:\\.\Root\Microsoft\Windows\Storage")
    set disks=wmi.Execquery("Select * from MSFT_PhysicalDisk")
    diskp1=0
    diskp2=0
    diskp3=999999
    for each d in disks
        if d.MediaType=4 then
            if diskp1=0 then
                diskp1=d.MediaType
            end if
            if d.BusType=17 then
                diskp2=d.BusType
                exit for
            elseif d.BusType=10 then
                if diskp2=0 or diskp2=11 then
                    diskp2=d.BusType
                end if
            elseif d.BusType=11 and diskp2=0 then
                diskp2=d.BusType
            end if
        end if
    next
    if diskp1=0 then
        for each e in disks
            if e.Size/1024/1024/1024<diskp3 then
                diskp3=e.Size/1024/1024/1024
                diskid=e.DeviceId
            end if
        next
    else
        for each f in disks
            if diskp1=f.MediaType and diskp2=f.BusType then
                if f.Size/1024/1024/1024<diskp3 then
                    diskp3=f.Size/1024/1024/1024
                    diskid=f.DeviceId
                end if
            end if
        next
    end if
    if diskid="" then
        diskid=0
    end if
    SetOSDisk=diskid
End Function

FormatOtherDisks.ps1

点我展开、收缩

Get-WmiObject -Class Win32_Volume -Filter "DriveType=5 and DriveLetter='D:'" |Select-Object -First 1 |Set-WmiInstance -Arguments @{DriveLetter="R:"}
Get-Disk |Where-Object PartitionStyle -eq 'RAW' |Initialize-Disk -PassThru |New-Partition -UseMaximumSize |Format-Volume -FileSystem NTFS -Confirm:$false
$tmp1 = Get-Partition | Where-Object {-not $_.DriveLetter -and $($_.size/1024/1024/1024) -gt 30}
foreach ($tmp2 in $tmp1) {
    $tmp3 = Get-Volume | Where-Object {$_.DriveLetter -ne "R" -and -not -not $_.DriveLetter} |Sort-Object DriveLetter |Select-Object -Last 1
    $tmp4 = [char]([int][char]$tmp3.DriveLetter + 1)
    Set-Partition -DiskNumber $tmp2.DiskNumber -PartitionNumber $tmp2.PartitionNumber -NewDriveLetter $tmp4
    Start-Sleep -Seconds 1
}

配置 Deployment Share

上传脚本 UserExit01.vbs 与 FormatOtherDisks.ps1 到项目中的 Scripts 目录(默认为:C:\DeploymentShare\Scripts)中。
编辑项目 Rule,在相关设置中配置如下内容,其他配置均省略。

[Settings]
Priority=Defatult

[Default]
OSInstall=Y
UserExit=UserExit01.vbs
OSDDiskIndex=#SetOSDisk()#
...

编辑 Winidows PE,选择 Platform x64。
点击 Feaatures,勾选 Storage Management Cmdlets(重要),Microsoft Data Access Components (MDAC/ADO) support,.NET Framework,Windows PowerShell(重要)。 由于原本就勾了一些,至于其他是不是必须的...懒得测试了...。

配置 Task Sequences 中的 Task Sequence

配置 FormatOtherDisk.ps1,若使用 State Restore,则可以在该 Group 下的 CustomTasks 中,添加 General 中 Run PowerShell Script。

  • Name:Format Other Disks
  • PowerShell script:%SCRIPTROOT%\FormatOtherDisks.ps1

若未使用 State Restore,可在 Task Sequence 的最后,以上方方式添加。

Update Deployment Share

配置完所有步骤后,应用,并确认,Update Deployment Share,第一次建议使用Completely regenerate the boot images,一直下一步即可。

配置 MDS

在 MDS Windows 部署服务管理器 -> 启动映像中:
1.禁用原启动镜像(默认名:Lite Touch Windows PE (x64))
2.添加新启动镜像:Deployment Share 工程目录目录下的 boot 文件中,应该会有一个现在时间点生成的LiteTouchPE_x64.wim文件,添加它即可。
最后,重启启动 WDS 服务即可。

相关报错

格式化并分区硬盘步骤成功,但是 MDT 设置的系统启动分区盘符与 MDT 部署时实际系统分区盘符不符,出现此错误。

could not find ccm install folder. don't use ccmerrors.dll

格式化并分区硬盘步骤失败/被跳过,出现错误,检查日志,排查为什么失败。

x:\windows\temp\deployment scripts\wizard.hta

参考

www.cnblogs.com/dreamer-fish/p/13175537.html
www.deploymentresearch.com/creating-custom-variables-in-mdt-2013/
social.technet.microsoft.com/Forums/en-US/56723290-c78c-4083-af92-bd6294f425ab/using-custom-properties-in-task-sequence-conditional-statement?forum=mdt
social.technet.microsoft.com/Forums/en-US/f32c9757-d49c-4bd8-b496-8904ff04d12b/priority-properties-and-userexit-script?forum=mdt
docs.microsoft.com/en-us/previous-versions/windows/desktop/stormgmt/msft-physicaldisk
www.deploymentresearch.com/mdt-2013-lite-touch-driver-management/
docs.microsoft.com/en-us/mem/configmgr/osd/understand/using-task-sequence-variables
docs.microsoft.com/zh-cn/windows/deployment/deploy-windows-mdt/configure-mdt-for-userexit-scripts
docs.microsoft.com/en-us/windows/win32/wmisdk/wmi-tasks--disks-and-file-systems
social.technet.microsoft.com/Forums/en-US/e57b2c8d-a0d8-4e5b-b42a-287415f07c93/mdt-2010-with-multiple-drives?forum=mdt
docs.microsoft.com/en-us/mem/configmgr/mdt/samples-guide#deploying-the-correct-device-drivers-to-computers-with-the-same-hardware-devices-but-different-make-and-model
social.technet.microsoft.com/Forums/en-US/bd72de95-2ce3-41fa-ac4a-1ca9693f2d00/multiple-userexit-scripts-built-into-default?forum=mdt
social.technet.microsoft.com/Forums/en-US/f497a85a-2423-4fb1-9252-1d602ed3ad9f/how-to-set-up-multiple-hard-disks?forum=mdt
superuser.com/questions/1073817/how-to-detect-identify-m-2-ssd
docs.microsoft.com/en-us/previous-versions/windows/desktop/stormgmt/msft-disk?redirectedfrom=MSDN

最后修改:2024 年 11 月 26 日 09 : 46 PM
如果觉得文章帮助了您,您可以随意赞赏。