Tags

, ,


I wrote the script below to deploy the Group Policy Preferences Client Side Extension to our old XP machines as there are various pre-requisites. The script was packaged along with two files which you’ll see referenced in the script (the CSE itself and XML Lite) and distributed with SCCM. The script exits if the PC doesn’t have SP3 on or is not XP, with return code 1. Other errors are returned (and can be seen in SCCM) and progress is logged to the local event log.
This script as written below was successfully used to get the CSE installed on over 1000 PCs.

 ' Install Group Policy Preferences Client Side Extension
 ' Cantoris - March 2011

On Error Resume Next

Const RUNMINIMISED = 7
Const WAITONRETURN = True
Const MSI_NEEDSRESTART = 3010
Const LOG_INFO = 4
Const LOG_ERROR = 1
Const wbemFlagReturnWhenComplete = 0

Const strAppName = "Cantoris' SCCM GPPrefs CSE Installer"

Dim objWshShell, objSWbemServices

Call subInit
Call subPreReqs
Call subHandleCSE
WScript.Quit 0

Sub subInit
 ' Basic initialisation
	On Error Resume Next

	Set objWshShell = WScript.CreateObject("WScript.Shell")
	Set objSWbemServices = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
	If Err.Number <> 0 Then WScript.Quit Err.Number
	
	objWshShell.LogEvent LOG_INFO, strAppName & ": Starting script to install Group Policy Preferences Client Side Extension - KB943729."
End Sub

Sub subPreReqs
 ' Check Pre-Requisites
	On Error Resume Next

 ' Check XP
	arrOS = Split(fnDetermineOSandSP, "*")
	If arrOS(0) <> "5.1" Then
		objWshShell.LogEvent LOG_ERROR, strAppName & ": This script should only be directed against XP machines - exiting."
		WScript.Quit 1
	End If

 ' Check at least XP SP2
	intSP = CInt(arrOS(1))
	If intSP < 2 Then
		objWshShell.LogEvent LOG_ERROR, strAppName & ": The GPPrefs CSE needs at least Service Pack 2 - exiting."
		WScript.Quit 1
	End If

 ' IS SP2, needs XML Lite first (included with SP3)
	If intSP = 2 Then Call subCheckXmlLite
End Sub

Sub subHandleCSE
 ' Check for and install the CSE
	On Error Resume Next

	blnIsInstalled = fnLookForHotfix("ServicePackInEffect", "KB943729", "GPPrefs CSE")
	If blnIsInstalled = True Then
		objWshShell.LogEvent LOG_INFO, strAppName & ": The GPPrefs CSE is already installed - exiting."
		WScript.Quit 0
	End If
	
	Call subInstallHotfix("WinXP-GPP-CSE-KB943729.exe", "/quiet /norestart", "GPPrefs CSE")
	objWshShell.LogEvent LOG_INFO, strAppName & ": The script has completed successfully - exiting."
End Sub

Sub subCheckXmlLite
 ' Look for and if required, install XML Lite
	On Error Resume Next

	blnIsInstalled = fnLookForHotfix("ServicePackInEffect", "KB915865", "XML Lite")
	If blnIsInstalled = True Then Exit Sub

	Call subInstallHotfix("WinXP-XmlLite-KB915865-v11.exe", "/quiet /norestart", "XML Lite")
End Sub

Function fnDetermineOSandSP
 ' Determine OS and Service Pack of host machine
 ' Return as two strings separated by "*"
	On Error Resume Next

	strWQL = "SELECT * FROM Win32_OperatingSystem"
	Set colOSs = objSWbemServices.ExecQuery(strWQL,,wbemFlagReturnWhenComplete)
	If Err.Number <> 0 Then
		objWshShell.LogEvent LOG_ERROR, strAppName & ": WMI call failed with error " & Chr(34) & Err.Description & Chr(34) & "."
		WScript.Quit Err.Number
	End If

	For Each objOS In colOSs
		strVersion = Left(objOS.Version & "000", 3)
		strSP = objOS.ServicePackMajorVersion
	Next
	
	strMsg = strAppName & ": OS detected as v" & strVersion
	If CInt(strSP) > 0 Then
		strMsg = strMsg & " with Service Pack " & strSP & "."
	Else
		strMsg = strMsg & " Gold."
	End If
	objWshShell.LogEvent LOG_INFO, strMsg
	
	fnDetermineOSandSP = strVersion & "*" & strSP
End Function

Function fnLookForHotfix(ByVal strWMIField, ByVal strMatch, ByVal strDesc)
 ' Look to see if hotfix is installed or not
	On Error Resume Next

	strWQL = "SELECT " & strWMIField & " FROM Win32_QuickFixEngineering"
	Set colQFEs = objSWbemServices.ExecQuery(strWQL,,wbemFlagReturnWhenComplete)
	If Err.Number <> 0 Then
		objWshShell.LogEvent LOG_ERROR, strAppName & ": WMI call failed with error " & Chr(34) & Err.Description & Chr(34) & "."
		WScript.Quit Err.Number
	End If

	blnQFEInstalled = False
	For Each objQFE In colQFEs
		If LCase(Eval("objQFE." & strWMIField)) = LCase(strMatch) Then blnQFEInstalled = True
	Next
	
	strMsg = strAppName & ": Hotfix " & Chr(34) & strDesc & Chr(34) & " is "
	If blnQFEInstalled = False Then strMsg = strMsg & "not "
	strMsg = strMsg & "already installed."
	objWshShell.LogEvent LOG_INFO, strMsg

	fnLookForHotfix = blnQFEInstalled
End Function

Sub subInstallHotfix(ByVal strFileName, ByVal strSwitches, ByVal strDesc)
 ' Try and install a hotfix
	On Error Resume Next
	
	objWshShell.LogEvent LOG_INFO, strAppName & ": Installing hotfix " & Chr(34) & strDesc & Chr(34) & "."
	strCmd = strFileName & " " & strSwitches
	intReturnCode = objWshShell.Run(strCmd, RUNMINIMISED, WAITONRETURN)
	If Err.Number <> 0 Then
		objWshShell.LogEvent LOG_ERROR, strAppName & ": Installation failed with error " & Chr(34) & Err.Description & Chr(34) & "."
		WScript.Quit Err.Number
	End If
	If intReturnCode <> 0 And intReturnCode <> MSI_NEEDSRESTART Then
		objWshShell.LogEvent LOG_ERROR, strAppName & ": Installation failed with return code " & intReturnCode & "."
		WScript.Quit intReturnCode
	End If
	
	objWshShell.LogEvent LOG_INFO, strAppName & ": Hotfix " & Chr(34) & strDesc & Chr(34) & " installation succeeded."
End Sub

You should assess if this is suitable for your own environment before trying it out. It goes without saying that you use it entirely at your own risk! The package was targeted to XP x86 machines by SCCM but I included a check to ensure it was indeed XP in the code but no x86 versus x64 check as our environment was entirely x86.

Advertisements