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+6CCFWUwggaTMIIEe6ADAgECAhMzAALccuJn # //7PI+uKAAAAAtxyMA0GCSqGSIb3DQEBDAUAMFoxCzAJBgNVBAYTAlVTMR4wHAYD # VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKzApBgNVBAMTIk1pY3Jvc29mdCBJ # RCBWZXJpZmllZCBDUyBBT0MgQ0EgMDMwHhcNMjYwNzA5MDM1OTA3WhcNMjYwNzEy # MDM1OTA3WjBXMQswCQYDVQQGEwJVUzERMA8GA1UECBMIVmlyZ2luaWExDzANBgNV # BAcTBlZpZW5uYTERMA8GA1UEChMIZGJhdG9vbHMxETAPBgNVBAMTCGRiYXRvb2xz # MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAjCpxcUSK3RpR80GMZ2uf # d7qrqrmBpfU4OY02HwDuWpNd+YPtIa1tFg32lkaBsIit5D0M8GfkKz3TRBRZ/+6j # IFAGTa2FNiJCmeOoSQysQE24W66QXsvppz3tYD6KOVkNp4YtQSiPiw7BH1U7kaMQ # iBje35UTTyfEGegtEwQ8PgavGw0B1Ohj1DoBFtbDiqD9c5FafCiJg1fpv8M/ATMM # JKkiXQbwkSrS2OR0Qyo7Ft0j5YsLikyJCmZCjfLv9kjHK/GVZ20guG8iA/YnX589 # UmZt0+66HXwVbU5w+xM6JNHChq0oB5JVZPlir3YFm9LpEXCIeu8AZIAt2JdKtP6B # DA750ilAACVeB9WX3u7S3wDkoNc3PepA/EHBpNTDAZo2iQfRKDIJh6EakrTbXkmU # vwmHYhkFW05or/1BfQeVBXZC6yVosDf7Oa52dSOsVw29YINY1KdfFgw1KmQ8Gf46 # ALnkCKZ0BLgmWdXhHNP8eJO87T5PCT+LKZgrNdvozTnJAgMBAAGjggHTMIIBzzAM # BgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIHgDA6BgNVHSUEMzAxBgorBgEEAYI3 # YQEABggrBgEFBQcDAwYZKwYBBAGCN2H5+cEspPS4DoOuxLIcm56wGDAdBgNVHQ4E # FgQUk02DWyLT6v1OP8EkrIo04WFYBnUwHwYDVR0jBBgwFoAUpEMMf3ZapYXnPo0o # DwwXokVpcMYwZwYDVR0fBGAwXjBcoFqgWIZWaHR0cDovL3d3dy5taWNyb3NvZnQu # Y29tL3BraW9wcy9jcmwvTWljcm9zb2Z0JTIwSUQlMjBWZXJpZmllZCUyMENTJTIw # QU9DJTIwQ0ElMjAwMy5jcmwwdAYIKwYBBQUHAQEEaDBmMGQGCCsGAQUFBzAChlho # dHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY3Jvc29mdCUy # MElEJTIwVmVyaWZpZWQlMjBDUyUyMEFPQyUyMENBJTIwMDMuY3J0MFQGA1UdIARN # MEswSQYEVR0gADBBMD8GCCsGAQUFBwIBFjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5j # b20vcGtpb3BzL0RvY3MvUmVwb3NpdG9yeS5odG0wDQYJKoZIhvcNAQEMBQADggIB # AItlH2bHp2h7InsWLgtbs4Ue/o4vnA+lYpcoczZ2TQP/xn6cr8d90wNHPWZOzeV/ # A77wc6iL6d6nqMHWGLkeW6P5o9VxRcPTt0EOMxglkeerkHCl370bbhFidHEXknwo # PR5J6EmciosS2BDWnZAbn0GlN2oS6S8x8+12Z5AcdCy7ZxtszmMswKGqrlHub1Tw # 059bp+QaktGPqF5ceOlroI/hXdfs1KeYRNFAxpdnFg+xhftkog8kGG8zud+i+Pbu # dHmEdp6BdBS2Lk1ih1Nf5HAFYGPJyFWoNhBSCS5irWIlOOS5283tdpgJCSlBl+JD # StyOgd/u1Pzs7e5dvAAtQ73iU1Lx0pWj0QtA/OUf9zU3KigL+kOwsypR7f/sX7Kb # WsViHv30htpxOP6edPc7XX4yTUyGkBFzl1/zviUZ96Xrtdmr/BT22FN8qOevK7g1 # +t3MP9bRnmyO7jYeMCirp4lJQRYUTMcBc/Q8FX0iDnjyjDKKWqGxEyOHwTRQwFSV # N3n/AItApuMhosjsJyHmq946XgN3v6ryuIpaRMStq7Kz+IA1mS3wuFVUXgsYvvhg # VXTdrIYlqlpQgBufVPRZFO0Kwt8kQvYm8cxuKM508bcTUIoAzSShhLcHIXLHmQKT # 5hownMiiciv3Gu4h3GyqohcdR1IqYSZv3R8O3m3y3A7lMIIHKDCCBRCgAwIBAgIT # MwAAABgN65FVqYoAmAAAAAAAGDANBgkqhkiG9w0BAQwFADBjMQswCQYDVQQGEwJV # UzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTQwMgYDVQQDEytNaWNy # b3NvZnQgSUQgVmVyaWZpZWQgQ29kZSBTaWduaW5nIFBDQSAyMDIxMB4XDTI2MDMy # NjE4MTEzMloXDTMxMDMyNjE4MTEzMlowWjELMAkGA1UEBhMCVVMxHjAcBgNVBAoT # FU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjErMCkGA1UEAxMiTWljcm9zb2Z0IElEIFZl # cmlmaWVkIENTIEFPQyBDQSAwMzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC # ggIBAMiA2mA0VqKJ/ZVZ5Y/kjo+cVfEn+UHft8lHnkYK9HsYtkEyQGKNuIpXCCkE # jfEzmd/jzjOcf+qdwn44KrrLeOCdBb5Hxl3tT7suOWuZyyRqXNJDSCEzESmcFbz8 # cezZXxknNCToc/5IOxu+wvst2Uf947aXiaSeEMHCvRn9D3rpO8S2HlvyQLGPW+qJ # Xhg22EsZGplH27Z8r/IExa7zeno7i6jYR2D76AR7Dkgvu+eecoWqZKH9H288nLdY # XVhxl7ABTHyxdk1SfHdmFWDn2XYumK0+LDMToUyoiypoS9V7czO4V3Zr+5YNkfpV # sPJSJErvyYiDUNBgD3MMTLIEVw0j6fFVLOCW8vq7s9G42qBxXex/oQvHDz3KxAz9 # nhHWFEVZdGnI5YooAq18EdOTRSc2I9zGYswxizyN5SM6J19U+NMivL9RXCfDF2WQ # rzlxl8EQxhn8ME07B2iY/jn1jWfyLMqRuGxr6niXD5xBXEBMEXH2CBHv0eGvJPsc # Oak8u+Qm8FnjBbgJbfZRPZIzIN7bycg5Teb6F8eVV4pwsFBzKblWhEOMhwJUju6q # AZbY80wTRx96LzMLALLocKyywlYVLt6D9hsWGcBMlzJZ8yuQ24Bsx8w3w2mDxytL # qNVWjDIPQYbnN2CL65BVxIr/rfyYDXERgremcihCA7T264MHAgMBAAGjggHcMIIB # 2DAOBgNVHQ8BAf8EBAMCAYYwEAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0OBBYEFKRD # DH92WqWF5z6NKA8MF6JFaXDGMFQGA1UdIARNMEswSQYEVR0gADBBMD8GCCsGAQUF # BwIBFjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL0RvY3MvUmVwb3Np # dG9yeS5odG0wGQYJKwYBBAGCNxQCBAweCgBTAHUAYgBDAEEwEgYDVR0TAQH/BAgw # BgEB/wIBADAfBgNVHSMEGDAWgBTZQSmwDw9jbO9p1/XNKZ6kSGow5jBwBgNVHR8E # aTBnMGWgY6Bhhl9odHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NybC9N # aWNyb3NvZnQlMjBJRCUyMFZlcmlmaWVkJTIwQ29kZSUyMFNpZ25pbmclMjBQQ0El # MjAyMDIxLmNybDB9BggrBgEFBQcBAQRxMG8wbQYIKwYBBQUHMAKGYWh0dHA6Ly93 # d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY2VydHMvTWljcm9zb2Z0JTIwSUQlMjBW # ZXJpZmllZCUyMENvZGUlMjBTaWduaW5nJTIwUENBJTIwMjAyMS5jcnQwDQYJKoZI # hvcNAQEMBQADggIBAHHHIFb5fqaF1GJLAP08wxZwZQCfHn9BTCc29l0UYRf7gNEM # iv1YKHgLzvAe3D6WDUPe7MrXQOy09fQsUsEUALe9YxhfgiZfCguGhHTGU3yZR2is # nduCekIla4jXnfVnWsLA+5StKQHF84gYOTenYQJvcej/EeLk9FJH85Sta5AfBeJp # cxO5e7chEt7PBWRmkWY3BhEPntH03HYX/Izu3M5jQeHSEYJpgQrfz/oWtLRJdp1d # bINQJ+flc4YAJGNQKcfH4lBQbR/hIcP6JuWkAjSCX5kedWZ1dfEdNl5NrQJgIiEX # Eo/b3bazSDrMuZ6JXXctZSa239QXtOtZekyLb/RQ2eJoOgfuuc8ZFXnFVfy5fLix # mKLhqzDOo8ztjv6bNytqepnwSNmTmCMuFDcDaxlqmuU67wJpGbJ9wiJUfvNV+AC+ # bzUxZcXOIB/ubLtA6+fIQU8Z12rwxJ8+19HLD9Sre4foqmhok0h89gfp9x5lKLnd # Fq3UD2CsTGrdE6OGFKlNxyG4Ei0Aw1U/Ggo1tSb6JH9fdeQv71ZCCKePId76Fcty # Vjy8AZcUPWnjQ+owikBiyYQkEUpb11/j//U3mhAOv8Vj0gEmX+hJL3v2Lmu1Ps1n # P0q9itoI9EEazRALL6xa+BBrRygzvRAlUt5XCZLFQ7/Sh3TD1CvLttIuvEagMIIH # 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 # A1UEAxMiTWljcm9zb2Z0IElEIFZlcmlmaWVkIENTIEFPQyBDQSAwMwITMwAC3HLi # Z//+zyPrigAAAALccjALBglghkgBZQMEAgGgfDAQBgorBgEEAYI3AgEMMQIwADAZ # BgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgorBgEEAYI3AgELMQ4wDAYKKwYB # BAGCNwIBFTAvBgkqhkiG9w0BCQQxIgQgrTp9UG5QBephf9keJRCXW8Dqb6Gp2fch # FiXJVY6AP7gwCwYJKoZIhvcNAQEBBIIBgGDftXYplPncDPs7yScnIMezMSjGb58/ # 0y7/bVniZa31jd5O73FUXFipvFDoStN3DR9C5cbsGGh8zoeE5lt8lqC35iptoMQy # WcqjLAClipsr8dFmWCvP/mmf8r8V3fVurIBKrmt5HsJNEm8wxSelvfX4lk7XKT+/ # 9b8TFSRk+necW85m2dj9Ym5ZykfZ+bBsyn1Ld2Li0lozvL4YkMpo8IYgPf2n2ab6 # 6j6uddqL3BDAmAX4xdoMWfzDW5hTBbkhMPmR+ouO6f1FjG/zcYHcMe/vuxSQ868K # QVgZLXJ0zEQ+rH+sxucYQay9VPCHsMax318RgNUzIyCbHShdySBI8MzB3cX+DHEf # DkGy7Z+zOzxBThQMfZv7jPM5ZRpRiIXHB4XiVqJksa/MHXXCQAJkb3VUWk4xHawY # N8pxuwsa/m+DmZht2HC/CGN8NyIxAcuLKbKXY/N5SwSkkSvvodcq7bvpUJyfSnk5 # R+Y2J6w/coG23RyEk4s7jHm2tb171Y5E36GCFL0wghS5BgorBgEEAYI3AwMBMYIU # qTCCFKUGCSqGSIb3DQEHAqCCFJYwghSSAgEDMQ8wDQYJYIZIAWUDBAIBBQAwggF1 # BgsqhkiG9w0BCRABBKCCAWQEggFgMIIBXAIBAQYKKwYBBAGEWQoDATAxMA0GCWCG # SAFlAwQCAQUABCDhFmguWvmB2gL/7FTVwQmzOgKvJuwd7xg31NsT8BlFBQIGajVn # OaI6GBMyMDI2MDcxMDIyMTg1Mi43NTZaMASAAgH0AgkAmj628C8xOx6ggemkgeYw # geMxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdS # ZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xLTArBgNVBAsT # JE1pY3Jvc29mdCBJcmVsYW5kIE9wZXJhdGlvbnMgTGltaXRlZDEnMCUGA1UECxMe # blNoaWVsZCBUU1MgRVNOOjdBMUEtMDVFMC1EOTQ3MTUwMwYDVQQDEyxNaWNyb3Nv # 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 # ggefMIIFh6ADAgECAhMzAAAAW0q1jUEybdx0AAAAAABbMA0GCSqGSIb3DQEBDAUA # MGExCzAJBgNVBAYTAlVTMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24x # MjAwBgNVBAMTKU1pY3Jvc29mdCBQdWJsaWMgUlNBIFRpbWVzdGFtcGluZyBDQSAy # MDIwMB4XDTI2MDEwODE4NTkwNVoXDTI3MDEwNzE4NTkwNVowgeMxCzAJBgNVBAYT # AlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYD # VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xLTArBgNVBAsTJE1pY3Jvc29mdCBJ # cmVsYW5kIE9wZXJhdGlvbnMgTGltaXRlZDEnMCUGA1UECxMeblNoaWVsZCBUU1Mg # RVNOOjdBMUEtMDVFMC1EOTQ3MTUwMwYDVQQDEyxNaWNyb3NvZnQgUHVibGljIFJT # QSBUaW1lIFN0YW1waW5nIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQADggIP # ADCCAgoCggIBAJBUzBbbnlDXee0B0KD5G4/475thFyfctCyuESTWQXvlLi4Wx/td # 2qUdeq4ideeg6VWhiOHfu3wJV4TUGSRtqh9Ccr1BmiBKv9iuFpgHyIBu5Qx38Zsx # wlFeXVS+ZqJJKnXRbDNQdcYSoC/6c0hQJ/PH50DBRDQkPXVwyFizLrRH9AlrJeUg # 7BKeT23zftS8/KOJLvEEbHOF6pSOY3ZVprZUWbWjWwRTmoHaQ/E8vrWtLNyEJ+b0 # 89VW1Ikra3t4GTB5Wby3CL1K2zYnAxBIvafsKMFyj9OuXHcTPKMDoFSMeamG9MKO # Mb6uoG1PjdnDgsLP6EOMRSzrLL7jED1mbB9RSd9fhty+HQr6vZgsBn6oUy+YTpNV # LskwdtUM82WYAkPztlOt3AiL0qyV7/U3j/uq3vHMjPM0w0340M57Nei0g4BCcMt0 # dbqoc91VgCb3/36sHQANontn1HOF2oLk8190QRS43isHVra8H8sf5+GlqIYsYiCK # X04HZiOzZW826nVI6d++8lyTeWmpj90Ua9uPbJhVjwE3oh6tO510ySqmSMSLEN07 # p3Ibe3E6BAb2w93rWzb26+dpSthbKF4kApofqBsWPX4MEtHKSOftPmVTCQ47tghr # VuHia9jY+Hsj01m4KW4WtkmVm3L6hMZECMa4sjMxAXz+bX/AJhWTe6TZAgMBAAGj # ggHLMIIBxzAdBgNVHQ4EFgQU7/LqUlWWYhXJdXwgYKx4b8Gv0rYwHwYDVR0jBBgw # FoAUa2koOjUvSGNAz3vYr0npPtk92yEwbAYDVR0fBGUwYzBhoF+gXYZbaHR0cDov # L3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jcmwvTWljcm9zb2Z0JTIwUHVibGlj # JTIwUlNBJTIwVGltZXN0YW1waW5nJTIwQ0ElMjAyMDIwLmNybDB5BggrBgEFBQcB # AQRtMGswaQYIKwYBBQUHMAKGXWh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lv # cHMvY2VydHMvTWljcm9zb2Z0JTIwUHVibGljJTIwUlNBJTIwVGltZXN0YW1waW5n # JTIwQ0ElMjAyMDIwLmNydDAMBgNVHRMBAf8EAjAAMBYGA1UdJQEB/wQMMAoGCCsG # AQUFBwMIMA4GA1UdDwEB/wQEAwIHgDBmBgNVHSAEXzBdMFEGDCsGAQQBgjdMg30B # ATBBMD8GCCsGAQUFBwIBFjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3Bz # L0RvY3MvUmVwb3NpdG9yeS5odG0wCAYGZ4EMAQQCMA0GCSqGSIb3DQEBDAUAA4IC # AQAAH+zd+XKh4OxXYMWFmtgilXAQGctOjCUB1w/uBiC/OXcH3Ia4/XbdUhKzFbai # TbIE6vYZKd1p4u7nKOLkawymAMVyuO7LSl6rLKttZIyLhWjTK0zXOz0u4xLq9+bR # tBEKJvA6sD5nJwH1IO6z1YizyuIRoalMCnbrUixfWxQn4TAmN7t9uk+X2FUThEa3 # ewzRwhtG+xwaAbLMkxRmR24JnfXd1VxKo90+m7Wzuov96Uugx5wZdewiIIm1ZWTj # 4lCJHup679LcOa7tAxJMipVaSltQH9fm9TOKczlfxtWuBcLU4duZfqwgsILsH7PM # kcX1zwQzQD0yAtPhnYz9KNG125bX+iilOe1S8RHqv2bbBpMpao4kcUvQI6dMgKRv # Fmm1eLbhSNOQplDMTGD1tNVdNGkI96jUu+troUjWMMi46TQfBAHxtDTpRhIu/87v # AVQ8Z6RHhFxesz4Ed5JThaIQRAy6GcO/Jk+QzDzoZ0arRIkIsGJ7rZgOVAjx9ctf # w8lH9RfjcwB3wdGBYNMNVJqQpUai2Taddf5pXzTZEHIqLEF53SrBjIeInoQrP7U5 # VlXiMQsxewLdINrAE2l2TR3KBikb+RQRygbTp8jj2yiC0NCUwG+K+ndglN5RMbXj # FW6aKa59Xq+b8XzK/DK+AJtgOpHgJv8Qrk62A+twOVLOpjGCA9QwggPQAgEBMHgw # YTELMAkGA1UEBhMCVVMxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEy # MDAGA1UEAxMpTWljcm9zb2Z0IFB1YmxpYyBSU0EgVGltZXN0YW1waW5nIENBIDIw # MjACEzMAAABbSrWNQTJt3HQAAAAAAFswDQYJYIZIAWUDBAIBBQCgggEtMBoGCSqG # SIb3DQEJAzENBgsqhkiG9w0BCRABBDAvBgkqhkiG9w0BCQQxIgQglpyQCebLpX5T # +m00K2MZR1yptM1lITpCk1rcWpP8smcwgd0GCyqGSIb3DQEJEAIvMYHNMIHKMIHH # MIGgBCAvMQNVXZ0b0xxlGw8X/3IEybObuT6a5W1d61CW+cGD7zB8MGWkYzBhMQsw # CQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTIwMAYD # VQQDEylNaWNyb3NvZnQgUHVibGljIFJTQSBUaW1lc3RhbXBpbmcgQ0EgMjAyMAIT # MwAAAFtKtY1BMm3cdAAAAAAAWzAiBCAJRig9d4xSDNFxiRY2uWaxjXxL44TPTaYQ # OngVb4vSUDANBgkqhkiG9w0BAQsFAASCAgBh4NYHQCFQA+jXqVMc51yKYKvqKfJO # qohc5Zki01PKbkdOeKqV+p9zFTtHSFT2LjHVLioKQP7HJIfgFsT7C9R0ZN5xPywL # o5dZ5SNMiaLvEIqnXUPHcWULQ+BbOKLKrh0ai/3nzWENgGNOSq0PKmuD5t1R7tec # hyIqaJ4NB0DwJD3UO9VDM1sh/sJl10WTDU1hWA9rn15RU+LM0SFyZIj8+wRxoKhd # 6W9TX6obmTf1QTWc9nJpk1+DCeO4MhErivRRVupDrRejFmNsbkEkag53BwuCdF8r # Ennb+MMEn6wRw+C1kmOcu6z40ODiLTDgpVfebnsDFMRekHM54M5NuR7To3ZbITHZ # LohmAuoDM/kznXiq27TMuw9ryMQgJo9+Rh10pYYI0oXFA83SOTFBMOsb7tVxgPrw # BZ8bqR7DK0Ji9qaIdXZIx5cbY6ftAN+Bx2KVf5GNEWCEsoGmiKrsDGCrRJma4RV3 # MZnc5Bq88Z04YjQHvyCsnGpyKYXdCa3F20WfCM8eTTfTfeDlbKvT42GlTj0VfPVL # KBrSFlG6uo4vCZMF9SAwxwBe/ZgPQQqoiaouHORNLLdu+Wfdsp5fJfd5oQC7Y9eL # i4X7xmUcZxthGgWLUa3HNcgE+5ZoLScs0YZyM39W3k3RzeqjyYg9ESsnTG7L5Ffx # lkJ76Jo9nWwNvA== # SIG # End signature block |