- How to create a PowerShell alias - Tue, Jul 29 2014
- System Center Updates Publisher – Create a SCUP catalog - Fri, May 23 2014
- System Center Updates Publisher – Third-party patch management - Wed, May 21 2014
The script itself is a basic HTML Application (HTA) with lots of Windows Management Instrumentation (WMI) calls to check various hardware properties. The pseudo-code is:
Initialize the HTA Function Run Preflight Check Check the make (vendor) Check the model (is in a text list) Check RAM is above value x Check HDD is not RAW Check CPU architecture< End
Clearly this makes it modular, with each check being a new function. Microsoft’s UDI uses a script for every check, which is fine; however, I found different people or teams have written them, so not even the comments are consistent.
I wanted to avoid resorting to “copy and paste” from the web, and I want my code to be efficient, so I only query the precise values I want. Too often code from the web uses “select * from…”. Although that works, it’s plain lazy coding. Forcing myself to select specific values also means I fully understand what the script is doing.
The first thing that the HTA runs is whatever you put into the Window_OnLoad subroutine. The code below shows what this function does in the comments.
The core engine of this script that calls each check is preflightchecks. A flag, blnDebug, precedes the checks. If you set this flag to TRUE and run the HTA, it enables “debug mode,” which allows the script to run but triggers a debugger. You need the Microsoft script debugger or Visual Studio installed to continue. (I still prefer the script debugger as it’s a tiny 654KB and has a command window). When the debug tool opens, you can then step through the code and the HTA itself will switch to a verbose mode, outputting more info below the table.
Running normally proceeds to start the checks. The pseudo code is:
Get hardware value Check the value WMI returns is usable data Perform the check Update GUI with value
The first check I do is for the vendor. Unless your business is truly chaotic, you will only have one or two hardware makes, e.g. HP and Toshiba. Restricting a deployment so it only attempts to deploy to the makes you want is prudent. The code is one line:
strHTAVendor=fCheckVendor(strWQLGenericBIOS)
This calls the fCheckVendor with a preset WQL string:
strWQLGenericBIOS="SELECT Manufacturer,SMBIOSBIOSVersion, ReleaseDate FROM Win32_BIOS WHERE PrimaryBIOS = True"
We only want the manufacturer now, but we will use the date and BIOS version a bit later too. fCheckVendor checks the string this query returns against those you want to allow. I create the vendor whitelist using a dictionary object, objApprovedMakesDict. If there’s a match, the script continues; otherwise, it aborts immediately. Since each check can trigger a reason to abort, I use the flag bAbortBuild to give control.
The second check is against the model name. Here I use an external text file with the model names, one per line. Because my deployment task-sequence queries WMI for the machine name, the text file needs the exact name. I use wmic csproduct get name on each hardware model to be sure the text is exact.
strHTAModel=fUniversalCheckData(strHTAModel," 'Discover Model - fGetModelName'") 'validate data
fUniversalCheckData is a basic validation function that checks that the value is not null and is alphanumeric. Using validation pre-empts errors and allows me to use consistent error handling.
The third check for RAM is fCheckRAM, and is a slightly modified copy from MDT2012.
The fourth check is vital. I’ve found that SCCM really doesn’t like non-standard file systems, whether OEM or encrypted. This check allows you to pause and manually format the disk, which is great while developing. I use constants to preset all prerequisite values, e.g. cMinFS.
The final checks all run against the processor. I use a generic call, fGetCPUInfo(strWQLCPUInfo), to return processor attributes and then check against the results for speed, core count, and architecture. Notice these checks run using a generic WMI function (below) that I cunningly call “WMI,” which takes two parameters. The parameters are what WQL needs to return the hardware values and the target namespace.
Function WMI(strQuery,strNameSpace 'Aim: generic WMI calls 'return value of BIOS
On Error Resume Next
Dim colItems,objItem Dim objWMI Const strService = "winmgmts:{impersonationlevel=impersonate} //" 'binding to WMI Const strComputer = "." 'this machine
Set objWMI = GetObject(strService & strComputer & strNamespace) 'GLOBAL wmi Set colItems = objWMI.ExecQuery(strQuery,,lFlags)
For Each objItem In colItems
If Err Then StatusBar.InnerText=StatusBar.InnerText & VbCrLf & "WMI query: " &
strQuery & " in " & strNamespace & objItem.Name
Call ErrHandler("WMI error " & strQuery,1)
Else
WMI=objItem.Name 'Return value
End If
Next End Function
Item | Action | Function | Comment |
Is make supported? | Abort | fCheckVendor(strVendor) | |
Is model supported (checklist)? | Abort | fCheckModels | Don’t want visitors to have their machine rebuilt OR people taking a build home |
Is there enough RAM in the machine? | Abort | fCheckRAM(strRAM) | HW prerequisite |
HDD: Is vol 0 NTFS? | Format 1st vol | fCheckNTFS(strDiskFS) | HW prerequisite |
CPU: Is the CPU 64-bit? | Set 64 flag (abort if try to deploy 64-bit OS) | fCheckCPUArch(strHTAArchitecture) | Only offer 64-bit builds to 64-bit HW |
CPU: How fast is the processer? | Abort | fCheckCPUSpeed(strCPU) 'any HW | |
CPU: How many cores? | Abort | fCheckCores(iCores) | |
Table 3 - List of pre-requisite checks and relevant functions
Subscribe to 4sysops newsletter!
After you download the file, unzip it to a new directory and change the TXT extension to HTA. To run the HTA, double-click the file. The script will report a failure unless you add the model of your machine to models.txt, which is entirely by design. 🙂
Great article!
I think I missed the check of the disk’s health with S.M.A.R.T (4c) which in my view is an important detail also to the success of any deployment since the disk is the main stage where all the staging will occur