ML
    • Recent
    • Categories
    • Tags
    • Popular
    • Users
    • Groups
    • Register
    • Login

    WSUS Help

    IT Discussion
    14
    69
    4.5k
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • ObsolesceO
      Obsolesce
      last edited by

      If it would go as smoothly as Linux where you can let dnf automatic do it whenever and not kill your PC or server reliability , I'd use Windows more.

      1 Reply Last reply Reply Quote 0
      • siringoS
        siringo
        last edited by siringo

        Stumbled across this script, I'm no powershell expert, my limit is spelling it correctly. Anyone want to have a look at this?

        From here:
        https://www.powershellgallery.com/packages/PSWsusSpringClean/0.4.0/Content/PSWsusSpringClean.psm1

        Function Invoke-WsusSpringClean {
        <#
        .SYNOPSIS
        Performs additional WSUS server clean-up beyond the capabilities of the built-in tools.
        .DESCRIPTION
        Adds the ability to decline numerous additional commonly unneeded updates as well as discover potentially incorrectly declined updates.
        .PARAMETER RunDefaultTasks
        Performs all clean-up tasks except for declining any unneeded updates as defined in the included update catalogue CSV file.

            You can disable one or more of the default clean-up tasks by setting the associated switch parameter to false (e.g. -CompressUpdates:$false). 
        
            You can perform a clean-up of unneeded updates by specifying the DeclineCategoriesInclude or DeclineCategoriesExclude parameter with your chosen categories. 
        
            Also note that this does not perform a server synchronisation before clean-up or find suspect declined updates. These tasks can be included via their respective parameters. 
            .PARAMETER SynchroniseServer 
            Perform a synchronisation against the upstream server before running cleanup. 
            .PARAMETER FindSuspectDeclines 
            Scan all declined updates for any that may have been inadvertently declined. 
        
            The returned suspect updates are those which: 
             - Are not superseded or expired 
             - Are not cluster or farm updates (if set to decline) 
             - Are not in the filtered list of updates to decline from the bundled catalogue 
            .PARAMETER DeclineClusterUpdates 
            Decline any updates which are exclusively for failover clustering installations. 
            .PARAMETER DeclineFarmUpdates 
            Decline any updates which are exclusively for farm deployment installations. 
            .PARAMETER DeclinePrereleaseUpdates 
            Decline any updates which are exclusively for pre-release products (e.g. betas). 
            .PARAMETER DeclineSecurityOnlyUpdates 
            Decline any Security Only updates. 
            .PARAMETER DeclineArchitectures 
            Array of update architectures to decline. 
        
            Valid options are: x64, ia64, arm64 
        
            We don't support declining x86 updates as there's no mechanism to determine which updates are x86 specific versus multi-architecture. 
            .PARAMETER DeclineCategoriesExclude 
            Array of update categories in the bundled updates catalogue to not decline. 
            .PARAMETER DeclineCategoriesInclude 
            Array of update categories in the bundled updates catalogue to decline. 
            .PARAMETER DeclineLanguagesExclude 
            Array of update language codes to not decline. 
            .PARAMETER DeclineLanguagesInclude 
            Array of update language codes to decline. 
            .PARAMETER CleanupObsoleteComputers 
            Specifies that the cmdlet deletes obsolete computers from the database. 
            .PARAMETER CleanupObsoleteUpdates 
            Specifies that the cmdlet deletes obsolete updates from the database. 
            .PARAMETER CleanupUnneededContentFiles 
            Specifies that the cmdlet deletes unneeded update files. 
            .PARAMETER CompressUpdates 
            Specifies that the cmdlet deletes obsolete revisions to updates from the database. 
            .PARAMETER DeclineExpiredUpdates 
            Specifies that the cmdlet declines expired updates. 
            .PARAMETER DeclineSupersededUpdates 
            Specifies that the cmdlet declines superseded updates. 
            .EXAMPLE 
            PS C:\>$SuspectDeclines = Invoke-WsusSpringClean -RunDefaultTasks -FindSuspectDeclines 
        
            Runs the default clean-up tasks & checks for declined updates that may not be intentional. 
            .EXAMPLE 
            PS C:\>Invoke-WsusSpringClean -DeclineCategoriesInclude @('Region - US', 'Superseded') 
        
            Declines all unneeded updates in the "Region - US" & "Superseded" categories. 
            .EXAMPLE 
            PS C:\>Invoke-WsusSpringClean -DeclineLanguagesExclude @('en-AU') 
        
            Declines all language specific updates excluding those for English (Australia). 
            .EXAMPLE 
            PS C:\>Invoke-WsusSpringClean -DeclineArchitectures @('arm64', 'ia64') 
        
            Declines all architecture specific updates for ARM64 & IA64 (Itanium) systems. 
            .NOTES 
            The script intentionally avoids usage of most WSUS cmdlets provided by the UpdateServices module as many are extremely slow. This is particularly true of the Get-WsusUpdate cmdlet. 
        
            The efficiency of the update declining logic could be substantially improved. That said, this script is not typically run frequently (~monthly), so this isn't a major priority. 
            .LINK 
            https://github.com/ralish/PSWsusSpringClean 
        #>
        
        [CmdletBinding(DefaultParameterSetName='Default',SupportsShouldProcess)]
        Param(
            [Switch]$RunDefaultTasks,
            [Switch]$SynchroniseServer,
            [Switch]$FindSuspectDeclines,
        
            [Switch]$DeclineClusterUpdates,
            [Switch]$DeclineFarmUpdates,
            [Switch]$DeclinePrereleaseUpdates,
            [Switch]$DeclineSecurityOnlyUpdates,
        
            [String[]]$DeclineCategoriesExclude,
            [String[]]$DeclineCategoriesInclude,
        
            [ValidateScript({Test-WsusSpringCleanArchitectures -Architectures $_})]
            [String[]]$DeclineArchitectures,
        
            [ValidateScript({Test-WsusSpringCleanLanguageCodes -LanguageCodes $_})]
            [String[]]$DeclineLanguagesExclude,
        
            [ValidateScript({Test-WsusSpringCleanLanguageCodes -LanguageCodes $_})]
            [String[]]$DeclineLanguagesInclude,
        
            # Wrapping of Invoke-WsusServerCleanup
            [Switch]$CleanupObsoleteComputers,
            [Switch]$CleanupObsoleteUpdates,
            [Switch]$CleanupUnneededContentFiles,
            [Switch]$CompressUpdates,
            [Switch]$DeclineExpiredUpdates,
            [Switch]$DeclineSupersededUpdates
        )
        
        # Ensure that any errors we receive are considered fatal
        $ErrorActionPreference = 'Stop'
        
        if ($PSBoundParameters.ContainsKey('DeclineCategoriesExclude') -and $PSBoundParameters.ContainsKey('DeclineCategoriesInclude')) {
            throw 'Can only specify one of DeclineCategoriesExclude and DeclineCategoriesInclude.'
        }
        
        if ($PSBoundParameters.ContainsKey('DeclineLanguagesExclude') -and $PSBoundParameters.ContainsKey('DeclineLanguagesInclude')) {
            throw 'Can only specify one of DeclineLanguagesExclude and DeclineLanguagesInclude.'
        }
        
        if (!$script:WscMetadata) {
            Import-WsusSpringCleanMetadata
        }
        
        if ($RunDefaultTasks) {
            $DefaultTasks = @(
                'DeclineClusterUpdates',
                'DeclineFarmUpdates',
                'DeclinePrereleaseUpdates',
                'DeclineSecurityOnlyUpdates',
        
                'CleanupObsoleteComputers',
                'CleanupObsoleteUpdates',
                'CleanupUnneededContentFiles',
                'CompressUpdates',
                'DeclineExpiredUpdates',
                'DeclineSupersededUpdates'
            )
        
            foreach ($Task in $DefaultTasks) {
                if ($PSBoundParameters.ContainsKey($Task)) {
                    Set-Variable -Name $Task -Value (Get-Variable -Name $Task).Value -WhatIf:$false
                } else {
                    Set-Variable -Name $Task -Value $true -WhatIf:$false
                }
            }
        }
        
        # Regular expressions for declining certain types of updates
        $script:RegExClusterUpdates = ' Failover Clustering '
        $script:RegExFarmUpdates = ' Farm[- ]'
        $script:RegExPrereleaseUpdates = ' (Beta|Preview|RC1|Release Candidate) '
        $script:RegExSecurityOnlyUpdates = ' Security Only (Quality )?Update '
        
        # Determine which categories of updates to decline (if any)
        if ($PSBoundParameters.ContainsKey('DeclineCategoriesExclude') -or $PSBoundParameters.ContainsKey('DeclineCategoriesInclude')) {
            Import-WsusSpringCleanCatalogue
            $CatalogueCategories = $script:WscCatalogue.Category | Sort-Object | Get-Unique
        
            if ($PSBoundParameters.ContainsKey('DeclineCategoriesExclude')) {
                $DeclineCategories = $CatalogueCategories | Where-Object { $_ -notin $DeclineCategoriesExclude }
            } else {
                $DeclineCategories = $CatalogueCategories | Where-Object { $_ -in $DeclineCategoriesInclude }
            }
        }
        
        # Fetch the metadata for any architectures we're going to decline
        if ($PSBoundParameters.ContainsKey('DeclineArchitectures')) {
            $DeclineArchitecturesMetadata = @()
            foreach ($Architecture in $DeclineArchitectures) {
                $DeclineArchitecturesMetadata += $script:WscMetadata.SelectSingleNode('//Architectures/Architecture[@name="{0}"]' -f $Architecture)
            }
        }
        
        # Fetch the metadata for any languages we're going to decline
        if ($PSBoundParameters.ContainsKey('DeclineLanguagesExclude')) {
            $DeclineLanguagesMetadata = $script:WscMetadata.Languages.Language | Where-Object { $_.code -notin $DeclineLanguagesExclude }
        } elseif ($PSBoundParameters.ContainsKey('DeclineLanguagesInclude')) {
            $DeclineLanguagesMetadata = $script:WscMetadata.Languages.Language | Where-Object { $_.code -in $DeclineLanguagesInclude }
        }
        
        if ($SynchroniseServer) {
            Write-Host -ForegroundColor Green "`r`nStarting WSUS server synchronisation ..."
            Invoke-WsusServerSynchronisation
        }
        
        Write-Host -ForegroundColor Green "`r`nBeginning WSUS server cleanup (Phase 1) ..."
        $CleanupWrapperParams = @{
            CleanupObsoleteUpdates=$CleanupObsoleteUpdates
            CompressUpdates=$CompressUpdates
            DeclineExpiredUpdates=$DeclineExpiredUpdates
            DeclineSupersededUpdates=$DeclineSupersededUpdates
        }
        Invoke-WsusServerCleanupWrapper @CleanupWrapperParams
        
        Write-Host -ForegroundColor Green "`r`nBeginning WSUS server cleanup (Phase 2) ..."
        $SpringCleanParams = @{
            DeclineClusterUpdates=$DeclineClusterUpdates
            DeclineFarmUpdates=$DeclineFarmUpdates
            DeclinePrereleaseUpdates=$DeclinePrereleaseUpdates
            DeclineSecurityOnlyUpdates=$DeclineSecurityOnlyUpdates
        }
        
        if ($DeclineCategories) {
            $SpringCleanParams += @{DeclineCategories=$DeclineCategories}
        }
        
        if ($DeclineArchitecturesMetadata) {
            $SpringCleanParams += @{DeclineArchitectures=$DeclineArchitecturesMetadata}
        }
        
        if ($DeclineLanguagesMetadata) {
            $SpringCleanParams += @{DeclineLanguages=$DeclineLanguagesMetadata}
        }
        
        Invoke-WsusServerSpringClean @SpringCleanParams
        
        Write-Host -ForegroundColor Green "`r`nBeginning WSUS server cleanup (Phase 3) ..."
        $CleanupWrapperParams = @{
            CleanupObsoleteComputers=$CleanupObsoleteComputers
            CleanupUnneededContentFiles=$CleanupUnneededContentFiles
        }
        Invoke-WsusServerCleanupWrapper @CleanupWrapperParams
        
        if ($FindSuspectDeclines) {
            Get-WsusSuspectDeclines @SpringCleanParams
        }
        

        }

        Function Get-WsusSuspectDeclines {
        [CmdletBinding()]
        Param(
        [Switch]$DeclineClusterUpdates,
        [Switch]$DeclineFarmUpdates,
        [Switch]$DeclinePrereleaseUpdates,
        [Switch]$DeclineSecurityOnlyUpdates,

            [String[]]$DeclineCategories,
            [Xml.XmlElement[]]$DeclineArchitectures,
            [Xml.XmlElement[]]$DeclineLanguages
        )
        
        $WsusServer = Get-WsusServer
        $UpdateScope = New-Object -TypeName Microsoft.UpdateServices.Administration.UpdateScope
        
        Write-Host -ForegroundColor Green '[*] Retrieving declined updates ...'
        $UpdateScope.ApprovedStates = [Microsoft.UpdateServices.Administration.ApprovedStates]::Declined
        $WsusDeclined = $WsusServer.GetUpdates($UpdateScope)
        
        # Ignore all updates corresponding to architectures, categories or languages we declined
        $IgnoredCatalogueCategories = $script:WscCatalogue | Where-Object { $_.Category -in $DeclineCategories }
        $IgnoredArchitecturesRegEx = ' ({0})' -f [String]::Join('|', $DeclineArchitectures.regex)
        $IgnoredLanguagesRegEx = ' [[]?({0})(_LP|_LIP)?[]]?' -f [String]::Join('|', $DeclineLanguages.code)
        
        Write-Host -ForegroundColor Green '[*] Finding suspect declined updates ...'
        $SuspectDeclines = @()
        foreach ($Update in $WsusDeclined) {
            # Ignore superseded and expired updates
            if ($Update.IsSuperseded -or $Update.PublicationState -eq 'Expired') {
                continue
            }
        
            # Ignore cluster updates if they were declined
            if ($DeclineClusterUpdates -and $Update.Title -match $RegExClusterUpdates) {
                continue
            }
        
            # Ignore farm updates if they were declined
            if ($DeclineFarmUpdates -and $Update.Title -match $RegExFarmUpdates) {
                continue
            }
        
            # Ignore pre-release updates if they were declined
            if ($DeclinePrereleaseUpdates -and $Update.Title -match $RegExPrereleaseUpdates) {
                continue
            }
        
            # Ignore Security Only Quality updates if they were declined
            if ($DeclineSecurityOnlyUpdates -and $Update.Title -match $RegExSecurityOnlyUpdates) {
                continue
            }
        
            # Ignore any update categories which were declined
            if ($Update.Title -in $IgnoredCatalogueCategories.Title) {
                continue
            }
        
            # Ignore any update architectures which were declined
            if ($Update.Title -match $IgnoredArchitecturesRegEx) {
                continue
            }
        
            # Ignore any update languages which were declined
            if ($Update.Title -match $IgnoredLanguagesRegEx) {
                continue
            }
        
            $SuspectDeclines += $Update
        }
        
        return $SuspectDeclines
        

        }

        Function Import-WsusSpringCleanMetadata {
        [CmdletBinding()]
        Param()

        Write-Verbose -Message '[*] Importing module metadata ...'
        $MetadataPath = Join-Path -Path $PSScriptRoot -ChildPath 'PSWsusSpringClean.xml'
        $script:WscMetadata = ([Xml](Get-Content -Path $MetadataPath)).PSWsusSpringClean
        

        }

        Function Invoke-WsusDeclineUpdatesByCatalogue {
        [CmdletBinding(SupportsShouldProcess)]
        Param(
        [Parameter(Mandatory)]
        [Microsoft.UpdateServices.Internal.BaseApi.Update[]]$Updates,

            [Parameter(Mandatory)]
            [ValidateNotNullOrEmpty()]
            [String]$Category
        )
        
        Write-Host -ForegroundColor Green ('[*] Declining updates in category: {0}' -f $Category)
        $UpdatesToDecline = $script:WscCatalogue | Where-Object { $_.Category -eq $Category }
        $MatchingUpdates = $Updates | Where-Object { $_.Title -in $UpdatesToDecline.Title }
        
        foreach ($Update in $MatchingUpdates) {
            if ($PSCmdlet.ShouldProcess($Update.Title, 'Decline')) {
                Write-Host -ForegroundColor Cyan ('[-] Declining update: {0}' -f $Update.Title)
                $Update.Decline()
            }
        }
        

        }

        Function Invoke-WsusDeclineUpdatesByRegEx {
        [CmdletBinding(SupportsShouldProcess)]
        Param(
        [Parameter(Mandatory)]
        [Microsoft.UpdateServices.Internal.BaseApi.Update[]]$Updates,

            [Parameter(Mandatory)]
            [ValidateNotNullOrEmpty()]
            [String]$RegEx
        )
        
        foreach ($Update in $Updates) {
            if ($Update.Title -match $RegEx) {
                if ($PSCmdlet.ShouldProcess($Update.Title, 'Decline')) {
                    Write-Host -ForegroundColor Cyan ('[-] Declining update: {0}' -f $Update.Title)
                    $Update.Decline()
                }
            }
        }
        

        }

        Function Invoke-WsusServerCleanupWrapper {
        [CmdletBinding(SupportsShouldProcess)]
        Param(
        [Switch]$CleanupObsoleteComputers,
        [Switch]$CleanupObsoleteUpdates,
        [Switch]$CleanupUnneededContentFiles,
        [Switch]$CompressUpdates,
        [Switch]$DeclineExpiredUpdates,
        [Switch]$DeclineSupersededUpdates
        )

        if ($CleanupObsoleteComputers) {
            Write-Host -ForegroundColor Green '[*] Deleting obsolete computers ...'
            Write-Host (Invoke-WsusServerCleanup -CleanupObsoleteComputers)
        }
        
        if ($CleanupObsoleteUpdates) {
            Write-Host -ForegroundColor Green '[*] Deleting obsolete updates ...'
            Write-Host (Invoke-WsusServerCleanup -CleanupObsoleteUpdates)
        }
        
        if ($CleanupUnneededContentFiles) {
            Write-Host -ForegroundColor Green '[*] Deleting unneeded update files ...'
            Write-Host (Invoke-WsusServerCleanup -CleanupUnneededContentFiles)
        }
        
        if ($CompressUpdates) {
            Write-Host -ForegroundColor Green '[*] Deleting obsolete update revisions ...'
            Write-Host (Invoke-WsusServerCleanup -CompressUpdates)
        }
        
        if ($DeclineExpiredUpdates) {
            Write-Host -ForegroundColor Green '[*] Declining expired updates ...'
            Write-Host (Invoke-WsusServerCleanup -DeclineExpiredUpdates)
        }
        
        if ($DeclineSupersededUpdates) {
            Write-Host -ForegroundColor Green '[*] Declining superseded updates ...'
            Write-Host (Invoke-WsusServerCleanup -DeclineSupersededUpdates)
        }
        

        }

        Function Invoke-WsusServerSynchronisation {
        [CmdletBinding(SupportsShouldProcess)]
        Param()

        $WsusServer = Get-WsusServer
        
        if ($PSCmdlet.ShouldProcess($env:COMPUTERNAME, 'WSUS synchronization')) {
            $SyncStatus = $WsusServer.GetSubscription().GetSynchronizationStatus()
            if ($SyncStatus -eq 'NotProcessing') {
                $WsusServer.GetSubscription().StartSynchronization()
            } elseif ($SyncStatus -eq 'Running') {
                Write-Warning -Message "[!] A synchronisation appears to already be running! We'll wait for this one to complete ..."
            } else {
                throw ('WSUS server returned unknown synchronisation status: {0}' -f $SyncStatus)
            }
        
            do {
                Start-Sleep -Seconds 5
            } while ($WsusServer.GetSubscription().GetSynchronizationStatus() -eq 'Running')
        
            $SyncResult = $WsusServer.GetSubscription().GetLastSynchronizationInfo().Result
            if ($SyncResult -ne 'Succeeded') {
                throw ('WSUS server synchronisation completed with unexpected result: {0}' -f $SyncResult)
            }
        }
        

        }

        Function Invoke-WsusServerSpringClean {
        [CmdletBinding(SupportsShouldProcess)]
        Param(
        [Switch]$DeclineClusterUpdates,
        [Switch]$DeclineFarmUpdates,
        [Switch]$DeclinePrereleaseUpdates,
        [Switch]$DeclineSecurityOnlyUpdates,

            [String[]]$DeclineCategories,
            [Xml.XmlElement[]]$DeclineArchitectures,
            [Xml.XmlElement[]]$DeclineLanguages
        )
        
        $WsusServer = Get-WsusServer
        $UpdateScope = New-Object -TypeName Microsoft.UpdateServices.Administration.UpdateScope
        
        Write-Host -ForegroundColor Green '[*] Retrieving approved updates ...'
        $UpdateScope.ApprovedStates = [Microsoft.UpdateServices.Administration.ApprovedStates]::LatestRevisionApproved
        $WsusApproved = $WsusServer.GetUpdates($UpdateScope)
        
        Write-Host -ForegroundColor Green '[*] Retrieving unapproved updates ...'
        $UpdateScope.ApprovedStates = [Microsoft.UpdateServices.Administration.ApprovedStates]::NotApproved
        $WsusUnapproved = $WsusServer.GetUpdates($UpdateScope)
        
        $WsusAnyExceptDeclined = $WsusApproved + $WsusUnapproved
        
        if ($DeclineClusterUpdates) {
            Write-Host -ForegroundColor Green '[*] Declining cluster updates ...'
            Invoke-WsusDeclineUpdatesByRegEx -Updates $WsusAnyExceptDeclined -RegEx $script:RegExClusterUpdates
        }
        
        if ($DeclineFarmUpdates) {
            Write-Host -ForegroundColor Green '[*] Declining farm updates ...'
            Invoke-WsusDeclineUpdatesByRegEx -Updates $WsusAnyExceptDeclined -RegEx $script:RegExFarmUpdates
        }
        
        if ($DeclinePrereleaseUpdates) {
            Write-Host -ForegroundColor Green '[*] Declining pre-release updates ...'
            Invoke-WsusDeclineUpdatesByRegEx -Updates $WsusAnyExceptDeclined -RegEx $script:RegExPrereleaseUpdates
        }
        
        if ($DeclineSecurityOnlyUpdates) {
            Write-Host -ForegroundColor Green '[*] Declining Security Only updates ...'
            Invoke-WsusDeclineUpdatesByRegEx -Updates $WsusAnyExceptDeclined -RegEx $script:RegExSecurityOnlyUpdates
        }
        
        if ($PSBoundParameters.ContainsKey('DeclineCategories')) {
            foreach ($Category in $DeclineCategories) {
                Invoke-WsusDeclineUpdatesByCatalogue -Updates $WsusAnyExceptDeclined -Category $Category
            }
        }
        
        if ($PSBoundParameters.ContainsKey('DeclineArchitectures')) {
            foreach ($Architecture in $DeclineArchitectures) {
                Write-Host -ForegroundColor Green ('[*] Declining updates with architecture: {0}' -f $Architecture.name)
                $ArchitectureRegEx = ' ({0})' -f $Architecture.regex
                Invoke-WsusDeclineUpdatesByRegEx -Updates $WsusAnyExceptDeclined -RegEx $ArchitectureRegEx
            }
        }
        
        if ($PSBoundParameters.ContainsKey('DeclineLanguages')) {
            foreach ($Language in $DeclineLanguages) {
                Write-Host -ForegroundColor Green ('[*] Declining updates with language: {0}' -f $Language.code)
                $LanguageRegEx = ' [[]?{0}(_LP|_LIP)?[]]?' -f $Language.code
                Invoke-WsusDeclineUpdatesByRegEx -Updates $WsusAnyExceptDeclined -RegEx $LanguageRegEx
            }
        }
        

        }

        Function Test-WsusSpringCleanArchitectures {
        Param(
        [Parameter(Mandatory)]
        [String[]]$Architectures
        )

        if (!$script:WscMetadata) {
            Import-WsusSpringCleanMetadata
        }
        
        $KnownArchitectures = $script:WscMetadata.Architectures.Architecture.name
        foreach ($Architecture in $Architectures) {
            if ($Architecture -notin $KnownArchitectures) {
                throw 'Unknown architecture specified: {0}' -f $Architecture
            }
        }
        
        return $true
        

        }

        Function Test-WsusSpringCleanLanguageCodes {
        Param(
        [Parameter(Mandatory)]
        [String[]]$LanguageCodes
        )

        if (!$script:WscMetadata) {
            Import-WsusSpringCleanMetadata
        }
        
        $KnownLanguageCodes = $script:WscMetadata.Languages.Language.code
        foreach ($LanguageCode in $LanguageCodes) {
            if ($LanguageCode -notin $KnownLanguageCodes) {
                throw 'Unknown language code specified: {0}' -f $LanguageCode
            }
        }
        
        return $true
        

        }

        Function ConvertTo-WsusSpringCleanCatalogue {
        Param(
        [Parameter(Mandatory,ValueFromPipeline)]
        [Microsoft.UpdateServices.Internal.BaseApi.Update[]]$Updates
        )

        Process {
            foreach ($Update in $Updates) {
                [String[]]$ProductTitles = @()
                foreach ($ProductTitle in $Update.ProductTitles) {
                    $ProductTitles += $ProductTitle
                }
        
                [PSCustomObject]@{
                    'Category'      = 'Unknown'
                    'Title'         = $Update.Title
                    'ProductTitles' = [String]::Join(', ', $ProductTitles)
                }
            }
        }
        

        }

        Function Import-WsusSpringCleanCatalogue {
        [CmdletBinding()]
        Param(
        [ValidateNotNullOrEmpty()]
        [String]$CataloguePath
        )

        if (!$CataloguePath) {
            $CataloguePath = Join-Path -Path $PSScriptRoot -ChildPath 'PSWsusSpringClean.csv'
        }
        
        Write-Verbose -Message '[*] Importing update catalogue ...'
        $script:WscCatalogue = Import-Csv -Path $CataloguePath
        

        }

        Function Test-WsusSpringCleanCatalogue {
        [CmdletBinding()]
        Param(
        [ValidateNotNullOrEmpty()]
        [String]$CataloguePath
        )

        Import-WsusSpringCleanCatalogue @PSBoundParameters
        
        Write-Host -ForegroundColor Green '[*] Retrieving all updates ...'
        $WsusServer = Get-WsusServer
        $WsusUpdateScope = New-Object -TypeName Microsoft.UpdateServices.Administration.UpdateScope
        $WsusUpdateScope.ApprovedStates = [Microsoft.UpdateServices.Administration.ApprovedStates]::Any
        $WsusUpdates = $WsusServer.GetUpdates($WsusUpdateScope)
        
        Write-Host -ForegroundColor Green '[*] Scanning for updates only present in catalogue ...'
        $CatalogueOnly = @()
        foreach ($Update in $script:WscCatalogue) {
            if ($Update.Title -notin $WsusUpdates.Title) {
                $CatalogueOnly += $Update
            }
        }
        
        return $CatalogueOnly
        

        }

        Looks like it pasted in stupidly, sorry.

        black3dynamiteB ObsolesceO 2 Replies Last reply Reply Quote 0
        • black3dynamiteB
          black3dynamite @siringo
          last edited by

          @siringo That was definitely difficult to followed from my iPhone.

          siringoS 1 Reply Last reply Reply Quote 0
          • ObsolesceO
            Obsolesce @siringo
            last edited by

            @siringo It's a start, but there's more to do besides just removing unused updates.

            1 Reply Last reply Reply Quote 0
            • siringoS
              siringo @black3dynamite
              last edited by

              @black3dynamite said in WSUS Help:

              @siringo That was definitely difficult to followed from my iPhone.

              hahaha. I bet.

              1 Reply Last reply Reply Quote 0
              • pmonchoP
                pmoncho @JaredBusch
                last edited by

                @jaredbusch said in WSUS Help:

                @pmoncho said in WSUS Help:

                @siringo said in WSUS Help:

                Finally setup wsus on a 2016 server. All went well except I told it I wanted updates for Windows 7, which I've decided I don't want.

                I told it I want updates for Windows 10 and it's downloading updates for all flavours of Windows 10, we only run Pro. So far it's filled up the 200GBs I set aside for it only 3 days ago.

                I can uninstall wsus and start again, that's not a problem, is that the quickest and easiest way to get some of my 200GBs back and start over?

                And, how can I tell it I only want updates for W10 Pro?

                And, if anyone has a link to a 'I don't want to think too much' guide for setting up wsus, I'd be keen to take a look.

                Thanks for any help.

                You may want to check out 🌶 for Clean-WSUS. Excellent script to help clean up WSUS.

                Except it is no longer available.

                Well Shit! I see that now. UGH!

                1 Reply Last reply Reply Quote 0
                • MattSpellerM
                  MattSpeller
                  last edited by

                  WSUS is a pain in the ass

                  pmonchoP 1 Reply Last reply Reply Quote 3
                  • pmonchoP
                    pmoncho @MattSpeller
                    last edited by

                    @mattspeller said in WSUS Help:

                    WSUS is a pain in the ass

                    I agree. Without derailing the off-topic to far, I'm wondering what do others use as an alternative? PDQ Deploy?

                    jmooreJ ObsolesceO 2 Replies Last reply Reply Quote 0
                    • jmooreJ
                      jmoore @pmoncho
                      last edited by

                      @pmoncho We have pdq and it might work but I don't use it for that. I really just use powershell to pull and install updates. Seems like it misses some but not a lot.

                      1 Reply Last reply Reply Quote 0
                      • ObsolesceO
                        Obsolesce @pmoncho
                        last edited by Obsolesce

                        @pmoncho said in WSUS Help:

                        @mattspeller said in WSUS Help:

                        WSUS is a pain in the ass

                        I agree. Without derailing the off-topic to far, I'm wondering what do others use as an alternative? PDQ Deploy?

                        The only real alternative is to use WSUS to stop updates completely, using it only to see which updates to deploy manually via SaltStack.

                        But really, WSUS is working fine, it's no more of a pain than doing it any other way.

                        If you don't update, you risk security issues, if you do update, you risk breaking shit... but I think MS is working on it. We'll see.

                        Edit: WSUS isn't too bad if you set it to only download updates you approve, and clean up updates that are no longer needed. Speed wise, there's a script to speed up the database.

                        momurdaM 1 Reply Last reply Reply Quote 0
                        • momurdaM
                          momurda @Obsolesce
                          last edited by

                          @obsolesce From what i can tell MS hasnt updated WSUS in any way since 2013.

                          ObsolesceO 1 Reply Last reply Reply Quote 1
                          • ObsolesceO
                            Obsolesce @momurda
                            last edited by

                            @momurda said in WSUS Help:

                            @obsolesce From what i can tell MS hasnt updated WSUS in any way since 2013.

                            There's no need to... what could they possibly do to make it any better?

                            IRJI scottalanmillerS 2 Replies Last reply Reply Quote 0
                            • momurdaM
                              momurda
                              last edited by

                              Well, the mmc crashes constantly. The updates dont install when you tell them too, computers dont follow the dont restart time windows. iisreset is required once a week to to even get mmc to populate data. Issues like that for a decade theyve done nothing about.

                              ObsolesceO 1 Reply Last reply Reply Quote 1
                              • ObsolesceO
                                Obsolesce @momurda
                                last edited by

                                @momurda said in WSUS Help:

                                Well, the mmc crashes constantly. The updates dont install when you tell them too, computers dont follow the dont restart time windows. iisreset is required once a week to to even get mmc to populate data. Issues like that for a decade theyve done nothing about.

                                I don't have any of those issues, and I've been using WSUS a lot for a long time.

                                1 Reply Last reply Reply Quote 0
                                • IRJI
                                  IRJ
                                  last edited by

                                  WSUS is a pile of shit. It will be nice when Microsoft introduces its monthly maintenance plan.

                                  scottalanmillerS 1 Reply Last reply Reply Quote 2
                                  • scottalanmillerS
                                    scottalanmiller @IRJ
                                    last edited by

                                    @irj said in WSUS Help:

                                    WSUS is a pile of shit. It will be nice when Microsoft introduces its monthly maintenance plan.

                                    Agreed, it's a disaster.

                                    1 Reply Last reply Reply Quote 0
                                    • IRJI
                                      IRJ @Obsolesce
                                      last edited by

                                      @obsolesce said in WSUS Help:

                                      @momurda said in WSUS Help:

                                      @obsolesce From what i can tell MS hasnt updated WSUS in any way since 2013.

                                      There's no need to... what could they possibly do to make it any better?

                                      I really hope you are joking....

                                      ObsolesceO 1 Reply Last reply Reply Quote 0
                                      • dbeatoD
                                        dbeato
                                        last edited by

                                        I amazes me that some of us manage Windows Systems and we still complain about them when it is our job to work with them....Not everything in Microsoft System is perfect nor does everything in Linux./

                                        scottalanmillerS IRJI 2 Replies Last reply Reply Quote 0
                                        • scottalanmillerS
                                          scottalanmiller @Obsolesce
                                          last edited by

                                          @obsolesce said in WSUS Help:

                                          @momurda said in WSUS Help:

                                          @obsolesce From what i can tell MS hasnt updated WSUS in any way since 2013.

                                          There's no need to... what could they possibly do to make it any better?

                                          Make it efficient, reliable, easy to use, or just make it unnecessary like Linux does.

                                          1 Reply Last reply Reply Quote 0
                                          • scottalanmillerS
                                            scottalanmiller @dbeato
                                            last edited by

                                            @dbeato said in WSUS Help:

                                            I amazes me that some of us manage Windows Systems and we still complain about them when it is our job to work with them....Not everything in Microsoft System is perfect nor does everything in Linux./

                                            Actually it being our job to work with them (or to decide if we use them) is exactly what makes you expect complaints. Who else would complain about something other than the users?

                                            dbeatoD 1 Reply Last reply Reply Quote 1
                                            • 1
                                            • 2
                                            • 3
                                            • 4
                                            • 2 / 4
                                            • First post
                                              Last post