# encoding: ascii
# api: powershell
# title: Environment
# description: Set environment variables stickily.
# version: 0.1
# type: function
# author: Joel Bennett
# license: CC0
# function: Get-SpecialFolder
# x-poshcode-id: 6061
# x-archived: 2016-08-26T03:55:47
# x-published: 2016-10-21T22:38:00
#
# Added SpecialFolder handlers
#
# if you're running "elevated" we want to know that:
$global:PSProcessElevated = ([System.Environment]::OSVersion.Version.Major -gt 5) -and ( # Vista and ...
new-object Security.Principal.WindowsPrincipal (
[Security.Principal.WindowsIdentity]::GetCurrent()) # current user is admin
).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
$OFS = ';'
function LoadSpecialFolders {
$Script:SpecialFolders = @{}
foreach($name in [System.Environment+SpecialFolder].GetFields("Public,Static") | Sort-Object Name) {
$Script:SpecialFolders.($name.Name) = [int][System.Environment+SpecialFolder]$name.Name
if($Name.Name.StartsWith("My")) {
$Script:SpecialFolders.($name.Name.Substring(2)) = [int][System.Environment+SpecialFolder]$name.Name
}
}
$Script:SpecialFolders.CommonModules = Join-Path $Env:ProgramFiles "WindowsPowerShell\Modules"
$Script:SpecialFolders.CommonProfile = (Split-Path $Profile.AllUsersAllHosts)
$Script:SpecialFolders.Modules = Join-Path (Split-Path $Profile.CurrentUserAllHosts) "Modules"
$Script:SpecialFolders.Profile = (Split-Path $Profile.CurrentUserAllHosts)
$Script:SpecialFolders.PSHome = $PSHome
$Script:SpecialFolders.SystemModules = Join-Path (Split-Path $Profile.AllUsersAllHosts) "Modules"
}
$Script:SpecialFolders = [Ordered]@{}
function Get-SpecialFolder {
#.Synopsis
# Gets the current value for a well known special folder
[CmdletBinding()]
param(
# The name of the Path you want to fetch (supports wildcards).
# From the list: AdminTools, ApplicationData, CDBurning, CommonAdminTools, CommonApplicationData, CommonDesktopDirectory, CommonDocuments, CommonMusic, CommonOemLinks, CommonPictures, CommonProgramFiles, CommonProgramFilesX86, CommonPrograms, CommonStartMenu, CommonStartup, CommonTemplates, CommonVideos, Cookies, Desktop, DesktopDirectory, Favorites, Fonts, History, InternetCache, LocalApplicationData, LocalizedResources, MyComputer, MyDocuments, MyMusic, MyPictures, MyVideos, NetworkShortcuts, Personal, PrinterShortcuts, ProgramFiles, ProgramFilesX86, Programs, PSHome, Recent, Resources, SendTo, StartMenu, Startup, System, SystemX86, Templates, UserProfile, Windows
[ValidateScript({
$Name = $_
if(!$Script:SpecialFolders.Count -gt 0) { LoadSpecialFolders }
if($Script:SpecialFolders.Keys -like $Name){
return $true
} else {
throw "Cannot convert Path, with value: `"$Name`", to type `"System.Environment+SpecialFolder`": Error: `"The identifier name $Name is not one of $($Script:SpecialFolders.Keys -join ', ')"
}
})]
[String]$Path = "*",
# If not set, returns a hashtable of folder names to paths
[Switch]$Value
)
$Names = $Script:SpecialFolders.Keys -like $Path
if(!$Value) {
$return = @{}
}
foreach($name in $Names) {
$result = $(
$id = $Script:SpecialFolders.$name
if($Id -is [string]) {
$Id
} else {
($Script:SpecialFolders.$name = [Environment]::GetFolderPath([int]$Id))
}
)
if($result) {
if($Value) {
Write-Output $result
} else {
$return.$name = $result
}
}
}
if(!$Value) {
Write-Output $return
}
}
function Set-EnvironmentVariable {
#.Synopsis
# Set an environment variable at the highest scope possible
[CmdletBinding()]
param(
[Parameter(Position=0)]
[String]$Name,
[Parameter(Position=1)]
[String]$Value,
[System.EnvironmentVariableTarget]
$Scope="Machine",
[Switch]$FailFast
)
Set-Content "ENV:$Name" $Value
$Success = $False
do {
try {
[System.Environment]::SetEnvironmentVariable($Name, $Value, $Scope)
Write-Verbose "Set $Scope environment variable $Name = $Value"
$Success = $True
}
catch [System.Security.SecurityException]
{
if($FailFast) {
$PSCmdlet.ThrowTerminatingError( (New-Object System.Management.Automation.ErrorRecord (
New-Object AccessViolationException "Can't set environment variable in $Scope scope"
), "FailFast:$Scope", "PermissionDenied", $Scope) )
} else {
Write-Warning "Cannot set environment variables in the $Scope scope"
}
$Scope = [int]$Scope - 1
}
} while(!$Success -and $Scope -gt "Process")
}
function Add-Path {
#.Synopsis
# Add a folder to a path environment variable
#.Description
# Gets the existing content of the path variable, splits it with the PathSeparator,
# adds the specified paths, and then joins them and re-sets the EnvironmentVariable
[CmdletBinding()]
param(
[Parameter(Position=0, Mandatory=$True)]
[String]$Name,
[Parameter(Position=1)]
[String[]]$Append = @(),
[String[]]$Prepend = @(),
[System.EnvironmentVariableTarget]
$Scope="User",
[Char]
$Separator = [System.IO.Path]::PathSeparator
)
# Make the new thing as an array so we don't get duplicates
$Path = @($Prepend -split "$Separator" | %{ $_.TrimEnd("\/") } | ?{ $_ })
$Path += $OldPath = @([Environment]::GetEnvironmentVariable($Name, $Scope) -split "$Separator" | %{ $_.TrimEnd("\/") }| ?{ $_ })
$Path += @($Append -split "$Separator" | %{ $_.TrimEnd("\/") }| ?{ $_ })
# Dedup path
# If the path actually exists, use the actual case of the folder
$Path = $(foreach($Folder in $Path) {
if(Test-Path $Folder) {
Get-Item ($Folder -replace '(?<!:)(\\|/)', '*$1') | Where FullName -ieq $Folder | % FullName
} else { $Folder }
} ) | Select -Unique
# Turn them back into strings
$Path = $Path -join "$Separator"
$OldPath = $OldPath -join "$Separator"
# Path environment variables are kind-of a pain:
# The current value in the process scope is a combination of machine and user, with changes
# We need to fix the CURRENT path instead of just setting it
$OldEnvPath = @($(Get-Content "ENV:$Name") -split "$Separator" | %{ $_.TrimEnd("\/") }) -join "$Separator"
if("$OldPath".Trim().Length -gt 0) {
Write-Verbose "Old $Name Path: $OldEnvPath"
$OldEnvPath = $OldEnvPath -Replace ([regex]::escape($OldPath)), $Path
Write-Verbose "New $Name Path: $OldEnvPath"
} else {
if($Append) {
$OldEnvPath = $OldEnvPath + "$Separator" + $Path
} else {
$OldEnvPath = $Path + "$Separator" + $OldEnvPath
}
}
Set-EnvironmentVariable $Name $($Path -join "$Separator") -Scope $Scope -FailFast
if($?) {
# Set the path back to the normalized value
Set-Content "ENV:$Name" $OldEnvPath
}
}
function Select-UniquePath {
[CmdletBinding()]
param(
# If non-full, split path by the delimiter. Defaults to ';' so you can use this on $Env:Path
[AllowNull()]
[string]$Delimiter=';',
# Paths to folders
[Parameter(Position=1,Mandatory=$true,ValueFromRemainingArguments=$true)]
[AllowEmptyCollection()]
[AllowEmptyString()]
[string[]]$Path
)
begin {
$Output = [string[]]@()
}
process {
$Output += $(foreach($folderPath in $Path) {
if($Delimiter) {
$folderPath = $folderPath -split $Delimiter
}
foreach($folder in @($folderPath)) {
$folder = $folder.TrimEnd('\/')
if($folderPath = $folder -replace '(?<!:)(\\|/)', '*$1') {
Get-Item $folderPath -ErrorAction Ignore | Where FullName -ieq $folder
}
}
})
}
end {
if($Delimiter) {
($Output | Select -Expand FullName -Unique) -join $Delimiter
} else {
$Output | Select -Expand FullName -Unique
}
}
}
function Trace-Message {
[CmdletBinding()]
param(
[Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
[string]$Message,
[switch]$AsWarning,
[switch]$ResetTimer,
[switch]$KillTimer,
[Diagnostics.Stopwatch]$Stopwatch
)
begin {
if($Stopwatch) {
$Script:TraceTimer = $Stopwatch
$Script:TraceTimer.Start()
}
if(-not $Script:TraceTimer) {
$Script:TraceTimer = New-Object System.Diagnostics.Stopwatch
$Script:TraceTimer.Start()
}
if($ResetTimer)
{
$Script:TraceTimer.Restart()
}
}
process {
$Message = "$Message - at {0} Line {1} | {2}" -f (Split-Path $MyInvocation.ScriptName -Leaf), $MyInvocation.ScriptLineNumber, $TraceTimer.Elapsed
if($AsWarning) {
Write-Warning $Message
} else {
Write-Verbose $Message
}
}
end {
if($KillTimer) {
$Script:TraceTimer.Stop()
$Script:TraceTimer = $null
}
}
}
function Set-AliasToFirst {
param(
[string[]]$Alias,
[string[]]$Path,
[string]$Description = "the app in $($Path[0])...",
[switch]$Force,
[switch]$Passthru
)
if($App = Resolve-Path $Path -EA Ignore | Sort LastWriteTime -Desc | Select-Object -First 1 -Expand Path) {
foreach($a in $Alias) {
Set-Alias $a $App -Scope Global -Option Constant, ReadOnly, AllScope -Description $Description -Force:$Force
}
if($Passthru) {
Split-Path $App
}
} else {
Write-Warning "Could not find $Description"
}
}
# SIG # Begin signature block
# MIIXxAYJKoZIhvcNAQcCoIIXtTCCF7ECAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB
# gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR
# AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUTYcHd2CFZxVm1V9P02d8vthN
# bSSgghL3MIID7jCCA1egAwIBAgIQfpPr+3zGTlnqS5p31Ab8OzANBgkqhkiG9w0B
# AQUFADCBizELMAkGA1UEBhMCWkExFTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTEUMBIG
# A1UEBxMLRHVyYmFudmlsbGUxDzANBgNVBAoTBlRoYXd0ZTEdMBsGA1UECxMUVGhh
# d3RlIENlcnRpZmljYXRpb24xHzAdBgNVBAMTFlRoYXd0ZSBUaW1lc3RhbXBpbmcg
# Q0EwHhcNMTIxMjIxMDAwMDAwWhcNMjAxMjMwMjM1OTU5WjBeMQswCQYDVQQGEwJV
# UzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xMDAuBgNVBAMTJ1N5bWFu
# dGVjIFRpbWUgU3RhbXBpbmcgU2VydmljZXMgQ0EgLSBHMjCCASIwDQYJKoZIhvcN
# AQEBBQADggEPADCCAQoCggEBALGss0lUS5ccEgrYJXmRIlcqb9y4JsRDc2vCvy5Q
# WvsUwnaOQwElQ7Sh4kX06Ld7w3TMIte0lAAC903tv7S3RCRrzV9FO9FEzkMScxeC
# i2m0K8uZHqxyGyZNcR+xMd37UWECU6aq9UksBXhFpS+JzueZ5/6M4lc/PcaS3Er4
# ezPkeQr78HWIQZz/xQNRmarXbJ+TaYdlKYOFwmAUxMjJOxTawIHwHw103pIiq8r3
# +3R8J+b3Sht/p8OeLa6K6qbmqicWfWH3mHERvOJQoUvlXfrlDqcsn6plINPYlujI
# fKVOSET/GeJEB5IL12iEgF1qeGRFzWBGflTBE3zFefHJwXECAwEAAaOB+jCB9zAd
# BgNVHQ4EFgQUX5r1blzMzHSa1N197z/b7EyALt0wMgYIKwYBBQUHAQEEJjAkMCIG
# CCsGAQUFBzABhhZodHRwOi8vb2NzcC50aGF3dGUuY29tMBIGA1UdEwEB/wQIMAYB
# Af8CAQAwPwYDVR0fBDgwNjA0oDKgMIYuaHR0cDovL2NybC50aGF3dGUuY29tL1Ro
# YXd0ZVRpbWVzdGFtcGluZ0NBLmNybDATBgNVHSUEDDAKBggrBgEFBQcDCDAOBgNV
# HQ8BAf8EBAMCAQYwKAYDVR0RBCEwH6QdMBsxGTAXBgNVBAMTEFRpbWVTdGFtcC0y
# MDQ4LTEwDQYJKoZIhvcNAQEFBQADgYEAAwmbj3nvf1kwqu9otfrjCR27T4IGXTdf
# plKfFo3qHJIJRG71betYfDDo+WmNI3MLEm9Hqa45EfgqsZuwGsOO61mWAK3ODE2y
# 0DGmCFwqevzieh1XTKhlGOl5QGIllm7HxzdqgyEIjkHq3dlXPx13SYcqFgZepjhq
# IhKjURmDfrYwggSjMIIDi6ADAgECAhAOz/Q4yP6/NW4E2GqYGxpQMA0GCSqGSIb3
# DQEBBQUAMF4xCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3Jh
# dGlvbjEwMC4GA1UEAxMnU3ltYW50ZWMgVGltZSBTdGFtcGluZyBTZXJ2aWNlcyBD
# QSAtIEcyMB4XDTEyMTAxODAwMDAwMFoXDTIwMTIyOTIzNTk1OVowYjELMAkGA1UE
# BhMCVVMxHTAbBgNVBAoTFFN5bWFudGVjIENvcnBvcmF0aW9uMTQwMgYDVQQDEytT
# eW1hbnRlYyBUaW1lIFN0YW1waW5nIFNlcnZpY2VzIFNpZ25lciAtIEc0MIIBIjAN
# BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAomMLOUS4uyOnREm7Dv+h8GEKU5Ow
# mNutLA9KxW7/hjxTVQ8VzgQ/K/2plpbZvmF5C1vJTIZ25eBDSyKV7sIrQ8Gf2Gi0
# jkBP7oU4uRHFI/JkWPAVMm9OV6GuiKQC1yoezUvh3WPVF4kyW7BemVqonShQDhfu
# ltthO0VRHc8SVguSR/yrrvZmPUescHLnkudfzRC5xINklBm9JYDh6NIipdC6Anqh
# d5NbZcPuF3S8QYYq3AhMjJKMkS2ed0QfaNaodHfbDlsyi1aLM73ZY8hJnTrFxeoz
# C9Lxoxv0i77Zs1eLO94Ep3oisiSuLsdwxb5OgyYI+wu9qU+ZCOEQKHKqzQIDAQAB
# o4IBVzCCAVMwDAYDVR0TAQH/BAIwADAWBgNVHSUBAf8EDDAKBggrBgEFBQcDCDAO
# BgNVHQ8BAf8EBAMCB4AwcwYIKwYBBQUHAQEEZzBlMCoGCCsGAQUFBzABhh5odHRw
# Oi8vdHMtb2NzcC53cy5zeW1hbnRlYy5jb20wNwYIKwYBBQUHMAKGK2h0dHA6Ly90
# cy1haWEud3Muc3ltYW50ZWMuY29tL3Rzcy1jYS1nMi5jZXIwPAYDVR0fBDUwMzAx
# oC+gLYYraHR0cDovL3RzLWNybC53cy5zeW1hbnRlYy5jb20vdHNzLWNhLWcyLmNy
# bDAoBgNVHREEITAfpB0wGzEZMBcGA1UEAxMQVGltZVN0YW1wLTIwNDgtMjAdBgNV
# HQ4EFgQURsZpow5KFB7VTNpSYxc/Xja8DeYwHwYDVR0jBBgwFoAUX5r1blzMzHSa
# 1N197z/b7EyALt0wDQYJKoZIhvcNAQEFBQADggEBAHg7tJEqAEzwj2IwN3ijhCcH
# bxiy3iXcoNSUA6qGTiWfmkADHN3O43nLIWgG2rYytG2/9CwmYzPkSWRtDebDZw73
# BaQ1bHyJFsbpst+y6d0gxnEPzZV03LZc3r03H0N45ni1zSgEIKOq8UvEiCmRDoDR
# EfzdXHZuT14ORUZBbg2w6jiasTraCXEQ/Bx5tIB7rGn0/Zy2DBYr8X9bCT2bW+IW
# yhOBbQAuOA2oKY8s4bL0WqkBrxWcLC9JG9siu8P+eJRRw4axgohd8D20UaF5Mysu
# e7ncIAkTcetqGVvP6KUwVyyJST+5z3/Jvz4iaGNTmr1pdKzFHTx/kuDDvBzYBHUw
# ggUmMIIEDqADAgECAhACXbrxBhFj1/jVxh2rtd9BMA0GCSqGSIb3DQEBCwUAMHIx
# CzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3
# dy5kaWdpY2VydC5jb20xMTAvBgNVBAMTKERpZ2lDZXJ0IFNIQTIgQXNzdXJlZCBJ
# RCBDb2RlIFNpZ25pbmcgQ0EwHhcNMTUwNTA0MDAwMDAwWhcNMTYwNTExMTIwMDAw
# WjBtMQswCQYDVQQGEwJVUzERMA8GA1UECBMITmV3IFlvcmsxFzAVBgNVBAcTDldl
# c3QgSGVucmlldHRhMRgwFgYDVQQKEw9Kb2VsIEguIEJlbm5ldHQxGDAWBgNVBAMT
# D0pvZWwgSC4gQmVubmV0dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
# AJfRKhfiDjMovUELYgagznWf+HFcDENk118Y/K6UkQDwKmVyVOvDyaVefjSmZZcV
# NZqqYpm9d/Iajf2dauyC3pg3oay8KfXAADLHgbmbvYDc5zGuUNsTzMUOKlp9h13c
# qsg898JwpRpI659xCQgJjZ6V83QJh+wnHvjA9ojjA4xkbwhGp4Eit6B/uGthEA11
# IHcFcXeNI3fIkbwWiAw7ZoFtSLm688NFhxwm+JH3Xwj0HxuezsmU0Yc/po31CoST
# nGPVN8wppHYZ0GfPwuNK4TwaI0FEXxwdwB+mEduxa5e4zB8DyUZByFW338XkGfc1
# qcJJ+WTyNKFN7saevhwp02cCAwEAAaOCAbswggG3MB8GA1UdIwQYMBaAFFrEuXsq
# CqOl6nEDwGD5LfZldQ5YMB0GA1UdDgQWBBQV0aryV1RTeVOG+wlr2Z2bOVFAbTAO
# BgNVHQ8BAf8EBAMCB4AwEwYDVR0lBAwwCgYIKwYBBQUHAwMwdwYDVR0fBHAwbjA1
# oDOgMYYvaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL3NoYTItYXNzdXJlZC1jcy1n
# MS5jcmwwNaAzoDGGL2h0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9zaGEyLWFzc3Vy
# ZWQtY3MtZzEuY3JsMEIGA1UdIAQ7MDkwNwYJYIZIAYb9bAMBMCowKAYIKwYBBQUH
# AgEWHGh0dHBzOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwgYQGCCsGAQUFBwEBBHgw
# djAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tME4GCCsGAQUF
# BzAChkJodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRTSEEyQXNz
# dXJlZElEQ29kZVNpZ25pbmdDQS5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0B
# AQsFAAOCAQEAIi5p+6eRu6bMOSwJt9HSBkGbaPZlqKkMd4e6AyKIqCRabyjLISwd
# i32p8AT7r2oOubFy+R1LmbBMaPXORLLO9N88qxmJfwFSd+ZzfALevANdbGNp9+6A
# khe3PiR0+eL8ZM5gPJv26OvpYaRebJTfU++T1sS5dYaPAztMNsDzY3krc92O27AS
# WjTjWeILSryqRHXyj8KQbYyWpnG2gWRibjXi5ofL+BHyJQRET5pZbERvl2l9Bo4Z
# st8CM9EQDrdG2vhELNiA6jwenxNPOa6tPkgf8cH8qpGRBVr9yuTMSHS1p9Rc+ybx
# FSKiZkOw8iCR6ZQIeKkSVdwFf8V+HHPrETCCBTAwggQYoAMCAQICEAQJGBtf1btm
# dVNDtW+VUAgwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCVVMxFTATBgNVBAoT
# DERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEkMCIGA1UE
# AxMbRGlnaUNlcnQgQXNzdXJlZCBJRCBSb290IENBMB4XDTEzMTAyMjEyMDAwMFoX
# DTI4MTAyMjEyMDAwMFowcjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0
# IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTExMC8GA1UEAxMoRGlnaUNl
# cnQgU0hBMiBBc3N1cmVkIElEIENvZGUgU2lnbmluZyBDQTCCASIwDQYJKoZIhvcN
# AQEBBQADggEPADCCAQoCggEBAPjTsxx/DhGvZ3cH0wsxSRnP0PtFmbE620T1f+Wo
# ndsy13Hqdp0FLreP+pJDwKX5idQ3Gde2qvCchqXYJawOeSg6funRZ9PG+yknx9N7
# I5TkkSOWkHeC+aGEI2YSVDNQdLEoJrskacLCUvIUZ4qJRdQtoaPpiCwgla4cSocI
# 3wz14k1gGL6qxLKucDFmM3E+rHCiq85/6XzLkqHlOzEcz+ryCuRXu0q16XTmK/5s
# y350OTYNkO/ktU6kqepqCquE86xnTrXE94zRICUj6whkPlKWwfIPEvTFjg/Bougs
# UfdzvL2FsWKDc0GCB+Q4i2pzINAPZHM8np+mM6n9Gd8lk9ECAwEAAaOCAc0wggHJ
# MBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgGGMBMGA1UdJQQMMAoG
# CCsGAQUFBwMDMHkGCCsGAQUFBwEBBG0wazAkBggrBgEFBQcwAYYYaHR0cDovL29j
# c3AuZGlnaWNlcnQuY29tMEMGCCsGAQUFBzAChjdodHRwOi8vY2FjZXJ0cy5kaWdp
# Y2VydC5jb20vRGlnaUNlcnRBc3N1cmVkSURSb290Q0EuY3J0MIGBBgNVHR8EejB4
# MDqgOKA2hjRodHRwOi8vY3JsNC5kaWdpY2VydC5jb20vRGlnaUNlcnRBc3N1cmVk
# SURSb290Q0EuY3JsMDqgOKA2hjRodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGln
# aUNlcnRBc3N1cmVkSURSb290Q0EuY3JsME8GA1UdIARIMEYwOAYKYIZIAYb9bAAC
# BDAqMCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy5kaWdpY2VydC5jb20vQ1BTMAoG
# CGCGSAGG/WwDMB0GA1UdDgQWBBRaxLl7KgqjpepxA8Bg+S32ZXUOWDAfBgNVHSME
# GDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzANBgkqhkiG9w0BAQsFAAOCAQEAPuwN
# WiSz8yLRFcgsfCUpdqgdXRwtOhrE7zBh134LYP3DPQ/Er4v97yrfIFU3sOH20ZJ1
# D1G0bqWOWuJeJIFOEKTuP3GOYw4TS63XX0R58zYUBor3nEZOXP+QsRsHDpEV+7qv
# tVHCjSSuJMbHJyqhKSgaOnEoAjwukaPAJRHinBRHoXpoaK+bp1wgXNlxsQyPu6j4
# xRJon89Ay0BEpRPw5mQMJQhCMrI2iiQC/i9yfhzXSUWW6Fkd6fp0ZGuy62ZD2rOw
# jNXpDd32ASDOmTFjPQgaGLOBm0/GkxAG/AeB+ova+YJJ92JuoVP6EpQYhS6Skepo
# bEQysmah5xikmmRR7zGCBDcwggQzAgEBMIGGMHIxCzAJBgNVBAYTAlVTMRUwEwYD
# VQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xMTAv
# BgNVBAMTKERpZ2lDZXJ0IFNIQTIgQXNzdXJlZCBJRCBDb2RlIFNpZ25pbmcgQ0EC
# EAJduvEGEWPX+NXGHau130EwCQYFKw4DAhoFAKB4MBgGCisGAQQBgjcCAQwxCjAI
# oAKAAKECgAAwGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIB
# CzEOMAwGCisGAQQBgjcCARUwIwYJKoZIhvcNAQkEMRYEFPCF/zb7DRZq/pPob7CW
# DAIqdMZ3MA0GCSqGSIb3DQEBAQUABIIBABCA7MjbMa7PAcYUfCaJiFQRRVt+SR7a
# JDdxzjXRrlxr7RN+4S7Himq5CQmV/2PgLPSk8Eil++jd3miRj2v1rkR09qBh9DkQ
# GJfH1n/spSohSwDxdV3pzCmwe97wVG9Mec9OfSyFk4c/sjWR++FPe066mK3bL6Gs
# 5N8WuOVK3O0T2Xco20I3vcQSIPKaiJc3Ziyk4cDJ4a9z0csNXWfMEeeyJD4JdfrL
# HKjbTIxQhq8n6q4VCsZo1PQsZBrwDfR0hIaS/0X9uaVFzfKOKKr71DpMdcyKvcLn
# yvhrP5P4dGQQkJs45CeUwLiHOjwFU/Umvan4N6SW4aDH25PsL5ABYbyhggILMIIC
# BwYJKoZIhvcNAQkGMYIB+DCCAfQCAQEwcjBeMQswCQYDVQQGEwJVUzEdMBsGA1UE
# ChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xMDAuBgNVBAMTJ1N5bWFudGVjIFRpbWUg
# U3RhbXBpbmcgU2VydmljZXMgQ0EgLSBHMgIQDs/0OMj+vzVuBNhqmBsaUDAJBgUr
# DgMCGgUAoF0wGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUx
# DxcNMTUxMDIxMjIzNjU0WjAjBgkqhkiG9w0BCQQxFgQU03GLggzJntCf2eO3Hkju
# yxyE/JcwDQYJKoZIhvcNAQEBBQAEggEATihKXFl8uvC50gbu37KAUdkbzHDONeGB
# JJJm0ZiwYx8WTJQ3a9dTdhueY/CY03ODNhNIt28i/l9cG/SqM5Tip9nIYJ9Akmlw
# wJl43v5ZkUo9bGpJFeN9hVDP4Yubxp39qCJVpbcvQnSzS5E+ABwZUSGa+UMINnf3
# +b60CTPWcxO1OXjRLAZgty8lCX45jiIQBPupZ6GzLFJOU/VgyTBaEBQRJRe7zMMz
# iP1ThfCUbx985ZW7Mkp5cT3mmKGOr+n5h9a2NYE2IgRp9hfv4D8petGG++Tgdu7J
# jPnggsSrdUsmK7uzwTHcgJffUTngOWsqPE3mp6KTwL5qqsij672ejw==
# SIG # End signature block