Private/Write-ADFSTkLog.ps1


function Write-ADFSTkLog {
[CmdletBinding(DefaultParametersetName="Default")]
param (        
    [Parameter(Mandatory=$false,
                ParameterSetName="Set",
                ValueFromPipelineByPropertyName=$false)]
    [string]
    #The path to the logfile. This needs to be set once in the script. The path will be stored in a global variable 'LogFilePath'
    $SetLogFilePath,
    [Parameter(Mandatory=$false,
                ParameterSetName="Set",
                ValueFromPipelineByPropertyName=$false)]
    [string]
    #The name of the eventlog. This needs to be set once in the script. The name will be stored in a global variable 'EventLogName'
    $SetEventLogName,
    [Parameter(Mandatory=$false,
                ParameterSetName="Set",
                ValueFromPipelineByPropertyName=$false)]
    [string]
    <#The Source that will be used in the eventlog.
     
    Use New-EventLog -LogName <EventLogName> -Source <NewSource> to add a new source to a eventlog.
     
    This needs to be set once in the script. The name will be stored in a global variable 'EventLogSource'#>

    $SetEventLogSource,
    [Parameter(Mandatory=$false,
                ParameterSetName="Get",
                ValueFromPipelineByPropertyName=$false)]
    [switch]
    #Returns the path to the LogFile.
    $GetLogFilePath,
    [Parameter(Mandatory=$false,
                ParameterSetName="Get",
                ValueFromPipelineByPropertyName=$false)]
    [switch]
    #Returns the name of the EventLog that will be used.
    $GetEventLogName,
    [Parameter(Mandatory=$false,
                ParameterSetName="Get",
                ValueFromPipelineByPropertyName=$false)]
    [switch]
    #Returns the Source of the EventLog that will be used.
    $GetEventLogSource,
    
    [Parameter(Mandatory=$false,
                ParameterSetName="Default",
                ValueFromPipelineByPropertyName=$true,
                Position=0)]
    [ValidateNotNullOrEmpty()]
    [string]
    #The message to be written in the log...
    $Message,
    
    [Parameter(Mandatory=$false,
                ParameterSetName="Default",
                ValueFromPipelineByPropertyName=$true)]
    [int]
    #The EventID if EventLog is used
    $EventID,
    [Parameter(Mandatory=$false,
                ParameterSetName="Default",
                ValueFromPipelineByPropertyName=$true)]
    [string]
    #Used in LogFile and on Screen to clarify the message. In EventLog the Level on the event is set to EntryType. Default is Information
    [ValidateSet("Information", "Error", "Warning")]
    $EntryType="Information",
    [Parameter(Mandatory=$false,
                ParameterSetName="Default",
                ValueFromPipelineByPropertyName=$true)]
    [switch]
    #If used the EntryType will be set as "Error" the message will be thown as an error.
    $MajorFault,
    [Parameter(Mandatory=$false,
                ParameterSetName="Default",
                ValueFromPipelineByPropertyName=$true)]
    [int]
    #Only for EventLog. Task Category on the event is set to Category. If -Verbose is used, Category will be set to 4
    $Category=1,
    [Parameter(Mandatory=$false,
                ParameterSetName="Default",
                ValueFromPipelineByPropertyName=$false)]
    [switch]
    #Used in LogFile and on Screen make the message underlined
    $Underline,
    [Parameter(Mandatory=$false,
                ParameterSetName="Default",
                ValueFromPipelineByPropertyName=$false)]
    [char]
    #The char used to make the underline (see parameter Underline). Default is '-'
    $UnderlineChar='-',
    [Parameter(Mandatory=$false,
                ParameterSetName="Default",
                ValueFromPipelineByPropertyName=$true)]
    [switch]
    #Use this to get output on the screen
    $Screen,
    [Parameter(Mandatory=$false,
                ParameterSetName="Default",
                ValueFromPipelineByPropertyName=$true)]
    [switch]
    #Use this to log to file
    $File,
    [Parameter(Mandatory=$false,
                ParameterSetName="Default",
                ValueFromPipelineByPropertyName=$true)]
    [switch]
    #Use this to log to EventLog
    $EventLog,
    [Parameter(Mandatory=$false,
                ParameterSetName="Default",
                ValueFromPipelineByPropertyName=$true)]
    [switch]
    #Doesn't write Date and Time in the beginning of the row
    $SkipDateTime,
    [Parameter(Mandatory=$false,
                ParameterSetName="Default",
                ValueFromPipelineByPropertyName=$true)]
    [ConsoleColor]
    #Sets the color the screen-text should be written in
    $ForegroundColor = [ConsoleColor]::Gray
)
       
Begin {
    
    if ($PsCmdlet.ParameterSetName -eq "Set")
    {
        if ($SetLogFilePath -ne [string]::Empty) 
        {
            $FilePath = $SetLogFilePath.SubString(0,$SetLogFilePath.LastIndexOf('\'))
            if (! (Test-Path ($FilePath)))
            {
                Write-Warning (Get-ADFSTkLanguageText logPathNotFound -f $FilePath)
            }
            else
            {
                Write-Verbose (Get-ADFSTkLanguageText logSettingXPathTo -f 'LogFilePath', $SetLogFilePath)
                $global:LogFilePath = $SetLogFilePath                    
            }
        }
        
        if ($SetEventLogName -ne [string]::Empty)
        {
            try
            {
                $TestEventLog = Get-EventLog $SetEventLogName -Newest 1
                
                Write-Verbose (Get-ADFSTkLanguageText logSettingXPathTo -f 'EventLogName', $SetEventLogName)
                $global:EventLogName = $SetEventLogName 
            }
            catch
            {
                Write-Warning (Get-ADFSTkLanguageText logEventLogNameNotExist)
            }
        }
        
        if ($SetEventLogSource -ne [string]::Empty)
        { 
            Write-Verbose (Get-ADFSTkLanguageText logSettingXPathTo -f 'SetEventLogSource', $SetLogFilePath)
            $global:EventLogSource = $SetEventLogSource
        }
    }
    elseif ($PsCmdlet.ParameterSetName -eq "Get")
    {
        if ($GetLogFilePath) { $LogFilePath }
        if ($GetEventLogName) { $EventLogName }
        if ($GetEventLogSource) { $EventLogSource }
    }
}
Process {
    ### Write main script below ###
    if ($PsCmdlet.ParameterSetName -eq "Default")
    {
        if ($MajorFault) { $EntryType = "Error" }
        if ($verbosePreference -eq "Continue") { $Category = 4 }
        
        $CurrentTime = (Get-Date).ToString()
        
        if (!$Screen.IsPresent -and !$File.IsPresent -and !$EventLog.IsPresent)
        {
            $Screen = $true

            if ($EventLogName -ne $null -and $EventLogSource -ne $null)
            {
                $EventLog = $true
            }

            if ($LogFilePath -ne $null)
            {
                $File = $true
            }
        }
        
        if ($Screen -and -not $MajorFault -and -not $Silent)
        { 
            #Write-Verbose "Logging to Screen..."
            
            if (!$SkipDateTime) 
            {
                Write-Host "$($CurrentTime): " -ForegroundColor DarkYellow -NoNewline
            }
            
            if ($EntryType -eq "Error")
            { 
                $ColorParams = @{
                    ForegroundColor = [System.ConsoleColor]::Red
                    BackgroundColor = [System.ConsoleColor]::Black
                }
                Write-Host "ERROR: $Message" @ColorParams
                if ($Underline) { Write-Host "$([string]::Empty.PadLeft($ScreenMessage.Length + 7,$UnderlineChar))" @ColorParams }
            }
            elseif ($EntryType -eq "Warning")
            {
                $ColorParams = @{
                    ForegroundColor = [System.ConsoleColor]::Yellow
                    BackgroundColor = [System.ConsoleColor]::Black
                }
                Write-Host "WARNING: $Message" @ColorParams
                if ($Underline) { Write-Host "$([string]::Empty.PadLeft($ScreenMessage.Length + 9,$UnderlineChar))" @ColorParams}
            }
            else
            {
                if ($verbosePreference -eq "Continue")
                { 
                    Write-Verbose $Message
                    if ($Underline) { Write-Verbose "$([string]::Empty.PadLeft($ScreenMessage.Length,$UnderlineChar))" }
                }
                else 
                { 
                    Write-Host $Message -ForegroundColor $ForegroundColor
                    if ($Underline) { Write-Host "$([string]::Empty.PadLeft($ScreenMessage.Length,$UnderlineChar))" }
                    
                }
            }
        }
        
        if ($File) 
        {
            if ($LogFilePath -eq [string]::Empty) { Write-Warning (Get-ADFSTkLanguageText logLogFilePathNotSet) }
            else
            {
                $FileMessage = ""
                if (!$SkipDateTime) 
                {
                    $FileMessage = "$CurrentTime - "
                }
                 $FileMessage += "$($EntryType): $Message"

                #Write-Verbose "Logging to File `'$LoggFilePath`'..."
                Add-Content -Path $LogFilePath -Value $FileMessage
                if ($Underline) { Add-Content -Path $LogFilePath -Value "$([string]::Empty.PadLeft($FileMessage.Length,$UnderlineChar))" }
            }
        }
        
        if ($EventLog)
        { 
            if ($EventLogName -eq [string]::Empty) { Write-Warning (Get-ADFSTkLanguageText logEventLogNameNotSet) }
            elseif ($EventLogSource -eq [string]::Empty) { Write-Warning (Get-ADFSTkLanguageText logEventSourceNotSet) }
            else
            {
                #Write-Verbose "Logging to EventLog `'$EventLogName`' as Source `'$EventLogSource`'..."
            
                Write-EventLog -LogName $EventLogName -Source $EventLogSource -EventId $EventID -Message $Message -EntryType $EntryType -Category $Category    
            }
        }

        if($EntryType -eq "Warning")
        {
            $global:Warnings++
            $global:LastWarning = $Message
        }
        elseif($EntryType -eq "Error")
        {
            $global:Errors++
            $global:LastError = $Message
        }
        
        if ($MajorFault) { throw $Message }   
    }
}
<#
.SYNOPSIS
Use this cmdlet to add logging to your script. Can log to Screen/File and EventLog
 
.DESCRIPTION
Start by setting FilePath and/or EventLogName/EventLogSource. The values are stored in global variables and don't need to be set again.
 
Call Write-ADFSTkLog with one or more parameters depending on how much logging needed.
 
If a Warning is logged the following global variables will be changed:
$Warnings will increase with 1
$LastWarning will be set to $Message
 
If an Error is logged the following global variables will be changed:
$Errors will increase with 1
$LastError will be set to $Message
 
If -MajorFault is provided, EntryType will automatically be set as Error and after logging has been done, the Message will be thrown.
 
If a variable namned $Silent is used and equals $true in the script calling Write-ADFSTkLog, no logging to screen will be done
 
.EXAMPLE
C:\PS> Write-ADFSTkLog -Message "Hello World!"
2012-02-02 16:40:16: Hello World!
 
-Message parameter are not needed as long as the message is written first
 
C:\PS> Write-ADFSTkLog "Hello World!" -EntryType Warning
WARNING: 2012-02-02 16:41:23: Hello World!
 
C:\PS> Write-ADFSTkLog -SetLogFilePath C:\Logs\myLogfile.txt
C:\PS> Write-ADFSTkLog "Hello textfile!" -File -Screen -Underline
2012-02-02 16:46:31: Hello textfile!
------------------------------------
.EXAMPLE
If none of the parameters (-Screen, -File or -EventLog) is provided, all defined ways will be used.
Default will only be the screen, a -SetLogFilePath has been set, the logging will be to screen and file, etc
 
C:\PS> Write-ADFSTkLog -SetLogFilePath C:\Logs\myLogfile.txt
C:\PS> Write-ADFSTkLog "Look, I don't use any parameters! :)"
2012-02-02 16:59:46: Look, I don't use any parameters! :)
 
C:\PS> Get-Content $LogFilePath
2012-02-02 16:46:31 - Information: Hello textfile!
--------------------------------------------------
2012-02-02 16:59:46 - Information: Look, I don't use any parameters! :)
 
C:\PS> Write-ADFSTkLog "Something isn't quite right!" -EntryType Warning
WARNING: 2012-02-02 17:00:45: Something isn't quite right!
 
C:\PS> Get-Content $LogFilePath
2012-02-02 16:46:31 - Information: Hello textfile!
--------------------------------------------------
2012-02-02 16:59:46 - Information: Look, I don't use any parameters! :)
2012-02-02 17:00:45 - Warning: Something isn't quite right!
C:PS> $Warnings
2
C:PS> $Errors
0
C:PS> $LastWarning
Something isn't quite right!
#>

}

function Write-ADFSTkVerboseLog {
[CmdletBinding(SupportsShouldProcess=$true)] 
param (
    [parameter(Position=0)]
    [ValidateNotNullOrEmpty()]
    [string]
    #The message to be written in the log...
    $Message,
    [string]
    #Used in LogFile and on Screen to clarify the message. In EventLog the Level on the event is set to EntryType. Default is Information
    [ValidateSet("Information", "Error", "Warning")]
    $EntryType="Information",
    [switch]
    #Use this to log to EventLog
    $EventLog,
    [switch]
    #Use this to log to file
    $File,
    [int]
    #The EventID if EventLog is used
    $EventID
)
    if ($verbosePreference -eq "Continue")
    { 
        if (!$File.IsPresent -and !$EventLog.IsPresent)
        {
            if ($EventLogName -ne $null -and $EventLogSource -ne $null)
            {
                $EventLog = $true
            }

            if ($LogFilePath -ne $null)
            {
                $File = $true
            }
        }

        if ($EventLog)
        {
            Write-ADFSTkLog -Message $Message -EventLog -EventID $EventID -EntryType $EntryType
        }
        
        if($File)
        {
            Write-ADFSTkLog -Message $Message -File -EventID $EventID -EntryType $EntryType
        }
        
        Write-ADFSTkLog -Message $Message -EntryType $EntryType -Screen
        
    }
<#
.SYNOPSIS
Use this cmdlet to add Verbose-logging to your script. Logging will always be to screen, but can also be done to File and/or EventLog
 
.DESCRIPTION
Start by setting FilePath and/or EventLogName/EventLogSource with Write-ADFSTkLog.
 
Category will always be set to 4
 
.EXAMPLE
Scriptfile below (Test-Script.ps1)
---
[CmdletBinding(SupportsShouldProcess=$true)]
param()
 
Write-VerboseLiULog "This is a verbose message"
---
 
C:\PS> .\Test-Script.ps1
 
C:\PS> .\Test-Script.ps1 -Verbose
VERBOSE: This is a verbose message
.EXAMPLE
Scriptfile below (Test-Script.ps1)
---
[CmdletBinding(SupportsShouldProcess=$true)]
param()
 
Write-ADFSTkLog -SetLogFilePath .\myLogfile.txt
Write-VerboseLiULog "This is a verbose message"
---
 
C:\PS> .\Test-Script.ps1 -File -Verbose
VERBOSE: Setting LogFilePath to '.\myLogfile.txt'...
VERBOSE: 2012-01-04 12:56:50: This is a verbose message
 
C:\PS> Get-Content .\myLogfile.txt
2012-01-04 12:58:13 - Information: This is a verbose message
#>

}


# SIG # Begin signature block
# MIIjnwYJKoZIhvcNAQcCoIIjkDCCI4wCAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBLk/U41GLdLqvT
# oDPoGBKd/tUesKZs1gX90LF4Y/yoaKCCHZgwggT+MIID5qADAgECAhANQkrgvjqI
# /2BAIc4UAPDdMA0GCSqGSIb3DQEBCwUAMHIxCzAJBgNVBAYTAlVTMRUwEwYDVQQK
# EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xMTAvBgNV
# BAMTKERpZ2lDZXJ0IFNIQTIgQXNzdXJlZCBJRCBUaW1lc3RhbXBpbmcgQ0EwHhcN
# MjEwMTAxMDAwMDAwWhcNMzEwMTA2MDAwMDAwWjBIMQswCQYDVQQGEwJVUzEXMBUG
# A1UEChMORGlnaUNlcnQsIEluYy4xIDAeBgNVBAMTF0RpZ2lDZXJ0IFRpbWVzdGFt
# cCAyMDIxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwuZhhGfFivUN
# CKRFymNrUdc6EUK9CnV1TZS0DFC1JhD+HchvkWsMlucaXEjvROW/m2HNFZFiWrj/
# ZwucY/02aoH6KfjdK3CF3gIY83htvH35x20JPb5qdofpir34hF0edsnkxnZ2OlPR
# 0dNaNo/Go+EvGzq3YdZz7E5tM4p8XUUtS7FQ5kE6N1aG3JMjjfdQJehk5t3Tjy9X
# tYcg6w6OLNUj2vRNeEbjA4MxKUpcDDGKSoyIxfcwWvkUrxVfbENJCf0mI1P2jWPo
# GqtbsR0wwptpgrTb/FZUvB+hh6u+elsKIC9LCcmVp42y+tZji06lchzun3oBc/gZ
# 1v4NSYS9AQIDAQABo4IBuDCCAbQwDgYDVR0PAQH/BAQDAgeAMAwGA1UdEwEB/wQC
# MAAwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwgwQQYDVR0gBDowODA2BglghkgBhv1s
# BwEwKTAnBggrBgEFBQcCARYbaHR0cDovL3d3dy5kaWdpY2VydC5jb20vQ1BTMB8G
# A1UdIwQYMBaAFPS24SAd/imu0uRhpbKiJbLIFzVuMB0GA1UdDgQWBBQ2RIaOpLqw
# Zr68KC0dRDbd42p6vDBxBgNVHR8EajBoMDKgMKAuhixodHRwOi8vY3JsMy5kaWdp
# Y2VydC5jb20vc2hhMi1hc3N1cmVkLXRzLmNybDAyoDCgLoYsaHR0cDovL2NybDQu
# ZGlnaWNlcnQuY29tL3NoYTItYXNzdXJlZC10cy5jcmwwgYUGCCsGAQUFBwEBBHkw
# dzAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tME8GCCsGAQUF
# BzAChkNodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRTSEEyQXNz
# dXJlZElEVGltZXN0YW1waW5nQ0EuY3J0MA0GCSqGSIb3DQEBCwUAA4IBAQBIHNy1
# 6ZojvOca5yAOjmdG/UJyUXQKI0ejq5LSJcRwWb4UoOUngaVNFBUZB3nw0QTDhtk7
# vf5EAmZN7WmkD/a4cM9i6PVRSnh5Nnont/PnUp+Tp+1DnnvntN1BIon7h6JGA078
# 9P63ZHdjXyNSaYOC+hpT7ZDMjaEXcw3082U5cEvznNZ6e9oMvD0y0BvL9WH8dQgA
# dryBDvjA4VzPxBFy5xtkSdgimnUVQvUtMjiB2vRgorq0Uvtc4GEkJU+y38kpqHND
# Udq9Y9YfW5v3LhtPEx33Sg1xfpe39D+E68Hjo0mh+s6nv1bPull2YYlffqe0jmd4
# +TaY4cso2luHpoovMIIFMTCCBBmgAwIBAgIQCqEl1tYyG35B5AXaNpfCFTANBgkq
# hkiG9w0BAQsFADBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5j
# MRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBB
# c3N1cmVkIElEIFJvb3QgQ0EwHhcNMTYwMTA3MTIwMDAwWhcNMzEwMTA3MTIwMDAw
# WjByMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL
# ExB3d3cuZGlnaWNlcnQuY29tMTEwLwYDVQQDEyhEaWdpQ2VydCBTSEEyIEFzc3Vy
# ZWQgSUQgVGltZXN0YW1waW5nIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
# CgKCAQEAvdAy7kvNj3/dqbqCmcU5VChXtiNKxA4HRTNREH3Q+X1NaH7ntqD0jbOI
# 5Je/YyGQmL8TvFfTw+F+CNZqFAA49y4eO+7MpvYyWf5fZT/gm+vjRkcGGlV+Cyd+
# wKL1oODeIj8O/36V+/OjuiI+GKwR5PCZA207hXwJ0+5dyJoLVOOoCXFr4M8iEA91
# z3FyTgqt30A6XLdR4aF5FMZNJCMwXbzsPGBqrC8HzP3w6kfZiFBe/WZuVmEnKYmE
# UeaC50ZQ/ZQqLKfkdT66mA+Ef58xFNat1fJky3seBdCEGXIX8RcG7z3N1k3vBkL9
# olMqT4UdxB08r8/arBD13ays6Vb/kwIDAQABo4IBzjCCAcowHQYDVR0OBBYEFPS2
# 4SAd/imu0uRhpbKiJbLIFzVuMB8GA1UdIwQYMBaAFEXroq/0ksuCMS1Ri6enIZ3z
# bcgPMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgGGMBMGA1UdJQQM
# MAoGCCsGAQUFBwMIMHkGCCsGAQUFBwEBBG0wazAkBggrBgEFBQcwAYYYaHR0cDov
# L29jc3AuZGlnaWNlcnQuY29tMEMGCCsGAQUFBzAChjdodHRwOi8vY2FjZXJ0cy5k
# aWdpY2VydC5jb20vRGlnaUNlcnRBc3N1cmVkSURSb290Q0EuY3J0MIGBBgNVHR8E
# ejB4MDqgOKA2hjRodHRwOi8vY3JsNC5kaWdpY2VydC5jb20vRGlnaUNlcnRBc3N1
# cmVkSURSb290Q0EuY3JsMDqgOKA2hjRodHRwOi8vY3JsMy5kaWdpY2VydC5jb20v
# RGlnaUNlcnRBc3N1cmVkSURSb290Q0EuY3JsMFAGA1UdIARJMEcwOAYKYIZIAYb9
# bAACBDAqMCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy5kaWdpY2VydC5jb20vQ1BT
# MAsGCWCGSAGG/WwHATANBgkqhkiG9w0BAQsFAAOCAQEAcZUS6VGHVmnN793afKpj
# erN4zwY3QITvS4S/ys8DAv3Fp8MOIEIsr3fzKx8MIVoqtwU0HWqumfgnoma/Capg
# 33akOpMP+LLR2HwZYuhegiUexLoceywh4tZbLBQ1QwRostt1AuByx5jWPGTlH0gQ
# GF+JOGFNYkYkh2OMkVIsrymJ5Xgf1gsUpYDXEkdws3XVk4WTfraSZ/tTYYmo9WuW
# wPRYaQ18yAGxuSh1t5ljhSKMYcp5lH5Z/IwP42+1ASa2bKXuh1Eh5Fhgm7oMLStt
# osR+u8QlK0cCCHxJrhO24XxCQijGGFbPQTS2Zl22dHv1VjMiLyI2skuiSpXY9aaO
# UjCCBd8wggTHoAMCAQICEE5A5DdU7eaMAAAAAFHTlH8wDQYJKoZIhvcNAQELBQAw
# gb4xCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQL
# Ex9TZWUgd3d3LmVudHJ1c3QubmV0L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykg
# MjAwOSBFbnRydXN0LCBJbmMuIC0gZm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxMjAw
# BgNVBAMTKUVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcy
# MB4XDTIxMDUwNzE1NDM0NVoXDTMwMTEwNzE2MTM0NVowaTELMAkGA1UEBhMCVVMx
# FjAUBgNVBAoMDUVudHJ1c3QsIEluYy4xQjBABgNVBAMMOUVudHJ1c3QgQ29kZSBT
# aWduaW5nIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBDU0JSMTCCAiIw
# DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKeBj/cURbZiQ/LYrtMlXkhPUb/F
# fZ9QHDXR1n5hKpQZbSdGpKYaXfdUUWqAIsaoZnVNVIPJXmgbq/ZbZLCtrSC9VO9G
# a20C50WudfaOirkyLou4dxxSTXmIX6U6GMlQLJcnLb/aAH1jf+8y7EaHY9uan8Na
# ITZ7+ZvVyqBuciz84fGecE0IVhVvkKv7SLq518GCeIVlLn+1ycDiFLc3EUEG4org
# qPblfrZ4BQHDYO1PB0EuChNJ45Cbf929+qy/ZFHRXJu09VznXP87m6WgGtd9CbLC
# t/9uHLzIfebpK/xysxTpSlUShJxEJXUd9irwT6UgPWgl62GXfA/ltj3zrsPBEbwb
# jszgRzBeQgCGceNYrAbKZR97lKZLV2cMfl6teGdbVeNe68fY7Exuhsvz3Pifh6py
# WBIPfab4+EI5Ozws5DJNSYzg4QDCOKCc+oQ+QdxuVq7GGlv0Z2gFAc0bv66HvJ1T
# 9i7otmvkmd7FT4dYqNJlHsgf1XJu7lkcVzsJcp3XyreQxs17RZKRQgNMfT/K8qq4
# wg6G8xCfRi6kZoZoWmgYcCk4EYBga4pDo3Ns47NrN//mnWcBkobfL0jR+1Bg1Vz+
# IdMBQmP+73C0F8CPqO7TwUtfEur9/S4Oh0Rg46n0whij4/3ODIQiDfOneNqT89s4
# z7kvM8b/BzxevkXTAgMBAAGjggErMIIBJzAOBgNVHQ8BAf8EBAMCAYYwEgYDVR0T
# AQH/BAgwBgEB/wIBATAdBgNVHSUEFjAUBggrBgEFBQcDAwYIKwYBBQUHAwgwOwYD
# VR0gBDQwMjAwBgRVHSAAMCgwJgYIKwYBBQUHAgEWGmh0dHA6Ly93d3cuZW50cnVz
# dC5uZXQvcnBhMDMGCCsGAQUFBwEBBCcwJTAjBggrBgEFBQcwAYYXaHR0cDovL29j
# c3AuZW50cnVzdC5uZXQwMAYDVR0fBCkwJzAloCOgIYYfaHR0cDovL2NybC5lbnRy
# dXN0Lm5ldC9nMmNhLmNybDAdBgNVHQ4EFgQUgrrWPZfOn89x6JI3r/2ztWk1V88w
# HwYDVR0jBBgwFoAUanImetAe733nO2lR1GyNn5ASZqswDQYJKoZIhvcNAQELBQAD
# ggEBAB9eQQS2g3AkUyxVcx1lOsDstHsEmF5ZOBMJpFmUQl5Qv09sbiUgkJNYQA31
# GbRi7iRewgFYFQIdEAlvqNT7kn43OD4vFH2PHUM2ZLNmE18UzKVx91shS8aXvtyV
# /HB9ERzTId3QJDkpxf4KGqXPe3nuOm/e3L/pEd0WgwjTLI1/TagUeS8FYVI462Dz
# FGh9y7KKrcCUXOQmDiyK3UbDzuRWUcVW44W4TZtFcosH8Yr7Sbhf0fKWgV1pUiTx
# CCPS1iMP64vXfovBk2v68WJ7WOlQm5duF4gN4cZDmNeBYbaFnUfssZ6uPyA7Q53Y
# ohzg1HwIwq92BvhiZnq29/rIrzUwggaDMIIEa6ADAgECAhA1r7d7nTQfavyPhEar
# MTUrMA0GCSqGSIb3DQEBDQUAMGkxCzAJBgNVBAYTAlVTMRYwFAYDVQQKDA1FbnRy
# dXN0LCBJbmMuMUIwQAYDVQQDDDlFbnRydXN0IENvZGUgU2lnbmluZyBSb290IENl
# cnRpZmljYXRpb24gQXV0aG9yaXR5IC0gQ1NCUjEwHhcNMjEwNTA3MTkxOTUyWhcN
# NDAxMjI5MjM1OTAwWjBjMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNRW50cnVzdCwg
# SW5jLjE8MDoGA1UEAxMzRW50cnVzdCBFeHRlbmRlZCBWYWxpZGF0aW9uIENvZGUg
# U2lnbmluZyBDQSAtIEVWQ1MyMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKC
# AgEAvr2nOcmlfexdZfH0K6mH0OetGsUaOxjO4aFRjXL6zlgfXLgkQg9G1TGX0EpN
# 45swybqXqJz+RTbPJ4Dne7huwSS336d03IXyoyRYRcyUlDsC68SNfEb1XGaC46TB
# 0x+sbgxTIw7UOvraQvGDVF81MlbytXibVwBIHqlhYScOcwNDttZwkvvUhZowxrPm
# ml5L7x0q2GarFkb/C9gPpolKAlFXQTxBOE6Xx1EybWeOZqFeTZ81Iq/Vard/QF9o
# Ncxp+vEF8OqFpuoyhcvBwcqDaUVJBtwJbLpJZRmM+bc3J4xknjXj5eznB6CdqHK8
# b4U6LKYWTj2czwjmgvVEfSjAvYmtbC/cL3h5EdcccEvdnQhMXi76jb2n3WP2f/BS
# MYRuOtjZXIVEnmMGadCGWHiJm4e7WBykKGzG/mkKnB6sEWBqXslpZS7tQy1p8Xi3
# Oy018qpP4h/jAW+QRqrVqA0EV6C0rONtvZ0bKIAnRsfaqmeV8dGHe8fIJemEDI+J
# NtK+M+GFwDPVoDwZi6848uWTgL/Gw6t7k8Q9nbnuRXbA1GhvMF48tDb510VC4BIG
# gNulIfznBXoojbSOYHv3yLVKR6wUZpegWmlyMVdrU4TNYbpzBxVwO3sB/Kc/jC09
# h4z7CNflLxeDfoKrTwnyKeF+VXdllAUdWdQK3ZN+4xRd4rsCAwEAAaOCASswggEn
# MBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFM6JT4JRqhWihGLKMSNh0mH7
# +P54MB8GA1UdIwQYMBaAFIK61j2Xzp/PceiSN6/9s7VpNVfPMDMGCCsGAQUFBwEB
# BCcwJTAjBggrBgEFBQcwAYYXaHR0cDovL29jc3AuZW50cnVzdC5uZXQwMQYDVR0f
# BCowKDAmoCSgIoYgaHR0cDovL2NybC5lbnRydXN0Lm5ldC9jc2JyMS5jcmwwDgYD
# VR0PAQH/BAQDAgGGMBMGA1UdJQQMMAoGCCsGAQUFBwMDMEQGA1UdIAQ9MDswMAYE
# VR0gADAoMCYGCCsGAQUFBwIBFhpodHRwOi8vd3d3LmVudHJ1c3QubmV0L3JwYTAH
# BgVngQwBAzANBgkqhkiG9w0BAQ0FAAOCAgEAPgBUuCrzj2avYRbEWJNk9EGLZFWN
# GzUzoZuR2KtGyqtfvL5+cOTS1weolgfXhtFXCgjQ0HhN+CrfsgTzmuHXfPDBAHrB
# QKHfioy3y7QdAWHymJqm3biDBcqpLBbcnC0O/qeX5FCpl5XBSyqMUePEAuBrfDVN
# U7xLlBOLUxgWXqYKp7g0wWyx6yzkMX0MLMZ84aRW6C121bITdeqDAK4Ad8ZvqT3u
# YxSBUBb8W08SGQ5bD43qS84GTIlLriDMjkemddZl7i8w6F00jx+CTVxCpvIUTFAg
# nAmidCRcOdiJMoU8r4zlap7mBDqlE/+qHc1HSy4CBbRqj+uFT4HvCtt9nymPpcI/
# UjhSQZU7vD5bVDBCIwlj3lCNiTVF+qu4D4+irXt6EZPxjyiEe2h5R2roZClNH/Qd
# L20eyJSGPNNamXprfKs19ys5S0+5PxaS7ymMjausARrMcUQ5y0A+IBLOCHDjR/7c
# gNcIANELauohtXlmF+lqqlbdzRV4sQPAFK0+Rxh17QpTSzKTzf+AsZDWE+XkQXgi
# 7UGC5Q7fsM6VIUXmiwHTGff0K1Ws2VZzYxDguKBty1SWmKCZIVEGqqYMOitjy3na
# Q7nSEszej1V66Qnz4prTJcF7NpLa4OVSZ83j5lQKpZ3Uc6PTL10GZIUDd39g2MK8
# dMmVkWi3t35hGXUwggbzMIIE26ADAgECAhAWdy8OxRnHb5IdXyBiye3RMA0GCSqG
# SIb3DQEBCwUAMGMxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMu
# MTwwOgYDVQQDEzNFbnRydXN0IEV4dGVuZGVkIFZhbGlkYXRpb24gQ29kZSBTaWdu
# aW5nIENBIC0gRVZDUzIwHhcNMjIwMzI5MjAxODAzWhcNMjMwMzI5MjAxODAzWjCB
# ozELMAkGA1UEBhMCQ0ExEDAOBgNVBAgTB09udGFyaW8xDzANBgNVBAcTBk90dGF3
# YTETMBEGCysGAQQBgjc8AgEDEwJDQTEUMBIGA1UEChMLQ0FOQVJJRSBJTkMxHTAb
# BgNVBA8TFFByaXZhdGUgT3JnYW5pemF0aW9uMREwDwYDVQQFEwgyOTAyMDgtNzEU
# MBIGA1UEAxMLQ0FOQVJJRSBJTkMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK
# AoICAQC7QrVGr/0GFSjOKBtAIfg420mYYBtsT/eqfZigZeS4ZW6sykAZBX71qiU+
# 1SqfMpfU+GY2oQAvGGq/1kBaKTukhT+wwEAH90wJeaMSzAhpl9Q8vSx0xRfXmKfx
# GG8cn6kuq9DZb9kKeKP2qWSFPJyS2y0F5pVhSp8hDvZxAeAKNAjoTDip55kMJm14
# /CkqU2biZ35prXMDMh7/29YWuFWX55zKOxEfVWbbsRKGladcYtKXu1oqSh0XEhhF
# B1BLXBw1YdN2RgjXAIMxrsvNjQ7q8ZWHEMrgvA/50X59x9vxQLS4ivT8RRLic+EW
# 6BMoQ7tqlUwedFSLRsGRxs+7tLwt0FYjQQEYZEbqUpLCcrdco9QEWSI/xaY4sl7F
# S/F6HdISYpyeBlKjcsHVy5Cj7azh8UXVZYa4k+AeEseIB21/MQpynet1S1EuifGH
# Ms0Zh8axQAbJ+rDlupWsRiO63WTAPt5OsL/uEH20xZ/50m8sidF9tIZ1QrsLq8JF
# i99Zm+OncY3ysG2mQAgcsz3x7254Q2mHOSuDWKDDXx6VCZ7ihmAEtnUbL1rCngdf
# 4evV71tVyhf+4KTebjk03t6mpqYvjO3W7yuObH8NOVaAcYgOjUi0G9AN/vYwBZHf
# BAhikGO8pKxW6U/Krc2oQWaKpmGzKK1OpSVi5VZuB6has6Mm3wIDAQABo4IBYDCC
# AVwwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUEB15NHKwwcMjbBDrbk8UA+4uHysw
# HwYDVR0jBBgwFoAUzolPglGqFaKEYsoxI2HSYfv4/ngwZwYIKwYBBQUHAQEEWzBZ
# MCMGCCsGAQUFBzABhhdodHRwOi8vb2NzcC5lbnRydXN0Lm5ldDAyBggrBgEFBQcw
# AoYmaHR0cDovL2FpYS5lbnRydXN0Lm5ldC9ldmNzMi1jaGFpbi5wN2MwMQYDVR0f
# BCowKDAmoCSgIoYgaHR0cDovL2NybC5lbnRydXN0Lm5ldC9ldmNzMi5jcmwwDgYD
# VR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUFBwMDMEsGA1UdIAREMEIwNwYK
# YIZIAYb6bAoBAjApMCcGCCsGAQUFBwIBFhtodHRwczovL3d3dy5lbnRydXN0Lm5l
# dC9ycGEwBwYFZ4EMAQMwDQYJKoZIhvcNAQELBQADggIBAIXuiHbQsWUCEhlA76KA
# YJCAbtiCXDerGtT1z27L+7/TcVUBOv2luPJ9C9qXVuQIwa0CTYNQ/kDKSkhWCJxi
# vk4OPaGi5yONchUlHsLQFXQOLDvSFbIYjeUvLAvOp30NgLyy7/Sw3SQsiSKmuLrK
# fSbNTqj0Lf48W+TQk5YD0TzDSSQG8+J4oVfYyyFxoo4C9kAoh7gTjwtj01p5QLKe
# LYJG5lpH6EomLDftK9Pe0woz46smPdL+d9dfvA51O3jS/xHt4kBpqWcWOZ2C5ZGx
# ydU6Ru+U7NVlHATRzAM/dxGJGqFCeTs1CpQF9vykl8iiSpPjzJ+CdrJbQ8gA0kCa
# +G7CagqQ3bkSMvRQllexC5HW6CiUKc8rJfZsCGOpEqtrfuxbiUUZ2og8BOliaFHK
# ZENurT73LtMNygx+yMcbaJkpfEheDJuGK82avSh9HFkyuJD3MI2MafN2OtyXyO/M
# sseiqHwpcRdwDZr0mkOrN9y1YOo62BYRVDVUep9X5lQ/MEA9c6iMgrQ4/E8kk4Jo
# LC7pe21qAP1ICIbjS7g5t4cbPfeFBtvSZeMANKmlDXQkedoGOOnOxqCuhxc3a0LX
# B746Q/VF6hookZlTqDXuu6aeIdD3tpLt0Dx8D69FY2Si/eMdn6dKDsT7CXYFve0S
# 1DDwrqhTIXI9wPojPbu8ZXPzMYIFXTCCBVkCAQEwdzBjMQswCQYDVQQGEwJVUzEW
# MBQGA1UEChMNRW50cnVzdCwgSW5jLjE8MDoGA1UEAxMzRW50cnVzdCBFeHRlbmRl
# ZCBWYWxpZGF0aW9uIENvZGUgU2lnbmluZyBDQSAtIEVWQ1MyAhAWdy8OxRnHb5Id
# XyBiye3RMA0GCWCGSAFlAwQCAQUAoIGEMBgGCisGAQQBgjcCAQwxCjAIoAKAAKEC
# gAAwGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEOMAwG
# CisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIPpxBMgqFrpZFFHFQCE8nef13FmT
# oZ+SHupzAYP8jYOvMA0GCSqGSIb3DQEBAQUABIICAEczJJyU3+B5qQ8N8PktIDvU
# NJwpEVEDDjlAz1hELMr1Ho0IqP6Q17X8jVfHrKqIUyH5tnJjAxhL5a6a49N5MNpb
# eGh2fh5uZUPUqhxFVwQ4/YT6WJZElMfW1+kuAO2UMzmjNT9oVCCLjkhECMf3Y8GT
# ogcL+xFzVvFUo4Z9+zj4pi3gItA2rOeNdAIM5URDW2Qx4IqpdytEApJuVkm34iP3
# FTXSke+L1isZ+k8uqUpUOx8q3GCAqE757XYBFQXAx89vocXRwLdoqlgZz4zq6LRS
# J6pE/PFSDcFjhPXl3Y4OmVsN8n7nx9F3eTxieeKRNZJfi/Y94OCsIUjA9Ijg32xL
# XQ459Vuav7yCGreZfTjS67jZBMQRZdHaDr6WGXv1LbPV0J3JRd4Jbrn93NKshL0q
# hSBGUEwMiOYBXInPwWEKgPZbWiD1Pna5iB6Nyop4N9h0YfL/0++4xFjn+oQ9E9ki
# lyNJktjsZRfGOxhcM81tSvwdE5HWFvXQmOctkAbNUyLpoZ3WUiga0VryKz9z+eWV
# z8MRFHTKrEqEqn5MRosSfDtSHH8Dt6eRLsbZKXVwguFkJYwdZLbjA/hOc9ZrR4ki
# +8Q6XB2vaV4+XPTn4Hx3qzCgTaU8CD/XubkhyuL9QR7svnXApXCBYqL7rZrXAacw
# m956jBj/E/wSZHFQOFRboYICMDCCAiwGCSqGSIb3DQEJBjGCAh0wggIZAgEBMIGG
# MHIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsT
# EHd3dy5kaWdpY2VydC5jb20xMTAvBgNVBAMTKERpZ2lDZXJ0IFNIQTIgQXNzdXJl
# ZCBJRCBUaW1lc3RhbXBpbmcgQ0ECEA1CSuC+Ooj/YEAhzhQA8N0wDQYJYIZIAWUD
# BAIBBQCgaTAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEP
# Fw0yMjA0MDEwMTI2NTFaMC8GCSqGSIb3DQEJBDEiBCCkxVyhWNIekgtnzvvgRcxZ
# H7YkTy6bWgi3OQ3iiqC0mzANBgkqhkiG9w0BAQEFAASCAQAhYYn/xcyl4fsDLAsI
# EzKcpvLz+nYn9LJuKVZvgDnO/KeGx8dosv7sEXfG14YU6FNFFtxj0aD5kLb3WO9e
# HOJFINqHSB399qfd2OSWcfwfzOQ/jeutJyVmPpEa/4SpE98lKQLOVJlb8bC/Cc+A
# ivfJC1qKhTIIwYDRE+LcE+FT4j/K0JQDk3xsiVUVIyiH73caljweXEBo7cFlst4V
# EK7L7pT5uiuoiZ5jrZPb+THyPKP5dRV/pddHki5R2bETDL1PIeBycviKD562oIui
# 4zBGuWm2cbs2Q9W7+Tck6ZK3E6KU5zzpSWBP88G80epIvXwdJBk4gS522BpY8HJf
# Vr5G
# SIG # End signature block