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 |