Quickly Uninstall Single KB Update


Uninstalling Windows Updates is a pain in the neck!
  • The Windows Update GUI provides a long list of KB updates.  
  • Updates are organized by date and not by KB numbers.  
  • It lacks a built-in search function! 

Figure 1.  Windows Update History:
No search for you (CRL+F)!   :(


Use the command line to search and uninstall specific updates.

List installed patches:
wmic qfe list

Uninstall specific patch:
wusa /uninstall /kb:xxxxx

That's It!

Hide Windows Update Warnings on RDP /RDS Server


   Staff receive Windows Update message when logging onto the RDP server.  This problem confuses end users and causes unnecessary calls to help desk. 


   Remote desktop servers receive regular updates on Patch Tuesday. However, this problem was accentuated after Microsoft changed their patching policy to expedite out-of-band patches. 


Create new GPO policy to hide Windows Update messages on the RDP server.
    GPO Setting Path:  
      User Configuration\Policies\Administrative Templates\Windows Components\Windows Update
    GPO Policy:   
      Remove access to use all Windows Update features 
    GPO Attribute:  
     Enabled: 0. Do not show notifications. 


   This is a User Configuration setting -not a Computer Configuration.  Enable Loopback processing to ensure changes apply to all users that logon.  
    GPO Loopback Path:
      Computer Configuration\Policies\Administrative Templates\System/Group Policy\
    GPO Loopback Policy: 
     Configure user Group Policy loopback processing mode
    GPOLoopback Attribute:


Resolve WSUS Database Error Timeouts


WSUS GUI times out while running back-end SQL queries.  WSUS typically times out when refreshing Updates:  All Updates, Critical Updates, Security Updates, etc.


WSUS runs slow.  WSUS IIS App pool crashes and stops.  WSUS problem requires administrator to reset server node in order to function again.  Clients cannot download WSUS updates when APP pool is down.


Large number of updates in the catalog grows over time.  The update catalog reaches a size that increases the load on WSUS.  The server runs out of available memory for the App pool.


Kent Agerlund does a good job describing the problem on his blog.  Agerlund also provides a solution using a SQL script.  However, Agerlund's fix does not work for all WSUS implementations.  The script only works with the full version of SQL -not the Windows Internal Database.  For example:

The specified option 'Ad Hoc Distributed Queries' is not supported by this edition of SQL Server


Talented programmer, SAK, updates the script to work with WSUS 2012 running a Windows Internal Database version of SQL:

  1. SQL script to identify obsolete updates on WSUS server:
    DECLARE @return_value int
    EXEC @return_value = [dbo].[spGetObsoleteUpdatesToCleanup]
  2. SQL script to delete all obsolete updates on WSUS.  N.B., the script provides feedback messages, after each update ID is deleted.
    DECLARE @minimumDeadDeploymentTime DATETIME
    DECLARE @revisionDeletionTimeThreshold INT
    SELECT @revisionDeletionTimeThreshold=RevisionDeletionTimeThreshold FROM dbo.tbConfigurationC
    IF @@ERROR <> 0
        RAISERROR('spGetObsoleteUpdatesToCleanup: failed to get RevisionDeletionTimeThreshold from dbo.tbConfigurationC', 16, -1)
    SET @minimumDeadDeploymentTime = DATEADD(day, 0 - @revisionDeletionTimeThreshold, getutcdate())
    declare @updateid int
    declare @msg varchar(255)
    declare cur CURSOR LOCAL for
    SELECT DISTINCT u.LocalUpdateID FROM  dbo.tbUpdate u
        INNER JOIN dbo.tbRevision r ON r.LocalUpdateID = u.LocalUpdateID
        INNER JOIN dbo.tbProperty p ON p.RevisionID = r.RevisionID
         p.PublicationState = 1 
         AND (p.ExplicitlyDeployable = 1 OR p.UpdateType IN ('Category', 'Detectoid'))
         AND p.ReceivedFromCreatorService <= @minimumDeadDeploymentTime
         AND NOT EXISTS (SELECT * FROM dbo.tbBundleDependency bd 
                         INNER JOIN dbo.tbRevision r1 ON bd.BundledRevisionID = r1.RevisionID
                         WHERE r1.LocalUpdateID = u.LocalUpdateID)
         AND NOT EXISTS (SELECT * FROM dbo.tbPrerequisiteDependency pd
                         INNER JOIN dbo.tbRevision r2 ON pd.PrerequisiteRevisionID = r2.RevisionID
                         WHERE r2.LocalUpdateID = u.LocalUpdateID)
         AND NOT EXISTS (SELECT * FROM dbo.tbDeployment d
                         INNER JOIN dbo.tbRevision r3 ON d.RevisionID = r3.RevisionID
                         WHERE r3.LocalUpdateID = u.LocalUpdateID
                             AND d.TargetGroupTypeID = 0
                             AND d.ActionID IN (0, 1, 3))
         AND NOT EXISTS (SELECT * FROM dbo.tbDeadDeployment dd
                         INNER JOIN dbo.tbRevision r4 ON dd.RevisionID = r4.RevisionID
                         WHERE r4.LocalUpdateID = u.LocalUpdateID
                             AND dd.TargetGroupTypeID = 0
                             AND dd.ActionID IN (0, 1, 3)
                             AND dd.TimeOfDeath > @minimumDeadDeploymentTime)
    ORDER BY u.LocalUpdateID DESC
    open cur
    fetch next from cur into @updateid
    while @@FETCH_STATUS = 0 BEGIN
        --execute your sproc on each row
        --exec uspYourSproc @field1, @field2
     set @msg = 'Processing update: ' + cast(@updateid as varchar)
     exec spDeleteUpdate @updateid
        fetch next from cur into @updateid
    close cur
    deallocate cur