ZTISelectBootDisk.wsf new with BusType

Several years ago I wrote a script to help select which disk to deploy Windows to during your MDT LiteTouch or ZeroTouch task sequence.

https://keithga.wordpress.com/2013/09/18/ztiselectbootdisk-wsf/

Well, based on a request from my latest client, I have created a similar script that support BusType.

BackGround

My client is trying to install Windows Server 2016 on a Server with a SAN. When the machine boots to WinPE, one of the SAN drives appears *first* as Disk 0 (Zero). By default MDT Task Sequences will deploy to Disk Zero! My ZTISelectBootDisk.wsf already shows how to override. All we need to do is to find a way to tell MDT which disk to choose based on the correct WMI query.

Turns out it was harder than I thought.

What we wanted was the BusType that appears in the “Type” field when you type “Select Disk X” and then “detail disk” in Diskpart.exe.  When we ran “Detail Disk” in DIskpart.exe we could see the bus type: Fibre as compared to regular disks like SCSI or SAS.

The challenge was that the regular Win32_diskDrive WMI query wasn’t returning the BusType value, and we couldn’t figure out how to get that data through other queries.

I tried running some PowerShell queries like ‘Get-Disk’ and noticed that the output type was MSFT_Disk, from a weird WMI Namespace: root\microsoft\windows\storage. But adding that query to the script works! Yea!!!

BusType

What kind of BusTypes are there?

Name Value Meaning
Unknown 0 The bus type is unknown.
SCSI 1 SCSI
ATAPI 2 ATAPI
ATA 3 ATA
1394 4 IEEE 1394
SSA 5 SSA
Fibre Channel 6 Fibre Channel
USB 7 USB
RAID 8 RAID
iSCSI 9 iSCSI
SAS 10 Serial Attached SCSI (SAS)
SATA 11 Serial ATA (SATA)
SD 12 Secure Digital (SD)
MMC 13 Multimedia Card (MMC)
Virtual 14 This value is reserved for system use.
File Backed Virtual  15 File-Backed Virtual
Storage Spaces  16 Storage spaces
NVMe 17 NVMe

For this script we are *excluding* the following devices:

Name Value Meaning
Fibre Channel 6 Fibre Channel
iSCSI 9 iSCSI
Storage Spaces  16 Storage spaces
NVMe 17 NVMe

Meaning that the *FIRST* fixed device not in this list will become the new *Target* OS Disk. Run this query on your machine to see what disk will become the target:

gwmi -namespace root\microsoft\windows\storage -query 'select Number,Size,BusType,Model from MSFT_Disk where BusType <> 6 and BusTy
pe <> 9 and BusType <> 16 and BusType <> 17' | Select -first 1

Requirements

Reminder that this script requires MDT (latest), and the script should be placed in the %DeploymentShare%\Scripts folder. Additionally you should install all the Storage packages for WinPE, sorry I don’t recall *which* packages I selected when I did testing.

Script

<job id="ZTISelectBootDisk">
<script language="VBScript" src="ZTIUtility.vbs"/>
<script language="VBScript" src="ZTIDiskUtility.vbs"/>
<script language="VBScript">
' // ***************************************************************************
' //
' // Copyright (c) Microsoft Corporation. All rights reserved.
' //
' // Microsoft Deployment Toolkit Solution Accelerator
' //
' // File: ZTISelectBootDisk.wsf
' //
' // Version: <VERSION>
' //
' // Purpose: Given a collection of Storage Devices on a machine,
' // this program will assist in finding the correct
' // device to be processed by "ZTIDiskPart.wsf"
' //
' // Currently hard coded to select the *FIRST* drive that is
' // Not iSCSI, Fibre Channel, Storage Spaces, nor NVMe.
' //
' // REQUIRES that you install the correct WinPE Storage Components!
' //
' //
' // WARNING: If there are any *other* disks that need to be Cleaned
' // and formatted, they should be processed first.
' // And this the global Variable OSDDiskIndex should be
' // set to <blank> when done being processed by ZTIDiskPart.wsf.
' //
' // Variables:
' // OSDDiskIndex [ Output ] – Disk Index
' //
' // Usage:
' // cscript.exe [//nologo] ZTISelectBootDisk.wsf [/debug:true]
' // cscript.exe [//nologo] ZTIDiskPart.wsf [/debug:true]
' // cscript.exe [//nologo] ZTISetVariable.wsf [/debug:true] /OSDDiskIndex:""
' //
' // ***************************************************************************
Option Explicit
RunNewInstance
'//—————————————————————————-
'// Main Class
'//—————————————————————————-
Class ZTISelectBootDisk
'//—————————————————————————-
'// Main routine
'//—————————————————————————-
Function Main
Dim oWMIDisk
Dim bFound
Dim oDiskPartBoot
Dim oContext, oLocator, objQuery, objStorageWMI, objStorage
oLogging.CreateEntry "—————- Initialization —————-", LogTypeInfo
IF oEnvironment.Item("DEPLOYMENTTYPE") <> "NEWCOMPUTER" Then
oLogging.ReportFailure "Not a new computer scenario, exiting Select Boot Disk.", 7700
End If
bFound = FAILURE
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'
' 1st Pass – Find any disk that matches the Query "Select * From Win32_diskPartition %OSBootDiskOverrideWQL%"
'
Set oContext = CreateObject("WbemScripting.SWbemNamedValueSet")
oContext.Add "__ProviderArchitecture", 64
Set oLocator = CreateObject("Wbemscripting.SWbemLocator")
set objStorageWMI = oLocator.ConnectServer("","root\Microsoft\Windows\Storage","","",,,,oContext)
set objQuery = objStorageWMI.ExecQuery("select Number,Size,BusType,Model from MSFT_Disk where BusType <> 6 and BusType <> 9 and BusType <> 16 and BusType <> 17")
If objQuery.Count = 0 then
oLogging.CreateEntry "No Disk Drives Found!?!?! Dude, did you install the right storage drivers into WinPE 0x7b.",LogTypeError
exit function
End if
For each objStorage in objQuery
oLogging.CreateEntry "Found Device: N:" & ObjStorage.Number & " S:" & ObjStorage.Size & " M:" & ObjStorage.Model & " T:" & ObjStorage.BusType & " " , LogTypeInfo
oEnvironment.Item("OSDDiskIndex") = ObjStorage.Number
bFound = SUCCESS
exit for
Next
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'
' 2nd pass – Use the 1st Partition larger than 15GB on the first disk with a bootable partition.
'
If bFound = FAILURE then
oLogging.CreateEntry "No drive was found using search parameters, Use the 1st \Windows Partition found.", LogTypeInfo
set oDiskPartBoot = GetBootDriveEx( false, oEnvironment.Item("ImageBuild"), false )
If not oDiskPartBoot is nothing then
oEnvironment.Item("OSDDiskIndex") = oDiskPartBoot.Disk
bFound = SUCCESS
End if
End if
TestAndLog bFound = SUCCESS, "Verify OSDDiskIndex was found and set: " & oEnvironment.Item("OSDDiskIndex")
Main = bFound
End Function
End class
</script>
</job>

-k

 

 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s