I recently added Windows 10 to my WSUS Product and Classifications and got very surprised by the 100 GB of updates that was queued for download! Let’s learn how to clean up WSUS content folder.
Unfortunately, cancelling the download queued is not that straight forward, so I decided to use the opportunity to clean up my WSUS content folder and reclaim my VMFS datastore at the same time.
The reason why the updates where 100 GB was because I had all Classifications selected and an Automatic Approval Rule! After the changes below the updates where only 1 GB.
Lesson Learned, Be Careful with Automatic Approval Rules…
Clean Up WSUS
Before you start make sure to disable your Automatic Approval Rule(s). I have a very nice script below that saved me 300% of downloads.
It’s also a good time to verify that only the Products and Languages you actually need are selected.
From Update Files and Languages, make sure that you don’t have Express installation files selected.
Let’s clean up WSUS by running the following commands:
1 2 3 4 5 6 |
net stop wsusservice cd "C:\Program Files\Update Services\Tools" wsusutil.exe reset echo Delete WSUS Folder Content pause net start wsusservice |
Take a look in Task Manager and you’ll see that the process “SQL Server Windows NT – 64 bit” is consuming all the CPU. This is because all database tables are being checked and any missing hotfixes are being marked for download.
This could take up to 30-60 minutes to complete, depending on the Products and Classifications you have. When the CPU drops you’re ready to proceed.
Let’s start Synchronization.
The thing with WSUS is that it’s going to download everything, even superseded updates. Now the purpose of this post is to also reclaim VMFS storage, so downloading all and then deleting them won’t help much. Luckily there’s a script for that.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
#Change server name and port number and $True if it is on SSL $Computer = $env:COMPUTERNAME $Domain = $env:USERDNSDOMAIN $FQDN = "$Computer" + "." + "$Domain" [String]$updateServer1 = $FQDN [Boolean]$useSecureConnection = $False [Int32]$portNumber = 8530 # Load .NET assembly [void][reflection.assembly]::LoadWithPartialName("Microsoft.UpdateServices.Administration") $count = 0 # Connect to WSUS Server $updateServer = [Microsoft.UpdateServices.Administration.AdminProxy]::getUpdateServer($updateServer1,$useSecureConnection,$portNumber) write-host "<<<Connected sucessfully >>>" -foregroundcolor "yellow" $updatescope = New-Object Microsoft.UpdateServices.Administration.UpdateScope $u=$updateServer.GetUpdates($updatescope ) foreach ($u1 in $u ) { if ($u1.IsSuperseded -eq 'True') { write-host Decline Update : $u1.Title $u1.Decline() $count=$count + 1 } } write-host Total Declined Updates: $count trap { write-host "Error Occurred" write-host "Exception Message: " write-host $_.Exception.Message write-host $_.Exception.StackTrace exit } # EOF |
Open PowerShell ISE as Administrator and run the script.
WOW! Do you belive that? Out of 6467 updates, 4179 where declined.
Now run the Automatic Approval Rule to start the downloads.
Many people might argue that is unnecessary to run the wsusutil.exe reset command, simply because all updates will be re-downloaded.
Well, you could always search and decline all updates you don’t want and then run the Server Cleanup Wizard, but its PITA.
My WSUS folder went from 75 GB to 20 GB so I’m happy.
Reclaim VMFS Datastore
I’m not sure if you’re aware, but when you’re using Thin Provisioning it doesn’t matter if you delete unwanted files. When the space has been alllocated it will stay that way until you do the following steps below.
My WSUS folder was located on C: then moved to D: and finally E:
To reclaim the space after all unnecessary files has been deleted run sDelete on all volumes.
1 |
sdelete –z c: |
When finished shutdown the VM and connect to your ESXi host through Putty.
Navigate to your VMFS datastore folder for that VM.
1 2 |
cd /vmfs/volumes/Samsung850EVO/MDT-01 ls |
Now run the following command for all disks:
1 |
vmkfstools -K MDT-01.vmdk |
Power up the VM and enjoy. I reclaimed 120 GB in 2 hours on just 1 VM!
Excellent script, is there a way to have it decline the itanium updates as well?
Thanks, I guess so but I haven’t looked or had the need to do so.
I think this would be a nice feature as well.
I figured it out, you can just change the line to say if ($u1.IsSuperseded -eq ‘True’ -Or $u1.Title -like ‘*Itanium*’)
Thanks for sharing Rob.
Tip to build on Rob’s answer:
if ($u1.IsSuperseded -eq ‘True’ -Or $u1.Title -like ‘*Itanium*’ -Or $u1.Title -like ‘*Preview*’)
will also block the “preview” builds of patches. Saves an additional 500 downloads or so.
In case anyone pastes this in, they might need to change any ‘ to ‘ as PowerShell gives an error with the wrong type of quote mark.
Hi
thanks for the script however my server name has a hyphen “abc-def” and the script errors!
Open in PowerShell ISE and look for strange characters.
Same issue here. Computers/servers are named: “geographical location-server number”
PS is not accepting the –
I did “servername” but that is also not accepted.
Any suggestions
Maybe this is obvious and I’m just being dense, but in the batch file what is the “echo Delete WSUS Folder Content” for? Am I supposed to manually delete this folder and then allow the batch file to continue?
Correct, or you could add a line to do this automatically. Just don’t want to delete stuff without you knowing.
The script to decline the updates keeps failing. Getting this when trying to run it:
Error Occurred
Exception Message:
The specified string is invalid.
Parameter name: ServerName
at Microsoft.UpdateServices.Administration.AdminProxy.CreateUpdateServer(Object[] args)
at CallSite.Target(Closure , CallSite , RuntimeType , Object , Object , Object )
Try to set $ComputerName = instead.
Still getting error
Error Occurred
Exception Message:
The specified string is invalid.
Parameter name: ServerName
at Microsoft.UpdateServices.Administration.AdminProxy.CreateUpdateServer(Object[] args)
at Microsoft.UpdateServices.Administration.AdminProxy.GetUpdateServer(String serverName, Boolean useSecureConnection, Int32 portNumber)
at GetUpdateServer(Object , Object[] )
at System.Management.Automation.MethodInformation.Invoke(Object target, Object[] arguments)
at System.Management.Automation.DotNetAdapter.AuxiliaryMethodInvoke(Object target, Object[] arguments, MethodInformation methodInformation, Object[] originalArguments)
Try setting your server name fixed instead. $Computer = TYPEYOURSERVERNAME
I’ve tried all the various suggestions (including using the FQDN for the server) and still get the following:
Error Occurred
Exception Message:
The specified string is invalid.
Parameter name: ServerName
at Microsoft.UpdateServices.Administration.AdminProxy.CreateUpdateServer(Object[] args)
at CallSite.Target(Closure , CallSite , RuntimeType , Object , Object , Object )
What OS are you on?
Windows 2012 R2.
Thanks!
Make sure you’re running PowerShell as Administrator.
Great post used it on a new WSUS setup. Before doing your steps I was it over 300 GB of updates. Redid the sever now only downloading 62 GB. Total Declined Updates: 3690
Thanks
AWESOME
This was very helpful. I went from 600GB down to 84GB of WSUS storage.
Awesome, just saw a tweet on someone saving same as you, amazing 0.5TB….!!!
it should be: “.\WsusUtil.exe reset” otherwise you get an error that it cannot find the program (“mistyped”)
Does the script need to be run from the wsus server itself? or can you run it from another server? i am getting the same errors as Vivek
Please ignore this, managed to sort the issue. Needed to enter the fqdn for the server.
You need to run it from your WSUS server. What OS are you trying on?
Hi
I am getting the below error when running the script:
Exception calling “GetUpdates” with “1” argument(s): “The operation has timed out”
At line:1 char:1
+ $u=$updateServer.GetUpdates($updatescope )
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : WebException
Any idea why I am getting the above exception when running the script. Your answer is highly appreciated.
I get the below error while running the script in the second box of the page. Any thoughts?
Error Occurred
Exception Message:
Method invocation failed because [System.String] does not contain a method named ‘GetU
pdates’.
at CallSite.Target(Closure , CallSite , Object , Object )
at System.Management.Automation.Interpreter.DynamicInstruction`3.Run(InterpretedFra
me frame)
at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(Int
erpretedFrame frame)
Please ignore my earlier message, Got it to work. Thanks anyways!
Great Jason, could you share what you did to fix it? Seems like many are having similar issues.
Hi, I cannot run this script normally, after running it about 2-3 mins it returns error, here is my result:
<<>>
Error Occurred
Exception Message:
要求已經中止: 作業逾時。 <
Hi, I cannot run this script normally, after running it about 2-3 mins it returns error, here is my result:
Connected sucessfully
Error Occurred
Exception Message:
要求已經中止: 作業逾時。 (it means request has stopped: time out.)
於 System.Web.Services.Protocols.WebClientProtocol.GetWebResponse(WebRequest request
)
於 System.Web.Services.Protocols.HttpWebClientProtocol.GetWebResponse(WebRequest req
uest)
於 Microsoft.UpdateServices.Internal.DatabaseAccess.ApiRemotingCompressionProxy.GetW
ebResponse(WebRequest webRequest)
於 System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String methodName, Ob
ject[] parameters)
於 Microsoft.UpdateServices.Internal.ApiRemoting.ExecuteSPSearchUpdates(String updat
eScopeXml, String preferredCulture, Int32 publicationState)
於 Microsoft.UpdateServices.Internal.DatabaseAccess.AdminDataAccessProxy.ExecuteSPSe
archUpdates(String updateScopeXml, String preferredCulture, ExtendedPublicationState p
ublicationState)
於 Microsoft.UpdateServices.Internal.BaseApi.Update.SearchUpdates(UpdateScope search
Scope, ExtendedPublicationState publicationState, UpdateServer updateServer)
於 CallSite.Target(Closure , CallSite , Object , Object )
How can I solve this problem?
Are you using a Proxy?
Nope, no proxy used.
I try to follow the script, and I found it stopped here.
$u=$updateServer.GetUpdates($updatescope )
so, the connection is done, but it cannot get updates?
I ran this script after stop wsusservice and reset wsus, then start wsusservice, make sure SQL server 64-bit job was stabled. so what may cause timeout? too lower level’s vm? ram? or something?
Hi, I was also getting the timeout (3 minutes) at that step. Reindexing the WSUS Database did the trick. Now “declining” updates at full speed.
Reindex the WSUS Database:
https://technet.microsoft.com/en-us/library/dd939795(v=ws.10)
Next thing I was going to try (Timeout parameters):
https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/new-pssessionoption
Thanks for the post!
I am using the script unchanged and I too have the same problem on a 2012 R2 Server as follows:
<<>>
Error Occurred
Exception Message:
The operation has timed out
at System.Web.Services.Protocols.WebClientProtocol.GetWebResponse(WebRequest request)
at System.Web.Services.Protocols.HttpWebClientProtocol.GetWebResponse(WebRequest request)
at Microsoft.UpdateServices.Internal.DatabaseAccess.ApiRemotingCompressionProxy.GetWebResponse(WebRequest webRequest)
at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String methodName, Object[] parameters)
at Microsoft.UpdateServices.Internal.ApiRemoting.ExecuteSPSearchUpdates(String updateScopeXml, String preferredCultur
e, Int32 publicationState)
at Microsoft.UpdateServices.Internal.DatabaseAccess.AdminDataAccessProxy.ExecuteSPSearchUpdates(String updateScopeXml
, String preferredCulture, ExtendedPublicationState publicationState)
at Microsoft.UpdateServices.Internal.BaseApi.Update.SearchUpdates(UpdateScope searchScope, ExtendedPublicationState p
ublicationState, UpdateServer updateServer)
at CallSite.Target(Closure , CallSite , Object , Object )
Any Ideas?
Kind regards,
Chris
Thanks Chris, I’ll give it a go on Windows 2012 and see what happens to get this problem solved once and for all.
Ok guys i had the same problem with the dash in the hostname,and made it work with your suggestion to evek.
Thanks for the great post.
Thanks Maicon
i see a few techs having issues with server name….can you post on how you worked out the problem?
I ended up renaming my VM and it worked fine – I tried everything to get it to work with hyphenated host name and couldn’t
I have not checked above solution , However Following command help me clean the WSUS server . Run all the command one by one – if you get any error like ” Invoke-WsusServerCleanup : Execution Timeout Expired.
Re-run the command till it give you result. I cleaned up around 250 GB
Invoke-WsusServerCleanup -CleanupUnneededContentFiles
Invoke-WsusServerCleanup -DeclineExpiredUpdates
Invoke-WsusServerCleanup -CleanupObsoleteComputers
Invoke-WsusServerCleanup -CleanupObsoleteUpdates
Invoke-WsusServerCleanup -CleanupUnneededContentFiles
Invoke-WsusServerCleanup -CompressUpdates
Thanks for sharing Nitin.
Hi,
i trying scripts but all ending with this
Invoke-WsusServerCleanup : Execution Timeout Expired. The timeout period elapsed prior to completion of the operation or the server is not responding.
In SQL i have connction timeout set to 0
Hello,
Thanks for the great infos and scripts but I’ve a question.
When doing the procedure should not the Approved And Declined update get back to 0?
In my case I still see the previous horrendous count of 6k approved and 7k declined.
Did I do something wrong? When starting the service again I noticed the CPU climbing up but not for more than 5-6 minutes.
Regards
Hi, they won’t go back to 0, but the number of Declined show go up. If the CPU is high for a short time, means that you have a powerful server 🙂
Hi, the PS script is not working for me:
Error Occurred
Exception Message:
Invalid URI: The hostname could not be parsed.
at Microsoft.UpdateServices.Administration.AdminProxy.CreateUpdateServer(Object[] args)
at Microsoft.UpdateServices.Administration.AdminProxy.GetUpdateServer(String serverName, Boolean useSecureConnection, Int32 portNumber)
at CallSite.Target(Closure , CallSite , RuntimeType , Object , Object , Object )
Exception calling “GetUpdateServer” with “3” argument(s): “Invalid URI: The hostname could not be parsed.”
At line:14 char:1
+ $updateServer = [Microsoft.UpdateServices.Administration.AdminProxy]::getUpdateS …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : UriFormatException
<<>>
Error Occurred
Exception Message:
You cannot call a method on a null-valued expression.
at CallSite.Target(Closure , CallSite , Object , Object )
at System.Dynamic.UpdateDelegates.UpdateAndExecute2[T0,T1,TRet](CallSite site, T0 arg0, T1 arg1)
at System.Management.Automation.Interpreter.DynamicInstruction`3.Run(InterpretedFrame frame)
at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
You cannot call a method on a null-valued expression.
At line:20 char:1
+ $u=$updateServer.GetUpdates($updatescope )
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
OS: Windows Server 2012 R2
HELP PLEASE!!!
Please try to set $Computer = YOURCOMPUTERNAME
Can confirm, I was having the same issue. I changed line 3 from
$Computer = $env:COMPUTERNAME
to
$Computer = “YourServerName” (include the parentheses)
Doing this got the script to run.
Yes, seems like older version of PowerShell is unable to get $env:computername
Hi,
I’m confused on where exactly to run the script. I’ve done the reset.
Pls help.
Thanks.
You need to run it on your WSUS server.
actually i was referring to the 2nd script
#Change server name and port number and $True if it is on SSL
I opened powershell and copy the whole thing and change the computer name but noting seems to happen…the whole 350GB data keep downloading after i cleared up the WSUS content folder
PS C:\Windows\system32> $updateServer = [Microsoft.UpdateServices.Administration.AdminProxy]::getUpdateServer($updateSer
ver1,$useSecureConnection,$portNumber)
Exception calling “GetUpdateServer” with “3” argument(s): “The specified string is invalid.
Parameter name: ServerName”
At line:1 char:1
+ $updateServer = [Microsoft.UpdateServices.Administration.AdminProxy]::getUpdateS …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : ArgumentException
PS C:\Windows\system32>
PS C:\Windows\system32> write-host “<<>>” -foregroundcolor “yellow”
<<>>
PS C:\Windows\system32>
PS C:\Windows\system32> $updatescope = New-Object Microsoft.UpdateServices.Administration.UpdateScope
PS C:\Windows\system32>
PS C:\Windows\system32> $u=$updateServer.GetUpdates($updatescope )
You cannot call a method on a null-valued expression.
At line:1 char:1
+ $u=$updateServer.GetUpdates($updatescope )
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
If you get error:
Error Occurred
Exception Message:
The specified string is invalid.
Parameter name: ServerName
Change line 4 to: $Computer = $env:ComputerName
Strange, that makes no sense since that value is already set on line 3. I’m wondering if the problems are related to PowerShell version.
I have an issue with my WSUS server and I would love your advice. In an effort to clean up the server I selected the option under “Update Files and Languages” to “Do not store updates files locally; computers install from Microsoft Update”. Since the status has been “Cannot save configuration because the server is still processing a previous configuration change”. My plan was to set that option, run the cleanup wizard to purge the updates and then set it back to storing updates locally. It’s been over 24hrs and the status is the same. From what I’ve read there’s not a lot of ways to stop this. Ideas? Suggestions? Thanks!
Hi Jack, exactly what happened with me, no way to stop this, so just follow the post and get every cleaned up. I’ve seen people sawing over 1TB of data…
Hi Trond,
I don’t mean to spam your blog post, but can I offer an alternative, and a much better, more user friendly way of cleaning out WSUS for your readers. It does way more than what you’re post says, and it’s so easy to setup and use.
Have a peek at my Adamj Clean-WSUS script. It is the last WSUS Script you will ever need!
http://community.spiceworks.com/scripts/show/2998-adamj-clean-wsus
What it does:
1. Add WSUS Index Optimization to the database to increase the speed of many database operations in WSUS by approximately 1000-1500 times faster.
2. Remove all Drivers from the WSUS Database (Default; Optional).
3. Shrink your WSUSContent folder’s size by declining multiple types of updates including by default any superseded updates, preview updates, expired updates, Itanium updates, and beta updates. Optional extras: Language Packs, IE7, IE8, IE9, IE10, Embedded, NonEnglishUpdates, ComputerUpdates32bit, WinXP.
4. Remove declined updates from the WSUS Database.
5. Clean out all the synchronization logs that have built up over time (configurable, with the default keeping the last 14 days of logs).
6. Compress Update Revisions.
7. Remove Obsolete Updates.
8. Computer Object Cleanup (configurable, with the default of deleting computer objects that have not synced within 30 days).
9. Application Pool Memory Configuration to display the current private memory limit and easily set it to any configurable amount including 0 for unlimited. This is a manual execution only.
10. Checks to see if you have a dirty database, and if you do, fixes it. This is primarily for Server 2012 WSUS, and is a manual execution only.
11. Run the Recommended SQL database Maintenance script on the actual SQL database.
12. Run the Server Cleanup Wizard.
It will email the report out to you or save it to a file, or both.
Although the script is lengthy, it has been made to be super easy to setup and use so don’t over think it. There are some prerequisites and instructions at the top of the script. After installing the prerequisites and configuring the variables for your environment (email settings only if you are accepting all the defaults), simply run:
.\Clean-WSUS.ps1 -FirstRun
If you wish to view or increase the Application Pool Memory Configuration, or run the Dirty Database Check, you must run it with the required switch. See Get-Help .\Clean-WSUS.ps1 -Examples
If you’re having trouble, there’s also a -HelpMe option that will create a log so you can send it to me for support.
Awesome Adam, sharing is caring 🙂
To resolve error with regards to Servername
——-
Error Occurred
Exception Message:
The specified string is invalid.
Parameter name: ServerName
at Microsoft.UpdateServices.Administration.AdminProxy.CreateUpdateServer(Object[] args)
at CallSite.Target(Closure , CallSite , Type , Object , Object , Object )
——-
You need not change anything from the script. Just run it as is and run Windows Powershell ISE as Administrator. Running Windows Server 2012 R2.
Thanks.
Thanks, will update the post
I was having the same problem related to the hostname inside the PowerShell script. I have managed to solve it using:
$Computer = “FULL_FQDN_HOSTNAME” (using quotation marks)
Thanks for this great post!!!
Great Diego, thanks for sharing.
Thanks for that !!!
How do the script declining the updates take care of superseeded updates which is needed by some computers in my organization. Sorry for my inability to understand Powershell. I have understood that updates needed by a computer in my organisation should not be made inavailable.
/Finn Knudsen
The script doesn’t do that, it simply disables/remove updates that has been replaced by another one. I guess you can manually add those after running the script?
For those having issues with hostnames and hyphens change:
$Computer = $env:COMPUTERNAME
$Domain = $env:USERDNSDOMAIN
$FQDN = “$Computer” + “.” + “$Domain”
to:
$FQDN = “server.domain.local”
Excellent post Trond! Thank you so much and Tom thanks for the tip. I was about to pull my hair out.
This worked for me after several attempts with changing the first two lines to all sorts of stuff. Kept getting errors until I commented out the $computer and $domain lines and only used the suggested $FQDN = “my WSUS.myDOMAIN.myDomainSuffix”
I updated the server name and domain name.
Ran the script
Got no feedback. Just closed the PS ISE window.
Did not get any window saying what it did.
Nothing in event viewer.
No change in the data store size.
Resynced and ran server cleanup and no change.
I ran the script in PS in admin mode. This is where it errors out.
Any help would be great.
PS C:\Users\Kamran.Manii> $updateServer = [Microsoft.UpdateServices.Administration.AdminProxy]::getUpdateServer($updateS
erver1,$useSecureConnection,$portNumber)
Exception calling “GetUpdateServer” with “3” argument(s): “The specified string is invalid.
Parameter name: ServerName”
At line:1 char:1
+ $updateServer = [Microsoft.UpdateServices.Administration.AdminProxy]::getUpdateS …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : ArgumentException
PS C:\Users\Kamran.Manii>
PS C:\Users\Kamran.Manii> write-host “<<>>” -foregroundcolor “yellow”
<<>>
PS C:\Users\Kamran.Manii>
PS C:\Users\Kamran.Manii> $updatescope = New-Object Microsoft.UpdateServices.Administration.UpdateScope
PS C:\Users\Kamran.Manii>
PS C:\Users\Kamran.Manii> $u=$updateServer.GetUpdates($updatescope )
You cannot call a method on a null-valued expression.
At line:1 char:1
+ $u=$updateServer.GetUpdates($updatescope )
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
Hi people,
i found out if i have a wsus server that i named it as Up-Stream-WSUS, you have to remove line no 3,4 and 5 and replace $FQDN with “Up-Stream-WSUS”. Then open PS with admin rights and run the script. It will perform flawlessly.
I am a lazy person who do not want to reset and sync the database again. So after running the script i performed the command below as suggested by nitin
Invoke-WsusServerCleanup -CleanupUnneededContentFiles
Invoke-WsusServerCleanup -DeclineExpiredUpdates
Invoke-WsusServerCleanup -CleanupObsoleteComputers
Invoke-WsusServerCleanup -CleanupObsoleteUpdates
Invoke-WsusServerCleanup -CleanupUnneededContentFiles
Invoke-WsusServerCleanup -CompressUpdates
It shaved quite 50GB of disk spaces. Before it was 60GB of disk space
Cheers to Trond Eirik Haavarstein. Without your script, my wsus would have exploded due to windows defender definition updates. Windows Definition updates is exploding my WSUS.
My WSUS server is sitting behind a Proxy server which required authentication. The script was timing out before I ran the following commands:
$UserCredential = Get-Credential
New-PSSessionOption -ProxyAccessType IEConfig -ProxyAuthentication Negotiate -ProxyCredential $UserCredential
Then I ran the script again & it worked a treat…
Thanks Trond..
Just use the WSUS Server Cleanup Wizard. No need for all the scripts. Takes a little while to run but it will remove all of the declines and superseded updates automatically. Click on Options and look for the wizard.
You are right Marc, it does but the intention is to prevent downloading everything (even those not need) and then cleaning it up by deleting them. If you use Thin disk provisioning there’s no easy way back and you waste space. That’s the intention of the script.
Just want to say this was an Awesome Script, Using it on Windows Server 2016 Data Center Addition. Over 6757 Declined Updates. Nice Post thank you.
Thanks Greg, have a customer that saw 1TB of data…!!!
Greetings Trond.
I have tried everything suggested in the comments but still get
<<>>
Error Occurred
Exception Message:
The operation has timed out
at System.Web.Services.Protocols.WebClientProtocol.GetWebResponse(WebRequest request)
at Microsoft.UpdateServices.Internal.DatabaseAccess.ApiRemotingCompressionProxy.GetWebResponse(WebRequest webRequest)
at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String methodName, Object[] parameters)
at Microsoft.UpdateServices.Internal.ApiRemoting.ExecuteSPSearchUpdates(String updateScopeXml, String preferredCultur
e, Int32 publicationState)
at Microsoft.UpdateServices.Internal.DatabaseAccess.AdminDataAccessProxy.ExecuteSPSearchUpdates(String updateScopeXml
, String preferredCulture, ExtendedPublicationState publicationState)
at Microsoft.UpdateServices.Internal.BaseApi.Update.SearchUpdates(UpdateScope searchScope, ExtendedPublicationState p
ublicationState, UpdateServer updateServer)
at CallSite.Target(Closure , CallSite , Object , Object )
I am not using a proxy, My server has unrestricted access to the web. I tried changing secure connection to True. I added a NewPSSessionOption for the timeout to unlimited and I let it run overnight and the script was still in the same spot when I came back. When I started I had around 600gb of updates on the server, when I went through the first script and deleted the wsus content and reset updates it has downloaded 100gb now already.
Are there any other recommendations you have to getting this to run correctly?
Did you try to set the server name directly?
$Computer = “WSUS-01”
No this because we download the EXE not the MSI, but you could extract MSI fra EXE and then use MST.
did you manage to get it working i got the same error
Hi,
Can you tell me where is the Server name that i need top change in this script to match my server, please?
Nice work by the way.
First line : $Computer = $env:COMPUTERNAME
Hi, thank you for the script. Is there a way to delete only client superseded updates?
Hi, I’ve not looked into that part.
Hi, I don’t see any resolution for the Win2K12R2 WSUS timeout issue as per the above from others.
Anything at all will help.
I cannot overcome this issue.
Thank you
Hi George, what’s your issue? Just try to set the ComputerName manually as stated in the newest comments.
Hyphens / dashes “-” cause issues in SQL Instance Names. Line 18 will fail if there is a hyphen in the sql instance name. Likely because the hyphen would be treated like a math symbol minus sign in a sql connection statements, etc.. Anyone having that issue can use the IP address,port instead of the servername,port since this is also a valid way of providing a connection string since the port specifies specifically which SQL instance to connect to. Of course the proper thing to do would be to not use Hyphens in Computer Names as they cause issues with DNS registration, SQL Instance Names, Etc…. Example Line 18:
$updateServer = [Microsoft.UpdateServices.Administration.AdminProxy]::getUpdateServer(127.0.0.1,$useSecureConnection,$portNumber)
Thanks a lot Tray for sharing.
Great, perfect solution for me.
600 GB partition only for WSUS – full.
After using this scripts – 73 GB
Thanks!!!!
Awesome Alex, thanks for sharing your results.
After Deleting the WSUS content folder and reseting WSUSservice, When I open the console, it says loading and then fails and shows “Error Connection Error”
I tried recovering the WSUS content from backup and still no use. Please help.
Great Script, Thank you..
I’m running it on Windows Server 2019 Dc addition, no problems.
This was a great script and a huge help. I had 300GB of content on my e drive and after fising the computername and domain name by dropping the env: and in quotes putting the 2 entries it ran through like a typewriter.
Total Declined Updates: 10611
Total Required Updates: 740
300Gb down to 90Gb
I just keep getting
missing closing ‘}’ in statement block or type definition
Also hyphens in my server name and domain mane. First time using ICE and it replaces the -s with -split??
Please use PowerShell ISE
After changing the port for SSL, we receive the error below when running this. Any suggestions on how to resolve?
Error Occurred
Exception Message:
The underlying connection was closed: An unexpected error occurred on a receive.
at Microsoft.UpdateServices.Administration.AdminProxy.CreateUpdateServer(Object[] args)
at CallSite.Target(Closure , CallSite , Type , String , Boolean , Int32 )
And, were were using Powershell ISE for this.
Still the ‘timed oud’ issue with Server 2012 R2 unfortunately…
Tried with server name as well.
Any solution?
No sorry, maybe time for an upgrade…
Thanks man, working good on Windows Server 2019. Going down from 300GB to 40GB 🙂
I am so glad I ran across this! It worked like a charm for me. How often should this process need to be done to keep from getting back into the same old drive space issue?
It all depends on the number of updates approved, but at least 4 times a year, maybe more often if you have updates for Office, SQL etc
Excellent I free up 2 TB of disk space, only running the script then WSUS cleanup standard process. Thanks a lot.
Excelente, he liberado 2 TB. de disco, solu ejecutando el script y después pasando el asistente de limpieza integrado en WSUS. Muchas gracias.
I am getting the errror below when runnig the script. I think it is due to the .dom at the end of the domain server but I am not sure as I am just starting to learn powershell. Please help.
$Computer = $env:TSWSUS02
$Domain = $companyname.dom
Invalid URI: The hostname could not be parsed.
at Microsoft.UpdateServices.Administration.AdminProxy.CreateUpdateServer(Object[] args)
at CallSite.Target(Closure , CallSite , Type , Object , Object , Object )
Hi Brad, this is wrong, try this
$Computer = “TSWSUS02”
HI,
Im getting the below error, is anyone able to offer any guidance?
Error Occurred
Exception Message:
The operation has timed out
at System.Web.Services.Protocols.WebClientProtocol.GetWebResponse(WebRequest request)
at Microsoft.UpdateServices.Internal.DatabaseAccess.ApiRemotingCompressionProxy.GetWebResponse(WebRequest webRequest)
at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String methodName, Object[] parameters)
at Microsoft.UpdateServices.Internal.ApiRemoting.ExecuteSPSearchUpdates(String updateScopeXml, String preferredCulture, In
t32 publicationState)
at Microsoft.UpdateServices.Internal.DatabaseAccess.AdminDataAccessProxy.ExecuteSPSearchUpdates(String updateScopeXml, Str
ing preferredCulture, ExtendedPublicationState publicationState)
at Microsoft.UpdateServices.Internal.BaseApi.Update.SearchUpdates(UpdateScope searchScope, ExtendedPublicationState public
ationState, UpdateServer updateServer)
at CallSite.Target(Closure , CallSite , Object , Object )
Cheers
Rob
dude i had t he same error. make sure to run ise as admin and in x86.
Very god job.
It works for me.
Hanks.
Error Occurred
Exception Message:
The operation has timed out
at System.Web.Services.Protocols.WebClientProtocol.GetWebResponse(WebRequest request)
at Microsoft.UpdateServices.Internal.DatabaseAccess.ApiRemotingCompressionProxy.GetWebResponse(WebRequest webRequest)
at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String methodName, Object[] parameters)
at Microsoft.UpdateServices.Internal.ApiRemoting.ExecuteSPSearchUpdates(String updateScopeXml, String preferredCulture, Int32 publica
tionState)
at Microsoft.UpdateServices.Internal.DatabaseAccess.AdminDataAccessProxy.ExecuteSPSearchUpdates(String updateScopeXml, String preferr
edCulture, ExtendedPublicationState publicationState)
at Microsoft.UpdateServices.Internal.BaseApi.Update.SearchUpdates(UpdateScope searchScope, ExtendedPublicationState publicationState,
UpdateServer updateServer)
at CallSite.Target(Closure , CallSite , Object , Object )
Thank you so much!! This took my update folder size from 600GB to just 35GB!!
Any chance we could remove updates by date? I’ve got updates from 2017 I don’t want to download
Script works well – I’ve gone from 550GB to 110GB
For those that experience “Invalid URI: The hostname could not be parsed.”, make sure the hostname field is blank while looking at the bindings in IIS for the WSUS Administration site.
Thanks Adam.
I found a “short” version of this.
Fault. Server Cleanup Wizard in WSUS will not clean anything…
Step one. Run the above script:
_______________________________________________________________________________________
#Change server name and port number and $True if it is on SSL
$Computer = $env:COMPUTERNAME
$Domain = $env:USERDNSDOMAIN
$FQDN = “$Computer” + “.” + “$Domain”
[String]$updateServer1 = $FQDN
[Boolean]$useSecureConnection = $False
[Int32]$portNumber = 8530
# Load .NET assembly
[void][reflection.assembly]::LoadWithPartialName(“Microsoft.UpdateServices.Administration”)
$count = 0
# Connect to WSUS Server
$updateServer = [Microsoft.UpdateServices.Administration.AdminProxy]::getUpdateServer($updateServer1,$useSecureConnection,$portNumber)
write-host “<<>>” -foregroundcolor “yellow”
$updatescope = New-Object Microsoft.UpdateServices.Administration.UpdateScope
$u=$updateServer.GetUpdates($updatescope )
foreach ($u1 in $u )
{
if ($u1.IsSuperseded -eq ‘True’)
{
write-host Decline Update : $u1.Title
$u1.Decline()
$count=$count + 1
}
}
write-host Total Declined Updates: $count
trap
{
write-host “Error Occurred”
write-host “Exception Message: ”
write-host $_.Exception.Message
write-host $_.Exception.StackTrace
exit
}
# EOF
_______________________________________________________________________________________
Then run this script in PS as admin:
$wsus = [Microsoft.UpdateServices.Administration.AdminProxy]::getUpdateServer()
[reflection.assembly]::LoadWithPartialName(“Microsoft.UpdateServices.Administration”) | Out-Null
$wsus.getupdates() | Where {$_.isdeclined -match ‘true’} | ForEach-Object { $wsus.DeleteUpdate($_.Id.UpdateID); Write-Host $_.Title removed }
Now it´s time to try Server Cleanup Wizard again 🙂
If the first script gives a “Permission Error” it´s most likley to be this missing in .NET web.config file:
web.config location:
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Config (Ver. depends on your .NET version)
ADD
Awesome script!! Saved me a lot of time.
Lots of comments to read… so if someone has posted this forgive the duplicate.
The original first 3 line we modified because we have “-” in our server names. Here is our modifications.
$Computer = “wsus-01”
$Domain = “domain.local”
This resolved out error issue.
But if you do this you could further modify line 3, removing the 2 above lines
from $FQDN = “$Computer” + “.” + “$Domain”
to $FQDN = “wsus-01.domain.local”.
Hope this helps
Hello Everyone
I got another error, maybe someone can help here:
Exception Message:
Method invocation failed because [System.String] does not contain a method named ‘GetUpdates’.
at CallSite.Target(Closure , CallSite , Object , Object )
at System.Dynamic.UpdateDelegates.UpdateAndExecute2[T0,T1,TRet](CallSite site, T0 arg0, T1 arg1)
at System.Management.Automation.Interpreter.DynamicInstruction`3.Run(InterpretedFrame frame)
at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
Method invocation failed because [System.String] does not contain a method named ‘GetUpdates’.
At line:22 char:1
+ $u=$updateServer.GetUpdates($updatescope )
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound
Would be grateful for any help.