Annoying task… configuring VMware View desktops for use in an environment that utilizes VMware View. Some say, don’t put the management agent on the View desktop, just rebuild your desktops every time there is a security patch. I say, even if recomposing your pools is fast and easy, I still do not want to do it with every patch release.
Best practice for preparing a reference computer for deployment in an SCCM environment is to not include the SCCM client. However, SCCM client installation is SLOW, so I would like to save time and CPU load by including the software. Documentation how to do this is sketchy. Also, I really want a script fired off by the QuickPrep process to do the prep work, so that someone does not forget that it needs to be done.
Here is my first pass at the script… again, not too pretty, but functional:
'==========================================================================
'
' NAME: sccmClientPrep.vbs
'
' AUTHOR: J. Greg Mackinnon
' DATE: 2013-02-01
'
' COMMENT: prepares SCCM client for cloning
' Requires:
' - Certutil.exe in %systemroot%\system32 (included with Win7)
' Returns:
' 1 - CCMEXEC service stop failure
' 2 - Machine Certificate Store deletion failure
' 4 - SMS Certificate Store deletion failure
' 8 - SMSCFG.INI deltion failure
'==========================================================================
option explicit
'=-=-=-=-=-=-=-=-=-=-=-=-=
' CONSTANTS
const MACH_STORE = "My"
const SMS_STORE = "SMS"
const SVCNAME = "ccmexec"
const TIMEOUT = "120"
'=-=-=-=-=-=-=-=-=-=-=-=-=
' OBJECTS
dim oShell
set oShell = CreateObject("WScript.Shell")
'=-=-=-=-=-=-=-=-=-=-=-=-=
' VARIABLES
dim sSysRoot,sCUPath,sINIPath
dim iRet, iExit
sSysRoot = oShell.ExpandEnvironmentStrings("%SystemRoot%")
sCUPath = sSysRoot & "\system32\certutil.exe"
sINIPath = sSysRoot & "\SMSCFG.INI"
iExit = 0
'=-=-=-=-=-=-=-=-=-=-=-=-=
' FUNCTIONS AND SUBS
function stopSvc(sSvcName,iTimeout)
' Stops the Windows service with name matching input string "sSvcName".
' Times out in iTimeout seconds.
' Needs routine to verify that sSvcName is a valid service name.
'Variables:
dim bDone
dim iSecs
bDone = False
iSecs = 0
'Objects and Collections:
dim cSvcs
dim oWMI, oSvc
Set oWMI = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
Set cSvcs = oWMI.ExecQuery("Select * from Win32_Service Where Name = '" & sSvcName & "'")
'Stop the service if it is running, exit if it is not running
For Each oSvc In cSvcs
if oSvc.State = "Running" then
oSvc.StopService
else
stopSvc = 0
exit function
end if
exit for 'Only on service in collection
Next
'Check on the service until stopped. Timeout in iTimeout seconds.
Do while bDone = False
Set cSvcs = oWMI.ExecQuery("Select * from Win32_Service Where Name = '" & sSvcName & "'")
bDone = True
For Each oSvc In cSvcs
If oSvc.State "Stopped" Then
bDone = False
WScript.Sleep 1000
Exit For
End If
Next
iSecs = iSecs + 1
If iSecs >= iTimeout Then
stopSvc = 1
exit function
End If
Loop
stopSvc = 0
end function
function delCert(sStore,sSerial)
'Deletes certificate in certificate store "sStore" with serial number "sSerial"
'Returns: The ExitCode from certutil.exe
'Requires:
' - WScript.Shell object named "oShell"
' - Defined path to "certutil.exe" named "sCUPath"
' - Presence of certutil.exe on the system
dim oExec, oStdOut
dim sLine
'wscript.echo "About to execute: " & sCUPath & " -delstore " & sStore & " " & sSerial
set oExec = oShell.Exec(sCUPath & " -delstore " & sStore & " " & sSerial)
Set oStdOut = oExec.StdOut
Do While oExec.Status = 0
WScript.Sleep 100
Loop
'Uncomment the next four lines to debug certutil:
'Do Until oStdOut.AtEndOfStream
' sLine = oStdOut.ReadLine
' wscript.echo sLine
'Loop
delCert = oExec.ExitCode
end function
function getCert(sStore)
'Gets the serial numbers of certificates in the machine store specified by "sStore"
'Sends the captured serial numbers to the "delCert" function for deletion.
'Returns: 1 - If cert deletion files, 0 - If no errors are detected.
'Requires:
' - WScript.Shell object named "oShell"
' - Defined path to "certutil.exe" named "sCUPath"
' - Presence of certutil.exe on the system
dim oExec, oStdOut
dim bFail
dim i, iRet
dim sLine, sSerial
bFail=False
Set oExec = oShell.Exec(sCUPath & " -store " & sStore)
Set oStdOut = oExec.StdOut
Do Until oStdOut.AtEndOfStream
sLine = oStdOut.ReadLine
if InStr(1,sLine,"Serial Number",1) then
i = CInt(InStr(1,sLine,":",1) + 2)
sSerial = Mid(sLine,i)
iRet = delCert(sStore,sSerial)
if (iRet 0) then
wscript.echo "Certificate deletion failed"
bFail = True
end if
end if
Loop
if bFail = True then
getCert = 1
else
getCert = 0
end if
end function
function delFile(sFile)
'Deletes the file specified by "sFile"
'Requires existing Wscript.Shell object named "oShell"
dim oFSO, oFile
set oFSO = CreateObject("Scripting.FileSystemObject")
'wscript.echo "About to delete file: " & sFile
if oFSO.FileExists(sFile) then
'Delete method will force a WSH quit if it fails, so we need to disable exit-on-error:
Err.Clear
On Error Resume Next
set oFile = oFSO.GetFile(sFile)
delFile = oFile.Delete(True)
if Err.Number = 0 then
delFile = 0
else
delFile = Err.Number
end if
else
'Exit code for the function could be changed here if you are concerned about
' the requested file to delete not being present on the system.
'wscript.echo "File " & sFile & " does not exist."
delFile = 0
end if
end function
'=-=-=-=-=-=-=-=-=-=-=-=-=
' MAIN
iRet = stopSvc(SVCNAME, TIMEOUT)
'wscript.echo "Return from stopSvc: " & iRet
if iRet 0 then
iExit = iExit + 1
end if
iRet = getCert(MACH_STORE)
'wscript.echo "Return from cert deletion for store " & MACH_STORE & ": " & iRet
if iRet 0 then
iExit = iExit + 2
end if
iRet = getCert(SMS_STORE)
'wscript.echo "Return from cert deletion for store " & SMS_STORE & ": " & iRet
if iRet 0 then
iExit = iExit + 4
end if
iRet = delFile(sINIPath)
'wscript.echo "Return from file deletion: " & iRet
if iRet 0 then
iExit = iExit + 8
end if
WScript.Quit iExit