[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’