[download id=”95″]
The Challenge
Microsoft has changed the way updates are being installed and uninstalled many times. This means that a common method can’t be used.
Windows XP and Windows 2003
- Updates can be uninstalled from a hidden “uninstall” folder, located in the windows folder. Windows 2008 R2 and Windows 7
- A command line utility (wusa.exe) can uninstall the updates.
The solution
The solution contains one VBScript, this script is able to detect the local OS, and use one of the 2 methods above for uninstall.
XP/2003:
- The script does a check for the uninstall folder, and run the spuninst.exe
- The script writes event log event (Source: WSH) in the local event log describing if it was found it not.
- More logging can be enabled by the /log argument, and a text field will be created on the local machine
Win7/2k8R2:
- Script runs built-in the wusa.exe command.
- The script does no check if the update is installed before trying to uninstall the update, since wusa.exe have no method for doing this.
- Wusa.exe writes status messages to event log.
- Wusa.exe supported /log argument, but it does not write text files, therefore a .evt file will be saved (if a path for another type of file is specified, it will automatically be changed to .evt to make the file usable.)
The Flowchart later in this document describes this in a more detailed way.
The script will end with success, no matter if the update exists on the machine or not. If it fails, something else is wrong (for example: bad command line in the ConfigMgr Program).
Known Issues
- Windows 2008 (non R2) is Not Supported. It does not have the “old” uninstall folders in Windows folder, and “wusa.exe” utility does not support uninstallation.
- Some updates cannot be uninstalled, even if we try to do it manually.
- Other updates for Microsoft applications might not be possible to uninstall in this generic way
- 3rd party application updates or service packs cannot be uninstalled.
- Specific updates might use a non-standard installation method, which makes it impossible to uninstall (at least on XP/2003)
Using the script
Run the script with cscript.exe.
This is an example of the basic command line for running the script:
cscript.exe UninstallUpdates.vbs 976902
Syntax is
cscript.exe <scriptname> <kb number> <arguments>
this means you are able to use arguments for changing the behavior of the uninstall
Supported Arguments:
Argument | Description |
/passive | This disables the /quiet argument, and makes a progressbar visible for the user.(requires the user to be able to interact with the program in ConfigMgr) |
/norestart | Disable automatic restart when using /quiet |
/forcerestart | Force a restart after uninstall, no matter if it is needed or not. |
/warnrestart | Warn user before restarting(requires the user to be able to interact with the program in ConfigMgr) |
/log:”C:\temp\uninstall.log” | Create a log file on the local machine.XP/2003: Text file
7/2K8R2: .evt eventlog file. Notice there is no space between /log: and the path. Allways surround the path with “ “ to make sure that it is parsed correctly. |
To use argument in a command line
cscript.exe UninstallUpdates.vbs 976902 /norestart /log:”C:\KB976902-Uninstall.log”
Exit Codes
The script has a couple of custom exit codes.
You might experience other exit codes, if you have error in script, command line or similar.
Exit Code | Description |
10001 | No arguments supplied, at least one argument (KB Number) is required! |
a Thank you goes out to DFDS A/S
Script
' //*************************************************************************** ' // ***** Script Header ***** ' // ' // Solution: ConfigMgr Software Updates ' // File: UninstllUpdates-v0.1.vbs ' // Author: Jakob Gottlieb Svendsen, Coretech A/S. https://blog.ctglobalservices.com ' // Purpose: Uninstall Updates from Windows ' // Supported OS: ' // Windows XP ' // Windows 7 ' // Windows Server 2003 ' // Windows Server 2008 R2 ' // ' // Usage: wscript.exe <scriptname> <KB Number> <Arguments) ' // ' // 'Supported Arguments ' // /passive (no quiet install) ' // /norestart ' // /forcerestart ' // /warnrestart ' // /promptrestart (remember to make the program in configmgr to be interactive) ' // /log:"<path>" ' // ' // fx: cscript.exe UninstallUpdates-v0.1.vbs 978654 /norestart /log:"C:\log.log" ' // ' // CORETECH A/S History: ' // 1.0.0 JGS 25/07/2011 Created initial version. ' // 1.0.1 JGS 10/02/2012 Disabled check for KB number, since they can be both 6 or 7 decimals (maybe even more) ' // ' // Customer History: ' // ' // ***** End Header ***** ' //*************************************************************************** '//---------------------------------------------------------------------------- '// '// Global constant and variable declarations '// '//---------------------------------------------------------------------------- Set objShell = WScript.CreateObject("Wscript.Shell") '//---------------------------------------------------------------------------- '// Main routines '//---------------------------------------------------------------------------- 'Get Settings and KB i = 0 strCommandArgs = " " If WScript.Arguments.Count > 0 Then 'WScript.Echo WScript.Arguments.Item(i) Do While i < WScript.Arguments.length If i = 0 Then strKB = Replace(WScript.Arguments.Item(i),"KB","") 'Check regex. ' Set objRE = New RegExp ' objRE.Global = True ' objRE.IgnoreCase = False ' objRE.Pattern = "^\d{6}$" ' bMatch = objRE.Test(strKB) ' If Not bMatch Then ' WScript.Echo "KB Number wrong format: " & strKB ' WScript.Quit(10002) 'KB argument wrong format. ' End If Else strArg = LCase(WScript.Arguments.Item(i)) If InStr(strArg, "/log") Then bLog = True strLogFilePath = Replace(strArg, "/log:", "") 'More log in the select case below Else If InStr(strArg, "/passive") Then bPassive = True Else strCommandArgs = strCommandArgs & " " & strArg End If End If End If i = i + 1 Loop Else WScript.Quit(10001) 'No arguments supplied End If strCurrentOSVersion = CheckLocalOSVersion Select Case strCurrentOSVersion Case "6.1" 'Win7 - Win2k8r2 If bLog Then 'Convert file to .evt strLogFilePath = Left(strLogFilePath,Len(strLogFilePath) - 3) strLogFilePath = strLogFilePath & "evt" strCommandArgs = strCommandArgs & " /log:""" & strLogFilePath & """" End If UninstallUpdateWin2K8R2Win7 strKB, strCommandArgs, bPassive Case "5.2", "5.1" 'windows 2003 or Windows XP If bLog Then strCommandArgs = strCommandArgs & " /log:""" & strLogFilePath & """" End If UninstallUpdateXP2003 strKB, strCommandArgs, bPassive End Select '//---------------------------------------------------------------------------- '// Procedures '//---------------------------------------------------------------------------- Function UninstallUpdateWin2K8R2Win7(strKBNumber, Args, bPassive) Dim objShell Set objShell = WScript.CreateObject("Wscript.Shell") If bPassive Then 'run silent uninstall strCmd = "wusa.exe /kb:" & strKBNumber & " /uninstall /passive" & Args Else 'run silent uninstall strCmd = "wusa.exe /kb:" & strKBNumber & " /uninstall /quiet" & Args End If WScript.Echo "Commandline: " & strCmd ReturnCode = objShell.Run(strCmd , , True) WScript.Echo "ReturnCode: " & ReturnCode End Function Function UninstallUpdateXP2003(strKBNumber, Args, bPassive) Dim objFSO, objShell Set objFSO = CreateObject("Scripting.FileSystemObject") Set objShell = WScript.CreateObject("Wscript.Shell") Set objFolder = objFSO.GetFolder(objShell.ExpandEnvironmentStrings("%WINDIR%")) Set colSubfolders = objFolder.Subfolders bFound = False For Each objSubfolder in colSubfolders strFolderName = LCase(objSubFolder.Name) If InStr(strFolderName, "ntuninstallkb") Then strCurrentKB = Mid(strFolderName, InStr(strFolderName, "kb") + 2, 6) If strCurrentKB = strKBNumber Then bFound = True 'Uninstall KB strUninstallExe = objSubFolder.Path & "\spuninst\spuninst.exe" If (objFSO.FileExists(strUninstallExe)) Then If bPassive Then 'run silent uninstall strCmd = strUninstallExe & " /passive " & Args Else 'run silent uninstall strCmd = strUninstallExe & " /quiet " & Args End If WScript.Echo "Commandline: " & strCmd ReturnCode = objShell.Run(strCmd , , True) Else objShell.LogEvent 1, "Software Update KB" & strKBNumber & " could not be uninstalled (uninstalled exe was not found at " & strUninstallExe & " )" End If End If End If 'Wscript.Echo objSubfolder.Name, objSubfolder.Size Next If bFound Then objShell.LogEvent 0, "Software Update KB" & strKBNumber & " was successfully uninstalled" Else objShell.LogEvent 1, "Software Update KB" & strKBNumber & " could not be uninstalled (folder not found)" End If End Function Function CheckLocalOSVersion Set objShell = CreateObject("Wscript.Shell") OSVer = objShell.RegRead("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\CurrentVersion") CheckLocalOSVersion = OSVer End Function '//---------------------------------------------------------------------------- '// End Script '//----------------------------------------------------------------------------
[…] Pour plus d’information, je vous renvoie vers son blog post : http://blog.coretech.dk/jgs/vbscript-uninstall-updates-on-winxpwin2003-win7-and-win-2008-r2-automati… […]
Thanks for the script….
Great script!!!! It was very useful ( http://social.technet.microsoft.com/Forums/pt-BR/scriptadminpt/thread/4c8ac7b5-6053-48fa-829b-bf293a6a8911 )
suggestion:
Change line:
strCurrentKB = Mid(strFolderName, InStr(strFolderName, “kb”) + 2, 6)
to
strCurrentKB = Mid(strFolderName, InStr(strFolderName, “kb”) + 2, len(strKBNumber))
[…] – Uninstalll updates Automatically using a script: http://blog.coretech.dk/jgs/vbscript-uninstall-updates-on-winxpwin2003-win7-and-win-2008-r2-automati… […]
can any one help install windows updates using VB script for windows 2003 and 2008 servers
So when running the script I receive the error vbs(51, 31) Microsoft VBScript compilation error: Expected ‘Then’