Paul's Internet Landfill/ 2016/ Cleaning a Stuck WSUS Server: Too Many Unapproved Updates

Cleaning a Stuck WSUS Server: Too Many Unapproved Updates

This was a tough one. We have labs full of Windows 7 computers that get their updates via a WSUS server. These machines were not getting their updates. Many of them were failing with WSUS error 0x80244010 . (There were some other errors as well, which I foolishly did not write down.)

Error 0x80244010 means "the client tried to contact the WSUS server for more than 200 round trips". http://blogs.technet.com/b/sus/archive/2008/09/18/wsus-clients-fail-with-warning-syncserverupdatesinternal-failed-0x80244010.aspx . "200" is a hardcoded value. Re-running "Check for Updates" on the client several times (I have had to run it three or four times) can fix the issue well enough that the computer gets updates, but this is irritating.

The underlying problem appears to be twofold:

WSUS has a Cleanup Wizard which is supposed to expire obsolete and unneeded updates. I tried running this, but it would get stuck and hang forever.

There is lots of advice about how to fix this problem: defragging hard drives, running the Cleanup Wizard multiple times, running weird Powershell scripts that launch the Wizard via the commandline. None of them worked for me. What worked was the advice on this page:

https://social.technet.microsoft.com/Forums/en-US/7b12f8b2-d0e6-4f63-a98a-019356183c29/getting-past-wsus-cleanup-wizard-time-out-removing-unnecessary-updates?forum=winserverwsus

Although useful, note that the thread contains some unkind words to one of the thread participants. It also spreads out the advice I ended up using across the discussion.

The thread is full of good insight, and well worth reading. However, I thought it would be helpful to consolidate what I ended up using to solve our issue.

First, the problem: WSUS uses an internal database to store its updates. The Server Cleanup wizard calls a stored procedure which tries to expire all old updates at once, and this times out and makes the Cleanup Wizard hang. Usually, we want atomic all-or-nothing operations in databases, so when the expiry times out the database helpfully rolls back expired updates, leaving us in the position we started.

In addition to having too many updates it appears that certain obsolete updates have a large number of revisions, which also slows the clearout process down. Once these troublesome updates are expired, the rest of the cleanup can be handled relatively efficiently.

To solve the problem, you log into the database directly and run a script that expires updates one by one. Troublesome updates take a long time to expire, but they don't hit the timeout value, so eventually all updates get cleared.

Second: the steps. This boils down to running the following script, provided by user __Russ__ on the forums, based on code by vexation. (Sorry about the long line. I do not know how to safely insert linebreaks into the script and am not going to bother finding out.)

--************** vexation code with my small changes
USE SUSDB
DECLARE @var1 INT, @curitem INT, @totaltodelete INT
DECLARE @msg nvarchar(200)
CREATE TABLE #results (Col1 INT) INSERT INTO #results(Col1)
EXEC spGetObsoleteUpdatesToCleanup
SET @totaltodelete = (SELECT COUNT(*) FROM #results)
SELECT @curitem=1
DECLARE WC Cursor FOR SELECT Col1 FROM #results
OPEN WC
FETCH NEXT FROM WC INTO @var1 WHILE (@@FETCH_STATUS > -1)
BEGIN SET @msg = cast(@curitem as varchar(5)) + '/' + cast(@totaltodelete as varchar(5)) + ': Deleting ' + CONVERT(varchar(10), @var1) + ' ' + cast(getdate() as varchar(30))
RAISERROR(@msg,0,1) WITH NOWAIT
EXEC spDeleteUpdate @localUpdateID=@var1
SET @curitem = @curitem +1
FETCH NEXT FROM WC INTO @var1
END
CLOSE WC
DEALLOCATE WC
DROP TABLE #results

Later in the thread there is some Powershell script that is supposed to do the same thing, but it did not work for me.

There a few takehome lessons for me from this: