修改MDT VBS腳本, 解決OSD識別Surface Pro 7+ 硬件類別出錯

微軟的MDT提供一個ZtiGather.wsf的tool來識別客戶端的系統類別。對應不一樣的系統類型,會生成對應的OSD系統變量,如服務器(IsServer),臺式機(IsDesktop),筆記本(IsLaptop)。windows

這個變量對於咱們部署app來講是很方便的,能夠在一個task sequence裏安裝各個硬件類型的app,而不用爲每一個硬件類型都建立1個task sequence,簡化工做量,也簡化了維護的複雜度。服務器

好比,咱們能夠設置Laptop類型的機器安裝***軟件,而服務器和臺式機類型不用安裝,就能夠設置***安裝的條件爲IsLaptop = True.app

這個功能的實現是根據讀取WMI的ChassiType來實現的, 具體的配置和值以下。ide

  • Other (1)wordpress

  • Unknown (2)函數

  • Desktop (3)ui

  • Low Profile Desktop (4)spa

  • Pizza Box (5)3d

  • Mini Tower (6)orm

  • Tower (7)

  • Portable (8)

  • Laptop (9)

  • Notebook (10)

  • Hand Held (11)

  • Docking Station (12)

  • All in One (13)

  • Sub Notebook (14)

  • Space-Saving (15)

  • Lunch Box (16)

  • Main System Chassis (17)

  • Expansion Chassis (18)

  • SubChassis (19)

  • Bus Expansion Chassis (20)

  • Peripheral Chassis (21)

  • Storage Chassis (22)

  • Rack Mount Chassis (23)

  • Sealed-Case PC (24)

  • Tablet (30)

  • Convertible (31)

  • Detachable (32)

https://docs.microsoft.com/en-us/windows/win32/cimwin32prov/win32-systemenclosure

經過檢測,咱們能夠看到ChassisTypes的值爲1,根據上表,1 表明Other,和VM同樣,因此當Surface Pro 7+作image的時候,OSD不認爲機器類型是Laptop,IsLaptop變量值爲false,帶來的結果就是全部筆記本須要安裝的app都不會安裝。

根據和微軟售後的確認,這個設置應該是個Bug,後面出的機器可能會修復這個問題,但是遠水救不了近渴。

image (9).png

那麼咱們能夠本身解決麼?答案是確定的。

既然咱們已經知道MDT是經過ZtiGather這個腳原本識別機器類型的, 那咱們能夠嘗試修改他識別的那個函數部分來修正這個問題。

找到GetAssetInfo()這個函數,替換爲下面的部分,變動後的邏輯簡單來講就根據WMI的Model信息來判斷Surface Pro系列的機器類型,而不看ChassisType值了。

	'//---------------------------------------------------------------------------
	'//  Function:	GetAssetInfo()
	'//  Purpose:	Get asset information using WMI
	'//---------------------------------------------------------------------------
	Function GetAssetInfo

	 	Dim bIsLaptop, bIsDesktop, bIsServer, bOnBattery, bFoundBattery, bFoundAC
		Dim sAssetTag, sSerialNumber, sMake, sModel, sProduct, sUUID, sMemory, sArchitecture, sProcessorSpeed, sCapableArchitecture

		Dim objResults, objInstance
		Dim i
		Dim bisX64, bIsUEFI, bSupportsSLAT, bSupportsX64, bSupportsX86


		oLogging.CreateEntry "Getting asset info", LogTypeInfo


		' Get the SMBIOS asset tag from the Win32_SystemEnclosure class

		Set objResults = objWMI.InstancesOf("Win32_SystemEnclosure")
		bIsLaptop = false
		bIsDesktop = false
		bIsServer = false
		For each objInstance in objResults

			If objInstance.ChassisTypes(0) = 12 or objInstance.ChassisTypes(0) = 21 then
				' Ignore docking stations
			Else

				If not IsNull(objInstance.SMBIOSAssetTag) then
					sAssetTag = Trim(objInstance.SMBIOSAssetTag)
				End if
				Select Case objInstance.ChassisTypes(0)
				Case "8", "9", "10", "11", "12", "14", "18", "21", "17", "32" 	'Added Chassis Type 17 for Surface Pro , also added Chassis Type 32 for Latitude 5285
					bIsLaptop = true
				Case "3", "4", "5", "6", "7", "15", "16", "13" ' Added Chassis Type 13 for AIO models
					bIsDesktop = true
				Case "23"
					bIsServer = true
				Case Else
					' Do nothing
				End Select

			End if

		Next
		If sAssetTag = "" then
			oLogging.CreateEntry "Unable to determine asset tag via WMI.", LogTypeInfo
		End if


		' Get the serial number from the Win32_BIOS class.

		Set objResults = objWMI.InstancesOf("Win32_BIOS")
		For each objInstance in objResults

	                ' Get the serial number

			If not IsNull(objInstance.SerialNumber) then
				sSerialNumber = Trim(objInstance.SerialNumber)
			End if

		Next
		If sSerialNumber = "" then
			oLogging.CreateEntry "Unable to determine serial number via WMI.", LogTypeInfo
		End if


		' Figure out the architecture from the environment

		If oEnv("PROCESSOR_ARCHITEW6432") <> "" then
			If UCase(oEnv("PROCESSOR_ARCHITEW6432")) = "AMD64" then
				sArchitecture = "X64"
			Else
				sArchitecture = UCase(oEnv("PROCESSOR_ARCHITEW6432"))
			End if
		ElseIf UCase(oEnv("PROCESSOR_ARCHITECTURE")) = "AMD64" then
			sArchitecture = "X64"
		Else
			sArchitecture = UCase(oEnv("PROCESSOR_ARCHITECTURE"))
		End if
		
		

		' Get the processor speed from the Win32_Processor class.

		bSupportsX86 = false
		bSupportsX64 = false
		bSupportsSLAT = false
		Set objResults = objWMI.InstancesOf("Win32_Processor")
		For each objInstance in objResults

			' Get the processor speed

			If not IsNull(objInstance.MaxClockSpeed) then
				sProcessorSpeed = Trim(objInstance.MaxClockSpeed)
			End if


			' Determine if the machine supports SLAT (only supported with Windows 8)

			On Error Resume Next
			bSupportsSLAT = objInstance.SecondLevelAddressTranslationExtensions
			On Error Goto 0
			

			' Get the capable architecture

			If not IsNull(objInstance.Architecture) then
				Select Case objInstance.Architecture
				Case 0
			
					' If the processor is running a x86 OS, then there is *Still* the possibility that it can 
					' support a x64 OS. We need to run a quick processor check to see if it supports x64.

					bisX64 = FALSE
					On Error Resume Next
					bisX64 = oUtility.BDDUtility.Is64Bit
					On Error Goto 0

					If bisX64 = TRUE then
						sCapableArchitecture = "AMD64 X64 X86"
						bSupportsX86 = true
						bSupportsX64 = true
					Else
						sCapableArchitecture = "X86"
						bSupportsX86 = true
					End if

				Case 6
					sCapableArchitecture = "IA64"
				Case 9
					sCapableArchitecture = "AMD64 X64 X86"
					bSupportsX86 = true
					bSupportsX64 = true
				Case Else
					SCapableArchitecture = "Unknown"
				End Select
			End if


			' Stop after first processor since all should match

			Exit For

		Next
		If sProcessorSpeed = "" then
			oLogging.CreateEntry "Unable to determine processor speed via WMI.", LogTypeInfo
		End if
		If sCapableArchitecture = "" then
			oLogging.CreateEntry "Unable to determine capable architecture via WMI.", LogTypeInfo
		End if


		' Get the make, model, and memory from the Win32_ComputerSystem class

		Set objResults = objWMI.InstancesOf("Win32_ComputerSystem")
		For each objInstance in objResults

			If not IsNull(objInstance.Manufacturer) then
				sMake = Trim(objInstance.Manufacturer)
			End if
			If not IsNull(objInstance.Model) then
				sModel = Trim(objInstance.Model)
			End if
			If not IsNull(objInstance.TotalPhysicalMemory) then
				sMemory = Trim(Int(objInstance.TotalPhysicalMemory / 1024 / 1024))
			End if

		Next
		If sMake = "" then
			oLogging.CreateEntry "Unable to determine make via WMI.", LogTypeInfo
		End if
		If sModel = "" then
			oLogging.CreateEntry "Unable to determine model via WMI.", LogTypeInfo
		End If


		' Get the Lenovo Model Version from the Win32_ComputerSystemProduct class
		' http://smulpuru.wordpress.com/2011/02/16/mdt-custom-variable-for-lenovo-model-drivergroup/
		' Added 10/08/2013 - dhedges
		
		'If sMake = "LENOVO" Then
			'Set objResults = objWMI.InstancesOf("Win32_ComputerSystemProduct")
			'For Each objInstance In objResults
				'sLenovoModel = objInstance.Version
			'Next
			'If sLenovoModel = "" Then
				'sLenovoModel = Null
				'oLogging.CreateEntry "Unable to determine LenovoModel tag via WMI", LogTypeInfo
			'End If
		'End If

		' Get the UUID from the Win32_ComputerSystemProduct class

		Set objResults = objWMI.InstancesOf("Win32_ComputerSystemProduct")
		For each objInstance in objResults

			If not IsNull(objInstance.UUID) then
				sUUID = Trim(objInstance.UUID)
			End if

		Next
		If sUUID = "" then
			oLogging.CreateEntry "Unable to determine UUID via WMI.", LogTypeInfo
		End if


		' Get the product from the Win32_BaseBoard class

		Set objResults = objWMI.InstancesOf("Win32_BaseBoard")
		For each objInstance in objResults

			If not IsNull(objInstance.Product) then
				sProduct = Trim(objInstance.Product)
			End if

		Next
		If sProduct = "" then
			oLogging.CreateEntry "Unable to determine product via WMI.", LogTypeInfo
		End if


		' Determine if we are running UEFI

		bIsUEFI = FALSE
		On Error Resume Next
		bIsUEFI = oUtility.BDDUtility.IsUEFI
		On Error Goto 0


		' See if we are running on battery

		If oEnv("SystemDrive") = "X:" and oFSO.FileExists("X:\Windows\Inf\Battery.inf") then
			
			' Load the battery driver

			oShell.Run "drvload X:\Windows\Inf\Battery.inf", 0, true
			
		End if

		bFoundAC = False
		bFoundBattery = False
		Set objResults = objWMI.InstancesOf("Win32_Battery")
		For each objInstance in objResults
			bFoundBattery = True
			If objInstance.BatteryStatus = 2 then
				bFoundAC = True
			End if 
		Next
		If bFoundBattery and (not bFoundAC) then
			bOnBattery = True
		Else
			bOnBattery = False
		End if
		
		'set IsLaptop to true as long as Surface Pro model detected no matter what the chassistype is

		If ((instr(sModel,"Surface Pro")) > 0) and (sMake = "Microsoft Corporation") then
			bIsLaptop = true
		End if

		oEnvironment.Item("AssetTag") = sAssetTag
		oEnvironment.Item("SerialNumber") = sSerialNumber
		oEnvironment.Item("Make") = sMake
		oEnvironment.Item("Model") = sModel
		oEnvironment.Item("Product") = sProduct
		oEnvironment.Item("UUID") = sUUID
		oEnvironment.Item("Memory") = sMemory
		oEnvironment.Item("Architecture") = sArchitecture
		oEnvironment.Item("ProcessorSpeed") = sProcessorSpeed
		oEnvironment.Item("CapableArchitecture") = sCapableArchitecture
		oEnvironment.Item("IsLaptop") = oUtility.ConvertBooleanToString(bIsLaptop)
		oEnvironment.Item("IsDesktop") = oUtility.ConvertBooleanToString(bIsDesktop)
		oEnvironment.Item("IsServer") = oUtility.ConvertBooleanToString(bIsServer)
		oEnvironment.Item("IsUEFI") = oUtility.ConvertBooleanToString(bIsUEFI)
		oEnvironment.Item("IsOnBattery") = oUtility.ConvertBooleanToString(bOnBattery)
		oEnvironment.Item("SupportsX86") = oUtility.ConvertBooleanToString(bSupportsX86)
		oEnvironment.Item("SupportsX64") = oUtility.ConvertBooleanToString(bSupportsX64)
		If bSupportsSLAT or oEnvironment.Item("SupportsSLAT") = "" then
			oEnvironment.Item("SupportsSLAT") = oUtility.ConvertBooleanToString(bSupportsSLAT)
		Else
			oLogging.CreateEntry "Property SupportsSLAT = " & oEnvironment.Item("SupportsSLAT"), LogTypeInfo
		End if

		oLogging.CreateEntry "Finished getting asset info", LogTypeInfo

		GetAssetInfo = Success

	End Function


建立一個新的MDT包,在Surface Pro 7+ 上跑一次OSD image,會發現全部筆記本要安裝的app所有成功安裝了。

至此,問題解決,並且之後出的Surface Pro系列都會識別爲Laptop類型。

相關文章
相關標籤/搜索