dbatools.library.psm1
|
param( # Automatically skip loading assemblies that are already loaded (useful when SqlServer module is already imported) [Alias('SkipLoadedAssemblies', 'AllowSharedAssemblies')] [switch]$AvoidConflicts ) function Get-DbatoolsLibraryPath { [CmdletBinding()] param() if ($PSVersionTable.PSEdition -eq "Core") { Join-Path -Path $PSScriptRoot -ChildPath core } else { Join-Path -Path $PSScriptRoot -ChildPath desktop } } $script:libraryroot = Get-DbatoolsLibraryPath if ($PSVersionTable.PSEdition -ne "Core") { if (-not ("Redirector" -as [type])) { $source = @" using System; using System.IO; using System.Reflection; public class Redirector { private static string _libPath; public Redirector(string libPath) { _libPath = libPath; this.EventHandler = new ResolveEventHandler(AssemblyResolve); } public readonly ResolveEventHandler EventHandler; protected static Assembly AssemblyResolve(object sender, ResolveEventArgs e) { var requestedName = new AssemblyName(e.Name); var assemblyName = requestedName.Name; // First, check if any version of this assembly is already loaded // This handles version mismatches (e.g., SMO requesting SqlClient 5.0.0.0 when 6.0.2 is loaded) foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) { try { if (assembly.GetName().Name == assemblyName) { return assembly; } } catch { // Some assemblies may throw when accessing GetName() } } // Try to load from our lib folder if the file exists string dllPath = Path.Combine(_libPath, assemblyName + ".dll"); if (File.Exists(dllPath)) { try { return Assembly.LoadFrom(dllPath); } catch { // Failed to load, return null to let default resolution continue } } return null; } } "@ $null = Add-Type -TypeDefinition $source } try { $libPath = [System.IO.Path]::Combine($script:libraryroot, "lib") $redirector = New-Object Redirector($libPath) [System.AppDomain]::CurrentDomain.add_AssemblyResolve($redirector.EventHandler) } catch { Write-Verbose "Could not register Redirector: $_" } } else { # PowerShell Core: Use AssemblyLoadContext.Resolving event for version redirection # This handles version mismatches when SqlServer module loads different versions of assemblies # IMPORTANT: Must be implemented in C# because the resolver runs on .NET threads without PowerShell runspaces $dir = [System.IO.Path]::Combine($script:libraryroot, "lib") + [System.IO.Path]::DirectorySeparatorChar if (-not ("CoreRedirector" -as [type])) { $coreSourcePath = Join-Path $PSScriptRoot "dbatools.library.CoreRedirector.cs" $coreSource = Get-Content -Path $coreSourcePath -Raw try { $null = Add-Type -TypeDefinition $coreSource -ReferencedAssemblies 'System.Runtime.Loader','System.Runtime.InteropServices','System.Collections','System.Diagnostics.TraceSource','System.Threading' } catch { Write-Verbose "Could not compile CoreRedirector: $_" } } try { [CoreRedirector]::Register($dir) } catch { Write-Verbose "Could not register CoreRedirector: $_" } } function Get-DbatoolsSqlClientPath { [CmdletBinding()] param( [Parameter(Mandatory)] [string]$LibraryRoot ) $libPath = [System.IO.Path]::Combine($LibraryRoot, "lib") if ($PSVersionTable.PSEdition -eq "Core") { if ($IsWindows) { $runtimeSqlClient = [System.IO.Path]::Combine($libPath, "runtimes", "win", "lib", "net8.0", "Microsoft.Data.SqlClient.dll") } else { $runtimeSqlClient = [System.IO.Path]::Combine($libPath, "runtimes", "unix", "lib", "net8.0", "Microsoft.Data.SqlClient.dll") } if (Test-Path $runtimeSqlClient) { return $runtimeSqlClient } } [System.IO.Path]::Combine($libPath, "Microsoft.Data.SqlClient.dll") } function Add-DbatoolsNativeSearchPath { [CmdletBinding()] param( [Parameter(Mandatory)] [string]$LibraryRoot ) if ($PSVersionTable.PSEdition -ne "Core" -or -not $IsWindows) { return } $architecture = [System.Runtime.InteropServices.RuntimeInformation]::ProcessArchitecture.ToString().ToLowerInvariant() $nativeRid = "win-$architecture" $nativePath = [System.IO.Path]::Combine($LibraryRoot, "lib", "runtimes", $nativeRid, "native") if (-not (Test-Path $nativePath)) { return } $pathSeparator = [System.IO.Path]::PathSeparator $pathParts = $env:PATH -split [Regex]::Escape([string]$pathSeparator) if ($pathParts -contains $nativePath) { return } $env:PATH = $nativePath + $pathSeparator + $env:PATH } Add-DbatoolsNativeSearchPath -LibraryRoot $script:libraryroot $sqlclient = Get-DbatoolsSqlClientPath -LibraryRoot $script:libraryroot # Get loaded assemblies once for reuse (used for AvoidConflicts checks and later assembly loading) $script:loadedAssemblies = [System.AppDomain]::CurrentDomain.GetAssemblies() # Check for incompatible System.ClientModel or SqlClient versions # Azure.Core 1.44+ requires System.ClientModel 1.1+ with IPersistableModel.Write() method # SqlServer module's SqlClient 5.x includes older System.ClientModel that's incompatible $script:hasIncompatibleClientModel = $false if ($AvoidConflicts) { # Check if System.ClientModel is already loaded with incompatible version $existingClientModel = $script:loadedAssemblies | Where-Object { $_.GetName().Name -eq 'System.ClientModel' } if ($existingClientModel) { $clientModelVersion = $existingClientModel.GetName().Version # System.ClientModel 1.1.0+ has the required IPersistableModel interface changes if ($clientModelVersion -lt [Version]'1.1.0') { $script:hasIncompatibleClientModel = $true Write-Verbose "Detected incompatible System.ClientModel version $clientModelVersion - will skip Azure.Core and Azure.Identity to avoid MissingMethodException" } } # Check if SqlServer's older SqlClient is loaded (which bundles incompatible System.ClientModel) # SqlClient 5.x from SqlServer module uses System.ClientModel 1.0.x # Our Azure.Core requires System.ClientModel 1.1+ if (-not $script:hasIncompatibleClientModel) { $existingSqlClient = $script:loadedAssemblies | Where-Object { $_.GetName().Name -eq 'Microsoft.Data.SqlClient' } if ($existingSqlClient) { $sqlClientVersion = $existingSqlClient.GetName().Version # SqlClient 5.x bundles older System.ClientModel; 6.x bundles compatible versions if ($sqlClientVersion.Major -lt 6) { $script:hasIncompatibleClientModel = $true Write-Verbose "Detected SqlClient $sqlClientVersion (pre-6.0) which uses incompatible System.ClientModel - will skip Azure.Core and Azure.Identity to avoid MissingMethodException" } } } } # Check if SqlClient is already loaded when AvoidConflicts is set $skipSqlClient = $false if ($AvoidConflicts) { $existingAssembly = $script:loadedAssemblies | Where-Object { $_.GetName().Name -eq 'Microsoft.Data.SqlClient' } if ($existingAssembly) { $skipSqlClient = $true Write-Verbose "Skipping Microsoft.Data.SqlClient.dll - already loaded" } } if (-not $skipSqlClient) { try { Import-Module $sqlclient } catch { throw "Couldn't import $sqlclient | $PSItem" } } if ($PSVersionTable.PSEdition -eq "Core") { $names = @( 'Microsoft.SqlServer.Server', 'Azure.Core', 'Azure.Identity', 'Microsoft.IdentityModel.Abstractions', 'Microsoft.SqlServer.Dac', 'Microsoft.SqlServer.Dac.Extensions', 'Microsoft.Data.Tools.Utilities', 'Microsoft.Data.Tools.Schema.Sql', 'Microsoft.SqlServer.TransactSql.ScriptDom', 'Microsoft.SqlServer.Smo', 'Microsoft.SqlServer.SmoExtended', 'Microsoft.SqlServer.SqlWmiManagement', 'Microsoft.SqlServer.WmiEnum', 'Microsoft.SqlServer.Management.RegisteredServers', 'Microsoft.SqlServer.Management.Collector', 'Microsoft.SqlServer.Management.XEvent', 'Microsoft.SqlServer.Management.XEventDbScoped', 'Microsoft.SqlServer.XEvent.XELite' ) } else { $names = @( 'Azure.Core', 'Azure.Identity', 'Microsoft.IdentityModel.Abstractions', 'Microsoft.SqlServer.Dac', 'Microsoft.SqlServer.Dac.Extensions', 'Microsoft.Data.Tools.Utilities', 'Microsoft.Data.Tools.Schema.Sql', 'Microsoft.SqlServer.TransactSql.ScriptDom', 'Microsoft.SqlServer.Smo', 'Microsoft.SqlServer.SmoExtended', 'Microsoft.SqlServer.SqlWmiManagement', 'Microsoft.SqlServer.WmiEnum', 'Microsoft.SqlServer.Management.RegisteredServers', 'Microsoft.SqlServer.Management.IntegrationServices', 'Microsoft.SqlServer.Management.Collector', 'Microsoft.SqlServer.Management.XEvent', 'Microsoft.SqlServer.Management.XEventDbScoped', 'Microsoft.SqlServer.XEvent.XELite' ) } if ($Env:SMODefaultModuleName) { # then it's DSC, load other required assemblies $names += "Microsoft.AnalysisServices.Core" $names += "Microsoft.AnalysisServices" $names += "Microsoft.AnalysisServices.Tabular" $names += "Microsoft.AnalysisServices.Tabular.Json" } # XEvent stuff kills CI/CD if ($PSVersionTable.OS -match "ARM64") { $names = $names | Where-Object { $PSItem -notmatch "XE" } } #endregion Names # Build string of loaded assembly names once for efficient checking $script:loadedAssemblyNames = $script:loadedAssemblies.FullName | Out-String try { $null = Import-Module ([IO.Path]::Combine($script:libraryroot, "third-party", "bogus", "Bogus.dll")) } catch { Write-Error "Could not import $assemblyPath : $($_ | Out-String)" } foreach ($name in $names) { $x64only = 'Microsoft.SqlServer.Replication', 'Microsoft.SqlServer.XEvent.Linq', 'Microsoft.SqlServer.BatchParser', 'Microsoft.SqlServer.Rmo', 'Microsoft.SqlServer.BatchParserClient' if ($name -in $x64only -and $env:PROCESSOR_ARCHITECTURE -eq "x86") { Write-Verbose -Message "Skipping $name. x86 not supported for this library." continue } # Skip Azure.Core and Azure.Identity if System.ClientModel is incompatible # These assemblies depend on System.ClientModel 1.1+ which has breaking API changes if ($script:hasIncompatibleClientModel -and $name -in @('Azure.Core', 'Azure.Identity')) { Write-Verbose "Skipping $name.dll - incompatible System.ClientModel already loaded" continue } # Check if assembly is already loaded (always check to avoid duplicate loads) if ($script:loadedAssemblyNames.Contains("$name,")) { if ($AvoidConflicts) { Write-Verbose "Skipping $name.dll - already loaded" } continue } # Load the assembly $assemblyPath = [IO.Path]::Combine($script:libraryroot, "lib", "$name.dll") try { $null = Import-Module $assemblyPath } catch { Write-Error "Could not import $assemblyPath : $($_ | Out-String)" } } # Keep the assembly resolver registered for Windows PowerShell # It's needed at runtime when SMO and other assemblies try to resolve dependencies # The resolver handles version mismatches (e.g., SMO requesting SqlClient 5.0.0.0 when 6.0.2 is loaded) if ($PSVersionTable.PSEdition -ne "Core" -and $redirector) { # Store the redirector in script scope so it stays alive and can be accessed if needed $script:assemblyRedirector = $redirector } # SIG # Begin signature block # MIItZgYJKoZIhvcNAQcCoIItVzCCLVMCAQMxDTALBglghkgBZQMEAgEwewYKKwYB # BAGCNwIBBKBtBGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBcmRmVoY7I+SWz # yK/iHfT7KZgGp1dqx1a5FLrvS2Fc+6CCFWUwggaTMIIEe6ADAgECAhMzAAYzD5v/ # iZ2s6Qv8AAAABjMPMA0GCSqGSIb3DQEBDAUAMFoxCzAJBgNVBAYTAlVTMR4wHAYD # VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKzApBgNVBAMTIk1pY3Jvc29mdCBJ # RCBWZXJpZmllZCBDUyBFT0MgQ0EgMDQwHhcNMjYwOTE1MDYwMTAxWhcNMjYwOTE4 # MDYwMTAxWjBXMQswCQYDVQQGEwJVUzERMA8GA1UECBMIVmlyZ2luaWExDzANBgNV # BAcTBlZpZW5uYTERMA8GA1UEChMIZGJhdG9vbHMxETAPBgNVBAMTCGRiYXRvb2xz # MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAr4aaea8sBCP7oYtzyv8j # cWzjovepD6cmgtaO9w8wclwoZYmbHY/zOPv50TADUFktRjg+gbITeAKXa0wbJ73W # Lbb0uThTyEBgqyMOXZVtozRzJfgDbsIV2sb3WOEQEeP1igEPfOaAR1PwmqpZiyN0 # T6J728NIkMghOutUQchBKhuafBVFuDqhM1lTrL+gqRTfDrtS1b2UwYIfZEuo2BSt # mXqQz+5/4Yc9be1B7ta243FzEB7GhhLrg8J3PvsE0LSOgjbKNKiiFNpdQr17dmn4 # W+J2yrl1gUuiMtXZCdxfJJYL9yObeQbxmAYkiPlgfM1DlnLvz4WkFjmihfW5nN3t # nlBspzRai6dlUd/DwDn0fftmn3hBavJ6guVlMVTjCUKIkFvWdQ7JsgFDZ2B2KHnS # hbi/+FSbUYAwg1aUU00U6zovWy2slsLSzLWeobhRm1djv7nzcXF5LHNbPFn+CUzC # 3hT/OTDRZu4bgC7/mXWRWH30LLUcwIIvRYz+9vIndCP9AgMBAAGjggHTMIIBzzAM # BgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIHgDA6BgNVHSUEMzAxBgorBgEEAYI3 # YQEABggrBgEFBQcDAwYZKwYBBAGCN2H5+cEspPS4DoOuxLIcm56wGDAdBgNVHQ4E # FgQUHNdUHgxd14fLhGkjCU3Ci47DgS0wHwYDVR0jBBgwFoAUmvFUd3UMhxY3RqCs # 3nn59H/BeOkwZwYDVR0fBGAwXjBcoFqgWIZWaHR0cDovL3d3dy5taWNyb3NvZnQu # Y29tL3BraW9wcy9jcmwvTWljcm9zb2Z0JTIwSUQlMjBWZXJpZmllZCUyMENTJTIw # RU9DJTIwQ0ElMjAwNC5jcmwwdAYIKwYBBQUHAQEEaDBmMGQGCCsGAQUFBzAChlho # dHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY3Jvc29mdCUy # MElEJTIwVmVyaWZpZWQlMjBDUyUyMEVPQyUyMENBJTIwMDQuY3J0MFQGA1UdIARN # MEswSQYEVR0gADBBMD8GCCsGAQUFBwIBFjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5j # b20vcGtpb3BzL0RvY3MvUmVwb3NpdG9yeS5odG0wDQYJKoZIhvcNAQEMBQADggIB # AHE0HJscMcw1iPBZSTqYQo1trie2J/IWqmsEeGB1XktLTksynglC8cHF4VqwCnF+ # 5fPraqpZpcVieMZptHRY+7AurCTPTuLF83gAN+WudruSR0ETkR30RrsKf5vo9MVA # uTP/E4yfMffn02fcGIuoPseEEssm8pYU9+8+9CadUZdCOwQ8n3MT6lb/0TdZ2ef5 # ew+DOpgd94vHdGq+aDh2h0CPrzQhoGZ5RqMr0fdaijcEch9/9xNuj3ddkooIyk6G # D3Q6sNp71ECxOvPxHWrsW7E9QCh5lcxUk4hvy5BxCYgJPmiJ0RHCoVf9n8Wf35h3 # InJRUN4FaHBd97YS6KVhCraKcSvUv1lPhSxBo6YKXjS5EoNQ/X7ZKoc+sFpOud8c # OzjX01pgvw3ls5QzDRhmop0WqUj0ZSe9liPoQQs5Gx7r8ciCHL6ST4SvD8uc2FhV # 3pN6Lu7BTzMdzKjgeamRoxkdoKVfBCSpjRBX40N1Do7cWfj9w0VzVMpqh8LutYpD # yuCLfGoGwe/Luvzlo78ZIpz1SX0RECUPAbyvnSnvQex/WBDAmSvm+gBCNTRX2EIK # YRdn2ixZjJm6tvQXKXpGy+1LShj4CrAKP9ChW21hhfM+H3o/agPF4+veRqBm2HeQ # kzbTXAPfwZ5ejxykneiI2zNZodz/dsrvBCCnrjWm26KQMIIHKDCCBRCgAwIBAgIT # MwAAABcnRQkLi4evxgAAAAAAFzANBgkqhkiG9w0BAQwFADBjMQswCQYDVQQGEwJV # UzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTQwMgYDVQQDEytNaWNy # b3NvZnQgSUQgVmVyaWZpZWQgQ29kZSBTaWduaW5nIFBDQSAyMDIxMB4XDTI2MDMy # NjE4MTEzMVoXDTMxMDMyNjE4MTEzMVowWjELMAkGA1UEBhMCVVMxHjAcBgNVBAoT # FU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjErMCkGA1UEAxMiTWljcm9zb2Z0IElEIFZl # cmlmaWVkIENTIEVPQyBDQSAwNDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC # ggIBAILHZP4DD2YqAZXMn5OrQ8yfj0beK0ixilvHsKUtJEcV7VEQt09xnWwipY6G # xJ/LrLKoRqkKUYf0l70VcDVxCBm++lBuSD5AidUuv/QQ+tUELCsz3qVtEjY/E14L # Bcb0uzJbaEbopCCKe0OY0IGjjOkMivfvumVV1KWJmbpQHusfCa8GdHTZBPq2eupa # raKHMHqVElVMTO6HQ5p/Mgx4ydgzT7H697kQ4sd1+Kr4deIx/0lvtgse1iDIciIk # DttNYuoVIsZpOHtmVvFuwtcD3U46ugSm/s6PMW67e2SkL0V+UDgOnYS6rj6o+bFS # p8an5NfSAtEmn00k7PMguNxMPeuQUUVvFS/XHKDpq+K8UMu2goGEzZN3Xfy6YTWk # 05pxqe5Ji08ch5AeYHqFoWLrhq8sEvBNMCb9FuK3zrRwVdHvbCr7lCHiFKZ7Meop # cRFY+lUF74A+sngipz5o94yYiSgJZlA7bYecs0VQVJeOLDIhuC+Uf8sgAkSpNp9P # PENmAqGUtTvOvqDCyrdY2lxhAjo27FafCHdVUMPIXuidCoqzkuXtuV5U3RjxW+qA # TjmmnIFu/Co39G6fl8wIJHPdpgxjSRmEo73Z4/u3jMepnltAwCBnS0TY/P+NvTCL # KRQX89yg6qqTe9UuJENiy3q93cYQw3MylRS9By8Ebjr4I4hvAgMBAAGjggHcMIIB # 2DAOBgNVHQ8BAf8EBAMCAYYwEAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0OBBYEFJrx # VHd1DIcWN0agrN55+fR/wXjpMFQGA1UdIARNMEswSQYEVR0gADBBMD8GCCsGAQUF # BwIBFjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL0RvY3MvUmVwb3Np # dG9yeS5odG0wGQYJKwYBBAGCNxQCBAweCgBTAHUAYgBDAEEwEgYDVR0TAQH/BAgw # BgEB/wIBADAfBgNVHSMEGDAWgBTZQSmwDw9jbO9p1/XNKZ6kSGow5jBwBgNVHR8E # aTBnMGWgY6Bhhl9odHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NybC9N # aWNyb3NvZnQlMjBJRCUyMFZlcmlmaWVkJTIwQ29kZSUyMFNpZ25pbmclMjBQQ0El # MjAyMDIxLmNybDB9BggrBgEFBQcBAQRxMG8wbQYIKwYBBQUHMAKGYWh0dHA6Ly93 # d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY2VydHMvTWljcm9zb2Z0JTIwSUQlMjBW # ZXJpZmllZCUyMENvZGUlMjBTaWduaW5nJTIwUENBJTIwMjAyMS5jcnQwDQYJKoZI # hvcNAQEMBQADggIBAJB1Whn9TSbfyXaIppkWWzFq+m2mg4vJpHVr1krZNIXWQ6cU # mEwOx7oqQKCy96iISNdNVzpe3zogoefvo2TmpkHQFe/aIxFDaCIAmZi9lyay2hmp # 8HYzcp3nCcmFQk60X9voeypJ6VjqeGsXTrOivWUOYNCLEFlwsH3NHX5EpCyjWN6Q # 3Fi5ST4do3eTVLnuqTQ7/9huTBTSYQsJbTg3m8gIxnHlPlzs2r/u4u9tWEJ0Pt/Z # tmkDhTu86QHWigHgBoRHemOgnQxp3ksXKLo1r2n1m7+Gst46NTkUi1LljGyq+V9f # EBOEnXvoKaRiy0pGbK1IdnsmEpF9Xp71l+2T84Nv8IrikZUBWqw5/jffttAas4cc # JDci832CadS4OHwl29uF6hY8fEg3UYHmxSJjnzi1c3vF0PwsJKxGom9Dx7treBlZ # OBWK6BGzVBar43Qb02N7okeU3UKMl6GB74fk8aS0mNr6O4YSvQ/66RKRwvqppnEV # BOHdIMjvWW9b77duX8TN3pI7w31R3D6t6jK9EcLJOJKymVlBIFNUl0+ajeoKka7I # cW0+jkIGff8U9OKol3cz0Eeiop3Qb0qaDp8ZwC8XCcs1cDaSi/vbvBGWMvfKl+ov # uIBP9ienG6XpHAdGVw5/10MaDVFG+v3Y0/8JZVchvryB5Hau9T82x+a2MXXAMIIH # njCCBYagAwIBAgITMwAAAAeHozSje6WOHAAAAAAABzANBgkqhkiG9w0BAQwFADB3 # MQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMUgw # RgYDVQQDEz9NaWNyb3NvZnQgSWRlbnRpdHkgVmVyaWZpY2F0aW9uIFJvb3QgQ2Vy # dGlmaWNhdGUgQXV0aG9yaXR5IDIwMjAwHhcNMjEwNDAxMjAwNTIwWhcNMzYwNDAx # MjAxNTIwWjBjMQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBv # cmF0aW9uMTQwMgYDVQQDEytNaWNyb3NvZnQgSUQgVmVyaWZpZWQgQ29kZSBTaWdu # aW5nIFBDQSAyMDIxMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAsvDA # rxmIKOLdVHpMSWxpCFUJtFL/ekr4weslKPdnF3cpTeuV8veqtmKVgok2rO0D05Bp # yvUDCg1wdsoEtuxACEGcgHfjPF/nZsOkg7c0mV8hpMT/GvB4uhDvWXMIeQPsDgCz # UGzTvoi76YDpxDOxhgf8JuXWJzBDoLrmtThX01CE1TCCvH2sZD/+Hz3RDwl2MsvD # SdX5rJDYVuR3bjaj2QfzZFmwfccTKqMAHlrz4B7ac8g9zyxlTpkTuJGtFnLBGaso # Onn5NyYlf0xF9/bjVRo4Gzg2Yc7KR7yhTVNiuTGH5h4eB9ajm1OCShIyhrKqgOkc # 4smz6obxO+HxKeJ9bYmPf6KLXVNLz8UaeARo0BatvJ82sLr2gqlFBdj1sYfqOf00 # Qm/3B4XGFPDK/H04kteZEZsBRc3VT2d/iVd7OTLpSH9yCORV3oIZQB/Qr4nD4YT/ # lWkhVtw2v2s0TnRJubL/hFMIQa86rcaGMhNsJrhysLNNMeBhiMezU1s5zpusf54q # lYu2v5sZ5zL0KvBDLHtL8F9gn6jOy3v7Jm0bbBHjrW5yQW7S36ALAt03QDpwW1JG # 1Hxu/FUXJbBO2AwwVG4Fre+ZQ5Od8ouwt59FpBxVOBGfN4vN2m3fZx1gqn52Gvai # Bz6ozorgIEjn+PhUXILhAV5Q/ZgCJ0u2+ldFGjcCAwEAAaOCAjUwggIxMA4GA1Ud # DwEB/wQEAwIBhjAQBgkrBgEEAYI3FQEEAwIBADAdBgNVHQ4EFgQU2UEpsA8PY2zv # adf1zSmepEhqMOYwVAYDVR0gBE0wSzBJBgRVHSAAMEEwPwYIKwYBBQUHAgEWM2h0 # dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvRG9jcy9SZXBvc2l0b3J5Lmh0 # bTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTAPBgNVHRMBAf8EBTADAQH/MB8G # A1UdIwQYMBaAFMh+0mqFKhvKGZgEByfPUBBPaKiiMIGEBgNVHR8EfTB7MHmgd6B1 # hnNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NybC9NaWNyb3NvZnQl # MjBJZGVudGl0eSUyMFZlcmlmaWNhdGlvbiUyMFJvb3QlMjBDZXJ0aWZpY2F0ZSUy # MEF1dGhvcml0eSUyMDIwMjAuY3JsMIHDBggrBgEFBQcBAQSBtjCBszCBgQYIKwYB # BQUHMAKGdWh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY2VydHMvTWlj # cm9zb2Z0JTIwSWRlbnRpdHklMjBWZXJpZmljYXRpb24lMjBSb290JTIwQ2VydGlm # aWNhdGUlMjBBdXRob3JpdHklMjAyMDIwLmNydDAtBggrBgEFBQcwAYYhaHR0cDov # L29uZW9jc3AubWljcm9zb2Z0LmNvbS9vY3NwMA0GCSqGSIb3DQEBDAUAA4ICAQB/ # JSqe/tSr6t1mCttXI0y6XmyQ41uGWzl9xw+WYhvOL47BV09Dgfnm/tU4ieeZ7NAR # 5bguorTCNr58HOcA1tcsHQqt0wJsdClsu8bpQD9e/al+lUgTUJEV80Xhco7xdgRr # ehbyhUf4pkeAhBEjABvIUpD2LKPho5Z4DPCT5/0TlK02nlPwUbv9URREhVYCtsDM # +31OFU3fDV8BmQXv5hT2RurVsJHZgP4y26dJDVF+3pcbtvh7R6NEDuYHYihfmE2H # dQRq5jRvLE1Eb59PYwISFCX2DaLZ+zpU4bX0I16ntKq4poGOFaaKtjIA1vRElIta # OKcwtc04CBrXSfyL2Op6mvNIxTk4OaswIkTXbFL81ZKGD+24uMCwo/pLNhn7VHLf # nxlMVzHQVL+bHa9KhTyzwdG/L6uderJQn0cGpLQMStUuNDArxW2wF16QGZ1NtBWg # KA8Kqv48M8HfFqNifN6+zt6J0GwzvU8g0rYGgTZR8zDEIJfeZxwWDHpSxB5FJ1VV # U1LIAtB7o9PXbjXzGifaIMYTzU4YKt4vMNwwBmetQDHhdAtTPplOXrnI9SI6HeTt # jDD3iUN/7ygbahmYOHk7VB7fwT4ze+ErCbMh6gHV1UuXPiLciloNxH6K4aMfZN1o # LVk6YFeIJEokuPgNPa6EnTiOL60cPqfny+Fq8UiuZzGCF1cwghdTAgEBMHEwWjEL # MAkGA1UEBhMCVVMxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjErMCkG # A1UEAxMiTWljcm9zb2Z0IElEIFZlcmlmaWVkIENTIEVPQyBDQSAwNAITMwAGMw+b # /4mdrOkL/AAAAAYzDzALBglghkgBZQMEAgGgfDAQBgorBgEEAYI3AgEMMQIwADAZ # BgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgorBgEEAYI3AgELMQ4wDAYKKwYB # BAGCNwIBFTAvBgkqhkiG9w0BCQQxIgQgrTp9UG5QBephf9keJRCXW8Dqb6Gp2fch # FiXJVY6AP7gwCwYJKoZIhvcNAQEBBIIBgIyVR9HWQCJEDbHAdUgsJIf2PYrWEbV1 # acpIihdm8SXS9Ro9z/3HKSVG5pBucIAhQ2+UtzXHzO1i74bWORP6Au20bLkHWU9o # o2tBg4p3IywcEe2yZZJnbbSqXvLGprivtvBifAAcxfk5pLgaCuEp0KaAGdAAgnl4 # kOR363JFEEUuqi/eKkO3P/p3GzN8tx+hnQ52Wdj3A18x/xYHULdXrjogpB13g1iW # vDEKSN2YFOWq0OIwCK2lZIRyHN5GxCyA03voXo7Wzrnh0Tjj/Dynbb4XZupUOBwL # l/cfv6MWJqvVHUKy3whL8pL/DrNsCcJ7phbiN16QFheJVg4JKBR9ZbvMlOKTDxO3 # 15ev89Y1vBgVqUn1YA61oRv1N6uzsLhclfEKfzsp4skoj/e0BqIsvYpucmLYrzt1 # JYoVh74hLhs5f8ZaP62ybguwGeG0/2tO54CXecrD8YALUAfqi42T5REs5njXPLN+ # smeJxBHCe0cfBNANw4RvxvXCJyvemaaj/6GCFL0wghS5BgorBgEEAYI3AwMBMYIU # qTCCFKUGCSqGSIb3DQEHAqCCFJYwghSSAgEDMQ8wDQYJYIZIAWUDBAIBBQAwggF1 # BgsqhkiG9w0BCRABBKCCAWQEggFgMIIBXAIBAQYKKwYBBAGEWQoDATAxMA0GCWCG # SAFlAwQCAQUABCAnEfPmzixyWjXWUAuP3kTWmJ0Hr+rdRPQwbkaHGz6LIgIGapqx # UKfmGBMyMDI2MDkxNjE4NTAzOS42MzdaMASAAgH0AgkA0L5bHyx7O2qggemkgeYw # geMxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdS # ZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xLTArBgNVBAsT # JE1pY3Jvc29mdCBJcmVsYW5kIE9wZXJhdGlvbnMgTGltaXRlZDEnMCUGA1UECxMe # blNoaWVsZCBUU1MgRVNOOjdCMUEtMDVFMC1EOTQ3MTUwMwYDVQQDEyxNaWNyb3Nv # ZnQgUHVibGljIFJTQSBUaW1lIFN0YW1waW5nIEF1dGhvcml0eaCCDykwggeCMIIF # aqADAgECAhMzAAAABeXPD/9mLsmHAAAAAAAFMA0GCSqGSIb3DQEBDAUAMHcxCzAJ # BgNVBAYTAlVTMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xSDBGBgNV # BAMTP01pY3Jvc29mdCBJZGVudGl0eSBWZXJpZmljYXRpb24gUm9vdCBDZXJ0aWZp # Y2F0ZSBBdXRob3JpdHkgMjAyMDAeFw0yMDExMTkyMDMyMzFaFw0zNTExMTkyMDQy # MzFaMGExCzAJBgNVBAYTAlVTMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRp # b24xMjAwBgNVBAMTKU1pY3Jvc29mdCBQdWJsaWMgUlNBIFRpbWVzdGFtcGluZyBD # QSAyMDIwMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAnnznUmP94MWf # BX1jtQYioxwe1+eXM9ETBb1lRkd3kcFdcG9/sqtDlwxKoVIcaqDb+omFio5DHC4R # BcbyQHjXCwMk/l3TOYtgoBjxnG/eViS4sOx8y4gSq8Zg49REAf5huXhIkQRKe3Qx # s8Sgp02KHAznEa/Ssah8nWo5hJM1xznkRsFPu6rfDHeZeG1Wa1wISvlkpOQooTUL # Fm809Z0ZYlQ8Lp7i5F9YciFlyAKwn6yjN/kR4fkquUWfGmMopNq/B8U/pdoZkZZQ # bxNlqJOiBGgCWpx69uKqKhTPVi3gVErnc/qi+dR8A2MiAz0kN0nh7SqINGbmw5OI # RC0EsZ31WF3Uxp3GgZwetEKxLms73KG/Z+MkeuaVDQQheangOEMGJ4pQZH55ngI0 # Tdy1bi69INBV5Kn2HVJo9XxRYR/JPGAaM6xGl57Ei95HUw9NV/uC3yFjrhc087qL # JQawSC3xzY/EXzsT4I7sDbxOmM2rl4uKK6eEpurRduOQ2hTkmG1hSuWYBunFGNv2 # 1Kt4N20AKmbeuSnGnsBCd2cjRKG79+TX+sTehawOoxfeOO/jR7wo3liwkGdzPJYH # gnJ54UxbckF914AqHOiEV7xTnD1a69w/UTxwjEugpIPMIIE67SFZ2PMo27xjlLAH # WW3l1CEAFjLNHd3EQ79PUr8FUXetXr0CAwEAAaOCAhswggIXMA4GA1UdDwEB/wQE # AwIBhjAQBgkrBgEEAYI3FQEEAwIBADAdBgNVHQ4EFgQUa2koOjUvSGNAz3vYr0np # Ptk92yEwVAYDVR0gBE0wSzBJBgRVHSAAMEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly93 # d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvRG9jcy9SZXBvc2l0b3J5Lmh0bTATBgNV # HSUEDDAKBggrBgEFBQcDCDAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTAPBgNV # HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFMh+0mqFKhvKGZgEByfPUBBPaKiiMIGE # BgNVHR8EfTB7MHmgd6B1hnNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3Bz # L2NybC9NaWNyb3NvZnQlMjBJZGVudGl0eSUyMFZlcmlmaWNhdGlvbiUyMFJvb3Ql # MjBDZXJ0aWZpY2F0ZSUyMEF1dGhvcml0eSUyMDIwMjAuY3JsMIGUBggrBgEFBQcB # AQSBhzCBhDCBgQYIKwYBBQUHMAKGdWh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9w # a2lvcHMvY2VydHMvTWljcm9zb2Z0JTIwSWRlbnRpdHklMjBWZXJpZmljYXRpb24l # MjBSb290JTIwQ2VydGlmaWNhdGUlMjBBdXRob3JpdHklMjAyMDIwLmNydDANBgkq # hkiG9w0BAQwFAAOCAgEAX4h2x35ttVoVdedMeGj6TuHYRJklFaW4sTQ5r+k77iB7 # 9cSLNe+GzRjv4pVjJviceW6AF6ycWoEYR0LYhaa0ozJLU5Yi+LCmcrdovkl53DNt # 4EXs87KDogYb9eGEndSpZ5ZM74LNvVzY0/nPISHz0Xva71QjD4h+8z2XMOZzY7YQ # 0Psw+etyNZ1CesufU211rLslLKsO8F2aBs2cIo1k+aHOhrw9xw6JCWONNboZ497m # wYW5EfN0W3zL5s3ad4Xtm7yFM7Ujrhc0aqy3xL7D5FR2J7x9cLWMq7eb0oYioXhq # V2tgFqbKHeDick+P8tHYIFovIP7YG4ZkJWag1H91KlELGWi3SLv10o4KGag42psw # jybTi4toQcC/irAodDW8HNtX+cbz0sMptFJK+KObAnDFHEsukxD+7jFfEV9Hh/+C # SxKRsmnuiovCWIOb+H7DRon9TlxydiFhvu88o0w35JkNbJxTk4MhF/KgaXn0GxdH # 8elEa2Imq45gaa8D+mTm8LWVydt4ytxYP/bqjN49D9NZ81coE6aQWm88TwIf4R4Y # ZbOpMKN0CyejaPNN41LGXHeCUMYmBx3PkP8ADHD1J2Cr/6tjuOOCztfp+o9Nc+Zo # IAkpUcA/X2gSMkgHAPUvIdtoSAHEUKiBhI6JQivRepyvWcl+JYbYbBh7pmgAXVsw # ggefMIIFh6ADAgECAhMzAAAAWXzacemNXvXAAAAAAABZMA0GCSqGSIb3DQEBDAUA # MGExCzAJBgNVBAYTAlVTMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24x # MjAwBgNVBAMTKU1pY3Jvc29mdCBQdWJsaWMgUlNBIFRpbWVzdGFtcGluZyBDQSAy # MDIwMB4XDTI2MDEwODE4NTkwMVoXDTI3MDEwNzE4NTkwMVowgeMxCzAJBgNVBAYT # AlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYD # VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xLTArBgNVBAsTJE1pY3Jvc29mdCBJ # cmVsYW5kIE9wZXJhdGlvbnMgTGltaXRlZDEnMCUGA1UECxMeblNoaWVsZCBUU1Mg # RVNOOjdCMUEtMDVFMC1EOTQ3MTUwMwYDVQQDEyxNaWNyb3NvZnQgUHVibGljIFJT # QSBUaW1lIFN0YW1waW5nIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQADggIP # ADCCAgoCggIBAKYu5/40eEX+hT+5jFa146bid3dA4LnXYntvkP3CGw4LGARFhnvL # MSJ/VtsubzDaeFnm7yb2KSM70WmHQprdCVqpvUH7l0uB4jNw7urLoAR9kKHLE0Vl # MlDStDSxUBI3qwsdrjvdmvV0k+9/njuDEiSlzJTf7Dowd1K3bO4beRyaFhR+Y8ty # mECOqlOAffYrG2wZdVM51+QSBSe+PEykr8C6OnnqSipuF8fZvCb6/huk0Zm6Zwsa # ixSHIAT2IEGvS7c63Im8jV3a8R0K6i2yiw0NNlnTSpwy/Zfv7iwsLBwhfbjBTn+X # Ol6mPzDXQQ3V+SRP9xXbGKOsBTxzGid7aKAHw3o4Ahl9UGWLH9kNP3VUokE6JYkj # lfpuUGZ6gQyqDewfxD4VoYIlopt4HZ0xQvqajuJx+cr8LR/IZ56gLLmwyMzde5+v # tjBoilry/gSZwVGwgkvkIgpKPBQHGsSB0y3szr7Y7wEb6v0yZal1XUvWnnz3inTa # SWsCFrLPVwVmXy3ncY5/d25VpOkht+m697GWNbvsNOhAOHRaftE9j/hhkoM6RsyJ # fBLnhqMcA/wcavf5oj5NeyRQdGZeLKcls9csKS3sBUzPidxx2iiNH9CPaDq/bLJE # OXasYohXMnRinu+fUk81s8VO7DQSF6ffn5oqSHoV8lf1Ax6u+kdShb8BAgMBAAGj # ggHLMIIBxzAdBgNVHQ4EFgQUj5bnC18D0vlnSRhCOiODGGuXNnYwHwYDVR0jBBgw # FoAUa2koOjUvSGNAz3vYr0npPtk92yEwbAYDVR0fBGUwYzBhoF+gXYZbaHR0cDov # L3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jcmwvTWljcm9zb2Z0JTIwUHVibGlj # JTIwUlNBJTIwVGltZXN0YW1waW5nJTIwQ0ElMjAyMDIwLmNybDB5BggrBgEFBQcB # AQRtMGswaQYIKwYBBQUHMAKGXWh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lv # cHMvY2VydHMvTWljcm9zb2Z0JTIwUHVibGljJTIwUlNBJTIwVGltZXN0YW1waW5n # JTIwQ0ElMjAyMDIwLmNydDAMBgNVHRMBAf8EAjAAMBYGA1UdJQEB/wQMMAoGCCsG # AQUFBwMIMA4GA1UdDwEB/wQEAwIHgDBmBgNVHSAEXzBdMFEGDCsGAQQBgjdMg30B # ATBBMD8GCCsGAQUFBwIBFjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3Bz # L0RvY3MvUmVwb3NpdG9yeS5odG0wCAYGZ4EMAQQCMA0GCSqGSIb3DQEBDAUAA4IC # AQBEMhzC/ZcjpG/zURE7z2Yp5vrUxUjsE5Xa3t/2RGvESwvbmsk3bLHhSFAajgo2 # XQ8xoGDP3sUhKCLPeICSbkVv6V8sSp8fJ8Jos6yrawf2YVis8tcV+OO7U9S6JGPQ # zpmPncfzQc4ne1fqZ4+HiKabIDEoFdddQT2Egkk9fzxCY/EZ52avJ27dSfrI/IDm # yn9V10O3iQpg2F+C9vNTrk7nVgoDoHa9+Q3pYr0IHGnSmt5irgGT436zo5WnXP8F # xMhswH1aiyiSZiVzhor10C9C52cP3C8/PEoMKUXstLjoPO0TMkeW/1Fr186KXD45 # QRgBo0xImgtWTdzWFnlD+p7+iDBIuSrNcRXDRYuq/aYZaDhWSI0SYdPIWVh5XvXu # WA31a8oQ0SO+oPa3Nk80k0864wiiyJ1KsbSnaaefg9vspeghrpY8ljCwxfCUtx5H # QRNgAJOI8IKACK4d014Mk0hlRO0lQVRHegqIg29K6Xqkc360W2ZJGUcstlKokkVj # 6KAHjGyrLRPzepYfiZUJq4gXyxbpvKb1XJ2FN2682aUoNXo9RyRK1ch0f66k6+yj # 88kzvuC7+vJWtNDs/UpIM6Hhm0kU64JUJ7MMEQcAc7kpft7Gm7YeRK+oKgqUgYXC # fmzbX8nJXJZnPa8ADWVsIqsuNAxCI0CZXkULofqo5Be6zzGCA9QwggPQAgEBMHgw # YTELMAkGA1UEBhMCVVMxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEy # MDAGA1UEAxMpTWljcm9zb2Z0IFB1YmxpYyBSU0EgVGltZXN0YW1waW5nIENBIDIw # MjACEzMAAABZfNpx6Y1e9cAAAAAAAFkwDQYJYIZIAWUDBAIBBQCgggEtMBoGCSqG # SIb3DQEJAzENBgsqhkiG9w0BCRABBDAvBgkqhkiG9w0BCQQxIgQgEiGEM7nYQQrJ # twS5Z7x1DpzH4yBNgRiTawgL3/N1Nj0wgd0GCyqGSIb3DQEJEAIvMYHNMIHKMIHH # MIGgBCDLRbqx24bpscXEJ+Hjj9xrcUVw7R8OyyMfSB2YGK3+vDB8MGWkYzBhMQsw # CQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTIwMAYD # VQQDEylNaWNyb3NvZnQgUHVibGljIFJTQSBUaW1lc3RhbXBpbmcgQ0EgMjAyMAIT # MwAAAFl82nHpjV71wAAAAAAAWTAiBCDTAzFk4Rl+hgzXvVd6RWuJPFoEic+gRtbZ # RO327UClmjANBgkqhkiG9w0BAQsFAASCAgACHhXI1sGacW1dfNAlOyOD8uJ+DwEG # oNH6jhXJQwJxpAxbIpdHRJR71RbVceUXqm1dXYe1HNMY4dmthEiJ2c62+GYqWqtW # Khbd+avViMp/qK2hOAwPjpJc25PUMnlLIPZjEFiw17KHty/dMuYArHG09ENLkJWS # lZtTXQa2xHOLXYELiUPvh5GmrejwZpLUq+osVecI3ZRm/QGl1dKSTrzi9pFdiQXx # Vpr5OLvqlFS+U4DRzpNXviJkQajV00p7zpeNYunq2LRbtT3AJIWzqaNET2lsF6oe # jqDtUxZliHm9QBpC81wujYbJyeyj516Nyh+d6g9AogHO/c/+QmC7BSh98AHa7u21 # LrNrfY0rNlpYWhBJFcIaDbwC1aNq2dG+xMKy5NYQlSzBvJSCPCy3I+6coxmHVyTp # hXVnMOf3XTyVDJGcLfocGaX3FUH9mTvPHtL1CshyzJ1WYiY/KfihrufSKpfa6mSW # 46NyWJ1SyuuUBICoYR1K+zH9U+wkNAODENXwme2G/YNw/gdmVUOTc+Dg3pGtJ7HS # Yfap+veyCxvJOxiD8TKqfqI/UkzRZ07tDt8E4n/UlHdlA/L3uPLn60AVPvmQPs6o # QckkGMr1nCKd7Wa/Uyl2mqtkDcPeu0WK5z20qfh9eqGDSLwP58+4xQdPisCVJOuB # z5B7KqWwPcgVXg== # SIG # End signature block |