When installing the required hotfix for Configuration Manager 2007 R3 you are probably faced with the challenge that you need to install more the one SCCM client hotfix. Installing them in the normal way would require three packages, programs and advertisements which need to be installed.
I wrote a script which will install all hotfixes placed in the same folder as the script I found a great example somewhere on how to write a MIF file which I cannot find again, sorry for not giving you credit for it.
The script will also create the .MIF file needed for Configuration Manager 2007 client to report back succeeded as the Configuration Manager Client hotfixes restarts the client service which makes the advertisement report back “Unexpected reboot”.
*****2011-08-23 – Updated with a new version of the script with improved error control******
Steps to implement the script:
- Create a collection to which you will advertise the Client Hotfixes, for instance use a query for all clients not having the latest version, in this example version 4.00.6487.2157.
Example Query:select SMS_R_SYSTEM.ResourceID,SMS_R_SYSTEM.ResourceType,SMS_R_SYSTEM.Name,SMS_R_SYSTEM.SMSUniqueIdentifier,SMS_R_SYSTEM.ResourceDomainORWorkgroup,SMS_R_SYSTEM.Client from SMS_R_System where SMS_R_System.ClientVersion != “4.00.6487.2157” - Download the sccm client hotfix script from here:https://ccmexec.com/wp-content/uploads/2011/08/updates11.vbs.txt
It is also posted in the bottom of this page. - Create a package with the script in the source files together with the client hotfixes you would like to install.
- For the MIF file to work the package name, version and publisher entered in the script must match the values for the package in SCCM. Change the following lines in the script to match it.
Call SMSWriteStatusMIF(“Updates.MIF”,“Microsoft”,”SCCM Client Hotfixes”, “2007”,”The operation completed successfully.”,”true”)
The picture below shows the reporting tab which is made up of the information for the package.
- Then create a program for the package according to the screenshot below, don’t forget to select the “program restarts computer”. Which it will not but it will not report failure when the client service is restarted.
- Then advertise the Program to the collection created in step 1.
If there are many clients not having the latest version, test the script first on a couple of clients. And as always test and roll out these changes in a controlled way.
Script content:
'Version 1.1 - updated error control and reporting
'Option Explicit
Dim objfso, objShell
Dim folder, files, sFolder, folderidx, Iretval, return
Set objfso = CreateObject("Scripting.FileSystemObject")
Set objShell = CreateObject("Wscript.Shell")
sFolder = left(WScript.ScriptFullName,(Len(WScript.ScriptFullName))-(len(WScript.ScriptName)))
Set folder = objfso.GetFolder(sFolder)
Set files = folder.Files
For each folderIdx In files
If Ucase(Right(folderIdx.name,3)) = "MSP" then
wscript.echo "msiexec.exe /p " & sfolder & folderidx.name & " /q REINSTALL=ALL REINSTALLMODE=mous"
iretval=objShell.Run ("msiexec.exe /p " & sfolder & folderidx.name & " /q REINSTALL=ALL REINSTALLMODE=mous", 1, True)
If (iRetVal = 0) or (iRetVal = 3010) then
wscript.echo folderidx.name & " Success"
Else
wscript.echo folderidx.name & " Failed"
call SMSWriteStatusMIF("PNITNST.MIF","Microsoft","SCCM Client Hotfixes", "2007",FolderIDX.name & " reported error: " & iretval &" and failed to install","fail")
wscript.quit
End If
End If
Next
call SMSWriteStatusMIF("PNITNST.MIF","Microsoft","SCCM Client Hotfixes", "2007","The operation completed successfully.","true")
Sub SMSWriteStatusMIF(FileName,Manufacturer, Product, Version, Description, bSuccess)
' Writing a status MIF for SWDist to return a success or a failure to execute
' Product is the name of the Script and MIF file.
' Description is the status message
' bSuccess is True/False of success
Const ForWriting = 2
Dim mifFile
Dim WinDir
Set FileSys = CreateObject("Scripting.FileSystemObject")
WinDir = objShell.ExpandEnvironmentStrings("%WINDIR%")
Set mifFile = FileSys.CreateTextFile(WinDir & "\" & FileName , ForWriting)
With mifFile
.Writeline ("START COMPONENT")
.Writeline ("NAME = ""WORKSTATION""")
.Writeline (" START GROUP")
.Writeline (" NAME = ""ComponentID""")
.Writeline (" ID = 1")
.Writeline (" CLASS = ""DMTF|ComponentID|1.0""")
.Writeline (" START ATTRIBUTE")
.Writeline (" NAME = ""Manufacturer""")
.Writeline (" ID = 1")
.Writeline (" ACCESS = READ-ONLY")
.Writeline (" STORAGE = SPECIFIC")
.Writeline (" TYPE = STRING(64)")
.Writeline (" VALUE = """ & Manufacturer & """")
.Writeline (" END ATTRIBUTE")
.Writeline (" START ATTRIBUTE")
.Writeline (" NAME = ""Product""")
.Writeline (" ID = 2")
.Writeline (" ACCESS = READ-ONLY")
.Writeline (" STORAGE = SPECIFIC")
.Writeline (" TYPE = STRING(64)")
.Writeline (" VALUE = """ & Product & """")
.Writeline (" END ATTRIBUTE")
.Writeline (" START ATTRIBUTE")
.Writeline (" NAME = ""Version""")
.Writeline (" ID = 3")
.Writeline (" ACCESS = READ-ONLY")
.Writeline (" STORAGE = SPECIFIC")
.Writeline (" TYPE = STRING(64)")
.Writeline (" VALUE = """ & Version & """")
.Writeline (" END ATTRIBUTE")
.Writeline (" START ATTRIBUTE")
.Writeline (" NAME = ""Locale""")
.Writeline (" ID = 4")
.Writeline (" ACCESS = READ-ONLY")
.Writeline (" STORAGE = SPECIFIC")
.Writeline (" TYPE = STRING(16)")
.Writeline (" VALUE = ""ENU""")
.Writeline (" END ATTRIBUTE")
.Writeline (" START ATTRIBUTE")
.Writeline (" NAME = ""Serial Number""")
.Writeline (" ID = 5")
.Writeline (" ACCESS = READ-ONLY")
.Writeline (" STORAGE = SPECIFIC")
.Writeline (" TYPE = STRING(64)")
.Writeline (" VALUE = ""NIL""")
.Writeline (" END ATTRIBUTE")
.Writeline (" START ATTRIBUTE")
.Writeline (" NAME = ""Installation""")
.Writeline (" ID = 6")
.Writeline (" ACCESS = READ-ONLY")
.Writeline (" STORAGE = SPECIFIC")
.Writeline (" TYPE = STRING(64)")
.Writeline (" VALUE = ""DateTime""")
.Writeline (" END ATTRIBUTE")
.Writeline (" END GROUP")
.Writeline (" START GROUP")
.Writeline (" NAME = ""InstallStatus""")
.Writeline (" ID = 2")
.Writeline (" CLASS = ""MICROSOFT|JOBSTATUS|1.0""")
.Writeline (" START ATTRIBUTE")
.Writeline (" NAME = ""Status""")
.Writeline (" ID = 1")
.Writeline (" ACCESS = READ-ONLY")
.Writeline (" STORAGE = SPECIFIC")
.Writeline (" TYPE = STRING(32)")
' Pass or fail this status mif?
If bSuccess = "true" then
.Writeline (" VALUE = ""Success""")
else
.Writeline (" VALUE = ""Failed""")
End if
.Writeline (" END ATTRIBUTE")
.Writeline (" START ATTRIBUTE")
.Writeline (" NAME = ""Description""")
.Writeline (" ID = 2")
.Writeline (" ACCESS = READ-ONLY")
.Writeline (" STORAGE = SPECIFIC")
.Writeline (" TYPE = STRING(256)")
.Writeline (" VALUE = """ & Description & """")
.Writeline (" END ATTRIBUTE")
.Writeline (" END GROUP")
.Writeline ("END COMPONENT")
End With
mifFile.Close
Set mifFile = Nothing
End Sub
'Package Properties
Hi Jörgen, thanks for the script! its the perfect method to deploy the numerous hotfixes for the client agent. But i had 2 patches that are not installed because of an error. This patches wasnt reported back as failed. on the client there wasnt a .mif file also. the status of the advertised package was reported as “success” though these hotfixes wasnt installed.
Is there a way to expand your script so that is get back the failed hotfixes?
Thanks for your help and work!
Hi,
I have updated the script now with better error-handling and it will report back to sccm which hotfix failed to install.
I tested the hotfixes and it seems as kb2278119 is superseeded by another update, the other ones installed just fine for me at least.
/Jörgen
Jorgen, thanks so much for your post. This is helping a lot. Your SQL query didn’t work for me (syntax error of some kind), so I set it myself with the following:
select SMS_R_SYSTEM.ResourceID,SMS_R_SYSTEM.ResourceType,SMS_R_SYSTEM.Name,SMS_R_SYSTEM.SMSUniqueIdentifier,SMS_R_SYSTEM.ResourceDomainORWorkgroup,SMS_R_SYSTEM.Client from SMS_R_System where SMS_R_System.ClientVersion < "4.00.6487.2188"
Obviously this pulls in all systems with agents lower than 2188 and I verified it works on my SCCM setup.
Jörgen, thanks for the script. Have you tested using it within a Task Sequence?
I followed your instructions, but instead of changing the script to use “updates.mif”, I instead specified the default filename within the package (“PNITNST.MIF”). I made sure that the restart settings matched your instructions. Then I created the program, distributed to the DPs, etc. Would you clarify this part of the instructions, please?
In my Task Sequence, I added a “Install Software” step just after “Setup Windows and ConfigMgr”, selected the correct package and program. When executing this Task Sequence, it errors out after the script starts to run, probably after the first MSP finishes, and the client restarts. I checked the various log files after the TS failed, and noticed the error pointed to “Unexpected restart” even though the program is marked as “Program will restart the computer”. Any ideas?
I did a bit more troubleshooting relative to the issue I already described, with help from Microsoft no less. Here’s what I’ve found:
Running this script within a Task Sequence seems to cause a disconnect between the SCCM Client service (ccmexec) and the Task Sequence processor (smsts), because smsts is constantly polling ccmexec. When the MSP is installed in this manner, and ccmexec restarts, smsts assumes the worst. If you set the “ignore errors and continue” flag within the task sequence, when ccmexec restarts the first time, the rest of that step is considered to have already errored, even if the script is still running and more patches are being applied, so the system will begin any subsequent steps… and then ccmexec will restart again from the next MSP as it is applied… the result is, any number of later steps (likely Software Distribution steps at that stage) will simply fail, as they cannot be performed without ccmexec running.
I’m looking for a solution. Namely, some way for smsts to avoid moving forward through the deployment until cscript has finished processing this. That or maybe some kind of sleep function. Alternatively, I’ll have to deploy each MSP manually through the Task Sequence.
Thanks, this was extremely helpful. I made some modifications for use within my environment to also have the script install .msi hotfixes using a Case statement as well as outputting a log to %windir%\temp for troubleshooting purposes.
I wanted to point out that in the sub statement, a value is defined Dim WinpDir and then later used as WinDir. Not a big deal since option explicit isn’t invoked.
Hi Jörgen,
first of all, very good blog, i like it! 😉
Relating to the installation problems of kb2278119, just take a look at my posting on: http://social.technet.microsoft.com/Forums/en-ZA/configmgrsetup/thread/ef98ef91-62f2-442f-b9fc-338d9ffbcc93
Perhaps interesting for you too.
Regards,
Christian
Thanks for pointing that out, I have updated it.
/Jörgen
Thanks for this great post! I tried it with one pc (mine for instance) and everything went smoothly!
Was a bit sceptical when I saw my ‘site mode’ to ‘unknown’ but the process wasn’t quite finished. But everything went automatically and I had nothing to do.
Again, great post and it saved me from making 4 separated packages ;-)))))