POLL: POWERSHELL VS. GUI - DO YOU WANT TO BE A DEVOP OR AN ADMIN?
Windows deployment preflight checks – Part 2: The script
In my last post, I discussed a few preflight checks that I recommend for Windows deployments. This post explains the code of my VBScript script that helps you with this task for Windows XP deployments.
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
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.
By