public/Get-KbInstalledUpdate.ps1

function Get-KbInstalledUpdate {
    <#
    .SYNOPSIS
        Replacement for Get-Hotfix, Get-Package, searching the registry and searching CIM for updates
 
    .DESCRIPTION
        Replacement for Get-Hotfix, Get-Package, searching the registry and searching CIM for updates.
 
    .PARAMETER Pattern
        Any pattern. But really, a KB pattern is your best bet.
 
    .PARAMETER ComputerName
        Used to connect to a remote host
 
    .PARAMETER Credential
        The optional alternative credential to be used when connecting to ComputerName
 
    .PARAMETER IncludeHidden
        Include KBs that are hidden due to misconfiguration.
 
    .PARAMETER EnableException
        By default, when something goes wrong we try to catch it, interpret it and give you a friendly warning message.
        This avoids overwhelming you with "sea of red" exceptions, but is inconvenient because it basically disables advanced scripting.
        Using this switch turns this "nice by default" feature off and enables you to catch exceptions with your own try/catch.
 
    .NOTES
        Author: Chrissy LeMaire (@cl), netnerds.net
        Copyright: (c) licensed under MIT
        License: MIT https://opensource.org/licenses/MIT
 
    .EXAMPLE
        PS C:\> Get-KbInstalledUpdate
 
        Gets all the updates installed on the local machine
 
    .EXAMPLE
        PS C:\> Get-KbInstalledUpdate -ComputerName server01
 
        Gets all the updates installed on server01
 
    .EXAMPLE
        PS C:\> Get-KbInstalledUpdate -ComputerName server01 -Pattern KB4057119
 
        Gets all the updates installed on server01 that match KB4057119
 
    .EXAMPLE
        PS C:\> Get-KbInstalledUpdate -ComputerName server01 -Pattern KB4057119 | Select -ExpandProperty InstallFile
 
        Shows alls of the install files for KB4057119 on server01. InstallFile is hidden by default because it has a lot of information.
#>

    [CmdletBinding()]
    param(
        [PSFComputer[]]$ComputerName = $env:COMPUTERNAME,
        [pscredential]$Credential,
        [Alias("Name", "HotfixId", "KBUpdate", "Id")]
        [string[]]$Pattern,
        [switch]$IncludeHidden,
        [switch]$EnableException
    )
    begin {
        $scriptblock = {
            param ([string[]]$Pattern, $IncludeHidden, $VerbosePreference)
            $allhotfixids = New-Object System.Collections.ArrayList
            $allcbs = Get-ChildItem 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\Packages'

            if ($psversiontable.PsVersion.Major -lt 5 -or ($psversiontable.PsVersion.Major -eq 5 -and $psversiontable.PsVersion.Major -lt 1)) {
                # using throw because it's a remote computer with no guarantee of psframework. Also the throw is caught at the bottom by PSFramework.
                throw "$env:ComputerName is running PowerShell version $psversiontalbe. Please upgrade to PowerShell version 5.1 or greater"
            }

            if ($pattern) {
                $packages = @()
                foreach ($name in $pattern) {
                    $packages += Get-Package -IncludeWindowsInstaller -ProviderName msi, msu, Programs -Name "*$name*" -ErrorAction SilentlyContinue
                    $packages += Get-Package -ProviderName msi, msu, Programs -Name "*$name*" -ErrorAction SilentlyContinue
                }
                $packages = $packages | Sort-Object -Unique Name
            } else {
                $packages = @()
                $packages += Get-Package -IncludeWindowsInstaller -ProviderName msi, msu, Programs
                $packages += Get-Package -ProviderName msi, msu, Programs
                $packages = $packages | Sort-Object -Unique Name
            }
            # Cim never reports stuff in a package :(

            foreach ($package in $packages) {
                $null = $package | Add-Member -MemberType ScriptMethod -Name ToString -Value { $this.Name } -Force

                # Make it pretty
                $fullpath = $package.FullPath
                if ($fullpath -eq "?") {
                    $fullpath = $null
                }
                $filename = $package.PackageFilename
                if ($filename -eq "?") {
                    $filename = $null
                }

                $null = $package | Add-Member -MemberType ScriptMethod -Name ToString -Value { $this.Name } -Force
                if (($regpath = ($package.FastPackageReference).Replace("hklm64\HKEY_LOCAL_MACHINE", "HKLM:\")) -match 'HKLM') {
                    $reg = Get-ItemProperty -Path $regpath -ErrorAction SilentlyContinue
                    $null = $reg | Add-Member -MemberType ScriptMethod -Name ToString -Value { $this.DisplayName } -Force
                    $hotfixid = Split-Path -Path $regpath -Leaf | Where-Object { $psitem.StartsWith("KB") }
                } else {
                    $reg = $null
                    $hotfixid = $null
                }

                #return the same properties as above
                if ($package.Name -match 'KB' -and -not $hotfixid) {
                    #anyone want to help with regex, I'm down. Till then..
                    $number = $package.Name.Split('KB') | Select-Object -Last 1
                    $number = $number.Split(" ") | Select-Object -First 1
                    $hotfixid = "KB$number".Trim().Replace(")", "")
                } else {
                    $hotfixid = $package.HotfixId
                }

                if ($hotfixid) {
                    $null = $allhotfixids.Add($hotfixid)
                    $cbs = $allcbs | Where-Object Name -match $hotfixid | Get-ItemProperty
                    if ($cbs) {
                        # make it pretty
                        $cbs | Add-Member -MemberType ScriptMethod -Name ToString -Value { "ComponentBasedServicing" } -Force
                        $installclient = ($cbs | Select-Object -First 1).InstallClient
                        $installuser = ($cbs | Select-Object -First 1).InstallUser
                        $installname = $cbs.InstallName

                        if ("$installname" -match "Package_1_for") {
                            $installname = $cbs | Where-Object InstallName -match "Package_1_for" | Select-Object -First 1 -ExpandProperty InstallName
                            $installname = $installname.Replace("Package_1_for", "Package_for")
                        } elseif ("$installname" -match "Package_for") {
                            $installname = $cbs | Where-Object InstallName -match "Package_for" | Select-Object -First 1 -ExpandProperty InstallName
                        }

                        if ($installname.Count -gt 1) {
                            $installname | Select-Object -First 1
                        }

                        # props for highlighting that the installversion is important
                        # https://social.technet.microsoft.com/Forums/Lync/en-US/f6594e00-2400-4276-85a1-fb06485b53e6/issues-with-wusaexe-and-windows-10-enterprise?forum=win10itprogeneral
                        if ($installname) {
                            $installname = $installname.Replace(".mum", "")
                            $installversion = (($installname -split "~~")[1])
                        }

                        $allfiles = New-Object -TypeName System.Collections.ArrayList
                        foreach ($file in $cbs) {
                            $name = $file.InstallName
                            $location = $file.InstallLocation.ToString().TrimStart("\\?\")
                            $location = "$location\$name"
                            $null = $allfiles.Add([pscustomobject]@{
                                    Name = $name
                                    Path = $location
                                })
                        }
                    }
                }
                # gotta get dism module and try that jesus christ
                [pscustomobject]@{
                    ComputerName         = $env:COMPUTERNAME
                    Name                 = $package.Name
                    ProviderName         = $package.ProviderName
                    Source               = $package.Source
                    Status               = $package.Status
                    HotfixId             = $hotfixid
                    FullPath             = $fullpath
                    PackageFilename      = $filename
                    Summary              = $package.Summary
                    InstalledBy          = $cim.InstalledBy
                    FastPackageReference = $package.FastPackageReference
                    InstalledOn          = $cim.InstalledOn
                    InstallDate          = $cim.InstallDate
                    InstallClient        = $installclient
                    InstallName          = $installname
                    InstallVersion       = $installversion
                    InstallFile          = $allfiles
                    InstallUser          = $installuser
                    FixComments          = $cim.FixComments
                    ServicePackInEffect  = $cim.ServicePackInEffect
                    Caption              = $cim.Caption
                    DisplayName          = $package.Meta.Attributes['DisplayName']
                    DisplayIcon          = $package.Meta.Attributes['DisplayIcon']
                    UninstallString      = $package.Meta.Attributes['UninstallString']
                    InstallLocation      = $package.Meta.Attributes['InstallLocation']
                    EstimatedSize        = $package.Meta.Attributes['EstimatedSize']
                    Publisher            = $package.Meta.Attributes['Publisher']
                    VersionMajor         = $package.Meta.Attributes['VersionMajor']
                    VersionMinor         = $package.Meta.Attributes['VersionMinor']
                    TagId                = $package.TagId
                    PackageObject        = $package
                    RegistryObject       = $reg
                    CBSPackageObject     = $cbs
                    CimObject            = $cim
                }
            }

            $allcim = Get-CimInstance -ClassName Win32_QuickFixEngineering | Sort-Object Name -Unique

            if ($pattern) {
                $allcim = $allcim | Where-Object HotfixId -in $pattern
            }

            foreach ($cim in $allcim) {
                #return the same properties as above
                if ($cim.Name -match 'KB' -and -not $cim.HotfixId) {
                    # anyone want to help with regex, I'm down. Till then..
                    $split = $cim.Name -split 'KB'
                    $number = ($split[-1]).TrimEnd(")").Trim()
                    $hotfixid = "KB$number"
                } else {
                    $hotfixid = $cim.HotfixId
                }

                if ($hotfixid) {
                    $null = $allhotfixids.Add($hotfixid)
                    $cbs = $allcbs | Where-Object Name -match $hotfixid | Get-ItemProperty
                    if ($cbs) {
                        # make it pretty
                        $cbs | Add-Member -MemberType ScriptMethod -Name ToString -Value { "ComponentBasedServicing" } -Force
                        $installclient = ($cbs | Select-Object -First 1).InstallClient
                        $installuser = ($cbs | Select-Object -First 1).InstallUser

                        $allfiles = New-Object -TypeName System.Collections.ArrayList
                        foreach ($file in $cbs) {
                            $name = $file.InstallName
                            $location = $file.InstallLocation.ToString().TrimStart("\\?\")
                            $location = "$location\$name"
                            $null = $allfiles.Add([pscustomobject]@{
                                    Name = $name
                                    Path = $location
                                })
                        }
                        # no idea why this doesn't work :(
                        Add-Member -InputObject $allfiles -MemberType ScriptMethod -Name ToString -Value { $this.Name } -Force
                    }
                }

                [pscustomobject]@{
                    ComputerName        = $env:COMPUTERNAME
                    Name                = $cim.HotfixId
                    ProviderName        = $null
                    Source              = $null
                    Status              = $null
                    HotfixId            = $hotfixid
                    FullPath            = $null
                    PackageFilename     = $null
                    Summary             = $null
                    InstalledBy         = $cim.InstalledBy
                    InstalledOn         = $cim.InstalledOn
                    InstallDate         = $cim.InstallDate
                    InstallClient       = $installclient
                    InstallName         = $installname
                    InstallVersion      = $installversion
                    InstallFile         = $allfiles
                    InstallUser         = $installuser
                    FixComments         = $cim.FixComments
                    ServicePackInEffect = $cim.ServicePackInEffect
                    Caption             = $cim.Caption
                    DisplayName         = $null
                    DisplayIcon         = $null
                    UninstallString     = $null
                    InstallLocation     = $null
                    EstimatedSize       = $null
                    Publisher           = $null
                    VersionMajor        = $null
                    VersionMinor        = $null
                    TagId               = $null
                    PackageObject       = $null
                    RegistryObject      = $null
                    CBSPackageObject    = $cbs
                    CimObject           = $cim
                }
            }

            if ($IncludeHidden) {
                #anyone want to help with regex, I'm down. Till then..
                $kbfiles = $allcbs | Get-ItemProperty | Where-Object InstallName -match '_KB' | Select-Object -ExpandProperty InstallName
                $allkbs = @()
                foreach ($file in $kbfiles) {
                    $tempfile = $file.ToString().Split("_") | Where-Object { $PSItem.StartsWith("KB") }
                    if ($tempfile) {
                        $allkbs += $tempfile.Replace("_", "").Split("~") | Select-Object -First 1
                    }
                }

                $missing = $allkbs | Where-Object { $PSitem -notin $allhotfixids } | Select-Object -Unique

                if ($Pattern) {
                    $missing = $missing | Where-Object { $PSItem -in $Pattern }
                }

                foreach ($result in $missing) {
                    [pscustomobject]@{
                        ComputerName        = $env:COMPUTERNAME
                        Name                = $result
                        ProviderName        = $null
                        Source              = $null
                        Status              = $null
                        HotfixId            = $result
                        FullPath            = $null
                        PackageFilename     = $null
                        Summary             = "Requires restart to finish installing"
                        InstalledBy         = $null
                        InstalledOn         = $null
                        InstallDate         = $null
                        InstallClient       = $null
                        InstallName         = $null
                        InstallVersion      = $null
                        InstallFile         = $null
                        InstallUser         = $null
                        FixComments         = $null
                        ServicePackInEffect = $null
                        Caption             = $null
                        DisplayName         = $null
                        DisplayIcon         = $null
                        UninstallString     = $null
                        InstallLocation     = $null
                        EstimatedSize       = $null
                        Publisher           = $null
                        VersionMajor        = $null
                        VersionMinor        = $null
                        TagId               = $null
                        PackageObject       = $null
                        RegistryObject      = $null
                        CBSPackageObject    = $null
                        CimObject           = $null
                    }
                }
            }
        }
    }
    process {
        if (-not (Test-PSFPowerShell -OperatingSystem Windows)) {
            Stop-PSFFunction -Message "This command using remoting and only supports Windows at this time" -EnableException:$EnableException
            return
        }

        try {
            foreach ($computer in $ComputerName) {
                Invoke-PSFCommand -ComputerName $computer -Credential $Credential -ErrorAction Stop -ScriptBlock $scriptblock -ArgumentList @($Pattern), $IncludeHidden, $VerbosePreference | Sort-Object -Property Name |
                    Select-Object -Property * -ExcludeProperty PSComputerName, RunspaceId | Select-DefaultView -ExcludeProperty InstallFile
            }
        } catch {
            Stop-PSFFunction -EnableException:$EnableException -Message "Failure" -ErrorRecord $_ -Continue
        }
    }
}
# SIG # Begin signature block
# MIIcYgYJKoZIhvcNAQcCoIIcUzCCHE8CAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB
# gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR
# AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUBUGbdod6+CwSbaZx8TlBk4FP
# tcaggheRMIIFGjCCBAKgAwIBAgIQAsF1KHTVwoQxhSrYoGRpyjANBgkqhkiG9w0B
# AQsFADByMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYD
# VQQLExB3d3cuZGlnaWNlcnQuY29tMTEwLwYDVQQDEyhEaWdpQ2VydCBTSEEyIEFz
# c3VyZWQgSUQgQ29kZSBTaWduaW5nIENBMB4XDTE3MDUwOTAwMDAwMFoXDTIwMDUx
# MzEyMDAwMFowVzELMAkGA1UEBhMCVVMxETAPBgNVBAgTCFZpcmdpbmlhMQ8wDQYD
# VQQHEwZWaWVubmExETAPBgNVBAoTCGRiYXRvb2xzMREwDwYDVQQDEwhkYmF0b29s
# czCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAI8ng7JxnekL0AO4qQgt
# Kr6p3q3SNOPh+SUZH+SyY8EA2I3wR7BMoT7rnZNolTwGjUXn7bRC6vISWg16N202
# 1RBWdTGW2rVPBVLF4HA46jle4hcpEVquXdj3yGYa99ko1w2FOWzLjKvtLqj4tzOh
# K7wa/Gbmv0Si/FU6oOmctzYMI0QXtEG7lR1HsJT5kywwmgcjyuiN28iBIhT6man0
# Ib6xKDv40PblKq5c9AFVldXUGVeBJbLhcEAA1nSPSLGdc7j4J2SulGISYY7ocuX3
# tkv01te72Mv2KkqqpfkLEAQjXgtM0hlgwuc8/A4if+I0YtboCMkVQuwBpbR9/6ys
# Z+sCAwEAAaOCAcUwggHBMB8GA1UdIwQYMBaAFFrEuXsqCqOl6nEDwGD5LfZldQ5Y
# MB0GA1UdDgQWBBRcxSkFqeA3vvHU0aq2mVpFRSOdmjAOBgNVHQ8BAf8EBAMCB4Aw
# EwYDVR0lBAwwCgYIKwYBBQUHAwMwdwYDVR0fBHAwbjA1oDOgMYYvaHR0cDovL2Ny
# bDMuZGlnaWNlcnQuY29tL3NoYTItYXNzdXJlZC1jcy1nMS5jcmwwNaAzoDGGL2h0
# dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9zaGEyLWFzc3VyZWQtY3MtZzEuY3JsMEwG
# A1UdIARFMEMwNwYJYIZIAYb9bAMBMCowKAYIKwYBBQUHAgEWHGh0dHBzOi8vd3d3
# LmRpZ2ljZXJ0LmNvbS9DUFMwCAYGZ4EMAQQBMIGEBggrBgEFBQcBAQR4MHYwJAYI
# KwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBOBggrBgEFBQcwAoZC
# aHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0U0hBMkFzc3VyZWRJ
# RENvZGVTaWduaW5nQ0EuY3J0MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQAD
# ggEBANuBGTbzCRhgG0Th09J0m/qDqohWMx6ZOFKhMoKl8f/l6IwyDrkG48JBkWOA
# QYXNAzvp3Ro7aGCNJKRAOcIjNKYef/PFRfFQvMe07nQIj78G8x0q44ZpOVCp9uVj
# sLmIvsmF1dcYhOWs9BOG/Zp9augJUtlYpo4JW+iuZHCqjhKzIc74rEEiZd0hSm8M
# asshvBUSB9e8do/7RhaKezvlciDaFBQvg5s0fICsEhULBRhoyVOiUKUcemprPiTD
# xh3buBLuN0bBayjWmOMlkG1Z6i8DUvWlPGz9jiBT3ONBqxXfghXLL6n8PhfppBhn
# daPQO8+SqF5rqrlyBPmRRaTz2GQwggUwMIIEGKADAgECAhAECRgbX9W7ZnVTQ7Vv
# lVAIMA0GCSqGSIb3DQEBCwUAMGUxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdp
# Q2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xJDAiBgNVBAMTG0Rp
# Z2lDZXJ0IEFzc3VyZWQgSUQgUm9vdCBDQTAeFw0xMzEwMjIxMjAwMDBaFw0yODEw
# MjIxMjAwMDBaMHIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMx
# GTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xMTAvBgNVBAMTKERpZ2lDZXJ0IFNI
# QTIgQXNzdXJlZCBJRCBDb2RlIFNpZ25pbmcgQ0EwggEiMA0GCSqGSIb3DQEBAQUA
# A4IBDwAwggEKAoIBAQD407Mcfw4Rr2d3B9MLMUkZz9D7RZmxOttE9X/lqJ3bMtdx
# 6nadBS63j/qSQ8Cl+YnUNxnXtqrwnIal2CWsDnkoOn7p0WfTxvspJ8fTeyOU5JEj
# lpB3gvmhhCNmElQzUHSxKCa7JGnCwlLyFGeKiUXULaGj6YgsIJWuHEqHCN8M9eJN
# YBi+qsSyrnAxZjNxPqxwoqvOf+l8y5Kh5TsxHM/q8grkV7tKtel05iv+bMt+dDk2
# DZDv5LVOpKnqagqrhPOsZ061xPeM0SAlI+sIZD5SlsHyDxL0xY4PwaLoLFH3c7y9
# hbFig3NBggfkOItqcyDQD2RzPJ6fpjOp/RnfJZPRAgMBAAGjggHNMIIByTASBgNV
# HRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBhjATBgNVHSUEDDAKBggrBgEF
# BQcDAzB5BggrBgEFBQcBAQRtMGswJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRp
# Z2ljZXJ0LmNvbTBDBggrBgEFBQcwAoY3aHR0cDovL2NhY2VydHMuZGlnaWNlcnQu
# Y29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENBLmNydDCBgQYDVR0fBHoweDA6oDig
# NoY0aHR0cDovL2NybDQuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9v
# dENBLmNybDA6oDigNoY0aHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0
# QXNzdXJlZElEUm9vdENBLmNybDBPBgNVHSAESDBGMDgGCmCGSAGG/WwAAgQwKjAo
# BggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzAKBghghkgB
# hv1sAzAdBgNVHQ4EFgQUWsS5eyoKo6XqcQPAYPkt9mV1DlgwHwYDVR0jBBgwFoAU
# Reuir/SSy4IxLVGLp6chnfNtyA8wDQYJKoZIhvcNAQELBQADggEBAD7sDVoks/Mi
# 0RXILHwlKXaoHV0cLToaxO8wYdd+C2D9wz0PxK+L/e8q3yBVN7Dh9tGSdQ9RtG6l
# jlriXiSBThCk7j9xjmMOE0ut119EefM2FAaK95xGTlz/kLEbBw6RFfu6r7VRwo0k
# riTGxycqoSkoGjpxKAI8LpGjwCUR4pwUR6F6aGivm6dcIFzZcbEMj7uo+MUSaJ/P
# QMtARKUT8OZkDCUIQjKyNookAv4vcn4c10lFluhZHen6dGRrsutmQ9qzsIzV6Q3d
# 9gEgzpkxYz0IGhizgZtPxpMQBvwHgfqL2vmCSfdibqFT+hKUGIUukpHqaGxEMrJm
# oecYpJpkUe8wggZqMIIFUqADAgECAhADAZoCOv9YsWvW1ermF/BmMA0GCSqGSIb3
# DQEBBQUAMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAX
# BgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0IEFzc3Vy
# ZWQgSUQgQ0EtMTAeFw0xNDEwMjIwMDAwMDBaFw0yNDEwMjIwMDAwMDBaMEcxCzAJ
# BgNVBAYTAlVTMREwDwYDVQQKEwhEaWdpQ2VydDElMCMGA1UEAxMcRGlnaUNlcnQg
# VGltZXN0YW1wIFJlc3BvbmRlcjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
# ggEBAKNkXfx8s+CCNeDg9sYq5kl1O8xu4FOpnx9kWeZ8a39rjJ1V+JLjntVaY1sC
# SVDZg85vZu7dy4XpX6X51Id0iEQ7Gcnl9ZGfxhQ5rCTqqEsskYnMXij0ZLZQt/US
# s3OWCmejvmGfrvP9Enh1DqZbFP1FI46GRFV9GIYFjFWHeUhG98oOjafeTl/iqLYt
# WQJhiGFyGGi5uHzu5uc0LzF3gTAfuzYBje8n4/ea8EwxZI3j6/oZh6h+z+yMDDZb
# esF6uHjHyQYuRhDIjegEYNu8c3T6Ttj+qkDxss5wRoPp2kChWTrZFQlXmVYwk/PJ
# YczQCMxr7GJCkawCwO+k8IkRj3cCAwEAAaOCAzUwggMxMA4GA1UdDwEB/wQEAwIH
# gDAMBgNVHRMBAf8EAjAAMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMIMIIBvwYDVR0g
# BIIBtjCCAbIwggGhBglghkgBhv1sBwEwggGSMCgGCCsGAQUFBwIBFhxodHRwczov
# L3d3dy5kaWdpY2VydC5jb20vQ1BTMIIBZAYIKwYBBQUHAgIwggFWHoIBUgBBAG4A
# eQAgAHUAcwBlACAAbwBmACAAdABoAGkAcwAgAEMAZQByAHQAaQBmAGkAYwBhAHQA
# ZQAgAGMAbwBuAHMAdABpAHQAdQB0AGUAcwAgAGEAYwBjAGUAcAB0AGEAbgBjAGUA
# IABvAGYAIAB0AGgAZQAgAEQAaQBnAGkAQwBlAHIAdAAgAEMAUAAvAEMAUABTACAA
# YQBuAGQAIAB0AGgAZQAgAFIAZQBsAHkAaQBuAGcAIABQAGEAcgB0AHkAIABBAGcA
# cgBlAGUAbQBlAG4AdAAgAHcAaABpAGMAaAAgAGwAaQBtAGkAdAAgAGwAaQBhAGIA
# aQBsAGkAdAB5ACAAYQBuAGQAIABhAHIAZQAgAGkAbgBjAG8AcgBwAG8AcgBhAHQA
# ZQBkACAAaABlAHIAZQBpAG4AIABiAHkAIAByAGUAZgBlAHIAZQBuAGMAZQAuMAsG
# CWCGSAGG/WwDFTAfBgNVHSMEGDAWgBQVABIrE5iymQftHt+ivlcNK2cCzTAdBgNV
# HQ4EFgQUYVpNJLZJMp1KKnkag0v0HonByn0wfQYDVR0fBHYwdDA4oDagNIYyaHR0
# cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEQ0EtMS5jcmww
# OKA2oDSGMmh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJ
# RENBLTEuY3JsMHcGCCsGAQUFBwEBBGswaTAkBggrBgEFBQcwAYYYaHR0cDovL29j
# c3AuZGlnaWNlcnQuY29tMEEGCCsGAQUFBzAChjVodHRwOi8vY2FjZXJ0cy5kaWdp
# Y2VydC5jb20vRGlnaUNlcnRBc3N1cmVkSURDQS0xLmNydDANBgkqhkiG9w0BAQUF
# AAOCAQEAnSV+GzNNsiaBXJuGziMgD4CH5Yj//7HUaiwx7ToXGXEXzakbvFoWOQCd
# 42yE5FpA+94GAYw3+puxnSR+/iCkV61bt5qwYCbqaVchXTQvH3Gwg5QZBWs1kBCg
# e5fH9j/n4hFBpr1i2fAnPTgdKG86Ugnw7HBi02JLsOBzppLA044x2C/jbRcTBu7k
# A7YUq/OPQ6dxnSHdFMoVXZJB2vkPgdGZdA0mxA5/G7X1oPHGdwYoFenYk+VVFvC7
# Cqsc21xIJ2bIo4sKHOWV2q7ELlmgYd3a822iYemKC23sEhi991VUQAOSK2vCUcIK
# SK+w1G7g9BQKOhvjjz3Kr2qNe9zYRDCCBs0wggW1oAMCAQICEAb9+QOWA63qAArr
# Pye7uhswDQYJKoZIhvcNAQEFBQAwZTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERp
# Z2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEkMCIGA1UEAxMb
# RGlnaUNlcnQgQXNzdXJlZCBJRCBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTIx
# MTExMDAwMDAwMFowYjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IElu
# YzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEhMB8GA1UEAxMYRGlnaUNlcnQg
# QXNzdXJlZCBJRCBDQS0xMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
# 6IItmfnKwkKVpYBzQHDSnlZUXKnE0kEGj8kz/E1FkVyBn+0snPgWWd+etSQVwpi5
# tHdJ3InECtqvy15r7a2wcTHrzzpADEZNk+yLejYIA6sMNP4YSYL+x8cxSIB8HqIP
# kg5QycaH6zY/2DDD/6b3+6LNb3Mj/qxWBZDwMiEWicZwiPkFl32jx0PdAug7Pe2x
# QaPtP77blUjE7h6z8rwMK5nQxl0SQoHhg26Ccz8mSxSQrllmCsSNvtLOBq6thG9I
# hJtPQLnxTPKvmPv2zkBdXPao8S+v7Iki8msYZbHBc63X8djPHgp0XEK4aH631XcK
# J1Z8D2KkPzIUYJX9BwSiCQIDAQABo4IDejCCA3YwDgYDVR0PAQH/BAQDAgGGMDsG
# A1UdJQQ0MDIGCCsGAQUFBwMBBggrBgEFBQcDAgYIKwYBBQUHAwMGCCsGAQUFBwME
# BggrBgEFBQcDCDCCAdIGA1UdIASCAckwggHFMIIBtAYKYIZIAYb9bAABBDCCAaQw
# OgYIKwYBBQUHAgEWLmh0dHA6Ly93d3cuZGlnaWNlcnQuY29tL3NzbC1jcHMtcmVw
# b3NpdG9yeS5odG0wggFkBggrBgEFBQcCAjCCAVYeggFSAEEAbgB5ACAAdQBzAGUA
# IABvAGYAIAB0AGgAaQBzACAAQwBlAHIAdABpAGYAaQBjAGEAdABlACAAYwBvAG4A
# cwB0AGkAdAB1AHQAZQBzACAAYQBjAGMAZQBwAHQAYQBuAGMAZQAgAG8AZgAgAHQA
# aABlACAARABpAGcAaQBDAGUAcgB0ACAAQwBQAC8AQwBQAFMAIABhAG4AZAAgAHQA
# aABlACAAUgBlAGwAeQBpAG4AZwAgAFAAYQByAHQAeQAgAEEAZwByAGUAZQBtAGUA
# bgB0ACAAdwBoAGkAYwBoACAAbABpAG0AaQB0ACAAbABpAGEAYgBpAGwAaQB0AHkA
# IABhAG4AZAAgAGEAcgBlACAAaQBuAGMAbwByAHAAbwByAGEAdABlAGQAIABoAGUA
# cgBlAGkAbgAgAGIAeQAgAHIAZQBmAGUAcgBlAG4AYwBlAC4wCwYJYIZIAYb9bAMV
# MBIGA1UdEwEB/wQIMAYBAf8CAQAweQYIKwYBBQUHAQEEbTBrMCQGCCsGAQUFBzAB
# hhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wQwYIKwYBBQUHMAKGN2h0dHA6Ly9j
# YWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcnQw
# gYEGA1UdHwR6MHgwOqA4oDaGNGh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdp
# Q2VydEFzc3VyZWRJRFJvb3RDQS5jcmwwOqA4oDaGNGh0dHA6Ly9jcmw0LmRpZ2lj
# ZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcmwwHQYDVR0OBBYEFBUA
# EisTmLKZB+0e36K+Vw0rZwLNMB8GA1UdIwQYMBaAFEXroq/0ksuCMS1Ri6enIZ3z
# bcgPMA0GCSqGSIb3DQEBBQUAA4IBAQBGUD7Jtygkpzgdtlspr1LPUukxR6tWXHvV
# DQtBs+/sdR90OPKyXGGinJXDUOSCuSPRujqGcq04eKx1XRcXNHJHhZRW0eu7NoR3
# zCSl8wQZVann4+erYs37iy2QwsDStZS9Xk+xBdIOPRqpFFumhjFiqKgz5Js5p8T1
# zh14dpQlc+Qqq8+cdkvtX8JLFuRLcEwAiR78xXm8TBJX/l/hHrwCXaj++wc4Tw3G
# XZG5D2dFzdaD7eeSDY2xaYxP+1ngIw/Sqq4AfO6cQg7PkdcntxbuD8O9fAqg7iwI
# VYUiuOsYGk38KiGtSTGDR5V3cdyxG0tLHBCcdxTBnU8vWpUIKRAmMYIEOzCCBDcC
# AQEwgYYwcjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcG
# A1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTExMC8GA1UEAxMoRGlnaUNlcnQgU0hBMiBB
# c3N1cmVkIElEIENvZGUgU2lnbmluZyBDQQIQAsF1KHTVwoQxhSrYoGRpyjAJBgUr
# DgMCGgUAoHgwGAYKKwYBBAGCNwIBDDEKMAigAoAAoQKAADAZBgkqhkiG9w0BCQMx
# DAYKKwYBBAGCNwIBBDAcBgorBgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAjBgkq
# hkiG9w0BCQQxFgQUM63Ie9PwxGXhZpn8wVCQqttfCAEwDQYJKoZIhvcNAQEBBQAE
# ggEAQaFCqFkMXY+o/sB+3vc8Uc1sku3DlvP+CnmyWvqdfvr7DKASI8L22Ep+EWSC
# 0Y5XYznuu4wlRbfYxqMZ/Fx3Z6KbbULY5faNtD1mwRXdJ5zh5rrGnUnqxJjKTxoE
# 2uSmwM27sLhM+vaZ+nM0MktU0YOGimJ5Yf9RH41NSOdITD58bppk/AwzZbvdJogK
# JldJBEQaJF8M81Uwyfeuo0yz6BAxiqpJF7pFrDNrg95KtwANeBqqSbXYBCi96XaA
# r7u8AhsZPL2jPxKgrj+S4D/IshHxV2e29ccxkqjTjYLZEgVl1ALinBhpEE0qVmJj
# tWvllJExjjMKRg81JqqVgrxwdKGCAg8wggILBgkqhkiG9w0BCQYxggH8MIIB+AIB
# ATB2MGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNV
# BAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0IEFzc3VyZWQg
# SUQgQ0EtMQIQAwGaAjr/WLFr1tXq5hfwZjAJBgUrDgMCGgUAoF0wGAYJKoZIhvcN
# AQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMjAwMjAzMTIzOTA2WjAj
# BgkqhkiG9w0BCQQxFgQUd9q8oLVbFfcLdkBfLTALvTs5VKEwDQYJKoZIhvcNAQEB
# BQAEggEAI+8HFX4MHtUqlLE2z8Zb8P6BUxvfUtPm0d9/Up1VB34XBseokfKOQQdR
# Yg2qnFhSBjGl9KKVSe5CkCGwvuu6dS6Ho0sYQslXw0nDVOOFoJcoSXw/GL0OyRqV
# Du0n9ET+R6e2Xw1y4twjbkWSKvKnMujOGIVyUdVarKVyKpoTNiXRtklB29QaD7e/
# tc3cW4riKoSiV/CND1SS+leFCGzsTyxxYtLSaeQJSZ0LfIyYMWRAt9AYnL5TENm3
# 3EhT/s1qm9V6il6CykVnRC6lwnA88Jd+R+lTcLAuhTxfnIGJNZpTyxfO9jECUZmU
# hgDu0j5jwf606QzTRJe37cmfzy1GSQ==
# SIG # End signature block