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") { Write-Error $Message if ($Underline) { Write-Error "$([string]::Empty.PadLeft($ScreenMessage.Length,$UnderlineChar))" } } elseif ($EntryType -eq "Warning") { Write-Warning $Message if ($Underline) { Write-Warning "$([string]::Empty.PadLeft($ScreenMessage.Length,$UnderlineChar))" } } 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 # MIIczwYJKoZIhvcNAQcCoIIcwDCCHLwCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUXwqcMZkt0Snjugjmsr/POsrX # 13igghcwMIIEFDCCAvygAwIBAgILBAAAAAABL07hUtcwDQYJKoZIhvcNAQEFBQAw # VzELMAkGA1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNV # BAsTB1Jvb3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw0xMTA0 # MTMxMDAwMDBaFw0yODAxMjgxMjAwMDBaMFIxCzAJBgNVBAYTAkJFMRkwFwYDVQQK # ExBHbG9iYWxTaWduIG52LXNhMSgwJgYDVQQDEx9HbG9iYWxTaWduIFRpbWVzdGFt # cGluZyBDQSAtIEcyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlO9l # +LVXn6BTDTQG6wkft0cYasvwW+T/J6U00feJGr+esc0SQW5m1IGghYtkWkYvmaCN # d7HivFzdItdqZ9C76Mp03otPDbBS5ZBb60cO8eefnAuQZT4XljBFcm05oRc2yrmg # jBtPCBn2gTGtYRakYua0QJ7D/PuV9vu1LpWBmODvxevYAll4d/eq41JrUJEpxfz3 # zZNl0mBhIvIG+zLdFlH6Dv2KMPAXCae78wSuq5DnbN96qfTvxGInX2+ZbTh0qhGL # 2t/HFEzphbLswn1KJo/nVrqm4M+SU4B09APsaLJgvIQgAIMboe60dAXBKY5i0Eex # +vBTzBj5Ljv5cH60JQIDAQABo4HlMIHiMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMB # Af8ECDAGAQH/AgEAMB0GA1UdDgQWBBRG2D7/3OO+/4Pm9IWbsN1q1hSpwTBHBgNV # HSAEQDA+MDwGBFUdIAAwNDAyBggrBgEFBQcCARYmaHR0cHM6Ly93d3cuZ2xvYmFs # c2lnbi5jb20vcmVwb3NpdG9yeS8wMwYDVR0fBCwwKjAooCagJIYiaHR0cDovL2Ny # bC5nbG9iYWxzaWduLm5ldC9yb290LmNybDAfBgNVHSMEGDAWgBRge2YaRQ2XyolQ # L30EzTSo//z9SzANBgkqhkiG9w0BAQUFAAOCAQEATl5WkB5GtNlJMfO7FzkoG8IW # 3f1B3AkFBJtvsqKa1pkuQJkAVbXqP6UgdtOGNNQXzFU6x4Lu76i6vNgGnxVQ380W # e1I6AtcZGv2v8Hhc4EvFGN86JB7arLipWAQCBzDbsBJe/jG+8ARI9PBw+DpeVoPP # PfsNvPTF7ZedudTbpSeE4zibi6c1hkQgpDttpGoLoYP9KOva7yj2zIhd+wo7AKvg # IeviLzVsD440RZfroveZMzV+y5qKu0VN5z+fwtmK+mWybsd+Zf/okuEsMaL3sCc2 # SI8mbzvuTXYfecPlf5Y1vC0OzAGwjn//UYCAp5LUs0RGZIyHTxZjBzFLY7Df8zCC # BH0wggNloAMCAQICAxvnFTANBgkqhkiG9w0BAQsFADBjMQswCQYDVQQGEwJVUzEh # MB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBE # YWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTE0MDEwMTA3 # MDAwMFoXDTMxMDUzMDA3MDAwMFowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdB # cml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNv # bSwgSW5jLjExMC8GA1UEAxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRo # b3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx # +lk09xvJGKP3gElY6SKDE6bFIEMBO4Tx5oVJnyfq9oQbTqC023CYxzIBsQU+B07u # 9PpPL1kwIuerGVZr4oAH/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD+qK+ihVqf94L # w7YZFAXK6sOoBJQ7RnwyDfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutd # fMh8+7ArU6SSYmlRJQVhGkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7 # S13MMuyFYkMlNAJWJwGRtDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsD # PAnrSTFcaUaz4EcCAwEAAaOCARcwggETMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0P # AQH/BAQDAgEGMB0GA1UdDgQWBBQ6moUHEGcotu/2vQVBbiDBlNoP3jAfBgNVHSME # GDAWgBTSxLDSkdRMEXGzYcs9of7dqGrU4zA0BggrBgEFBQcBAQQoMCYwJAYIKwYB # BQUHMAGGGGh0dHA6Ly9vY3NwLmdvZGFkZHkuY29tLzAyBgNVHR8EKzApMCegJaAj # hiFodHRwOi8vY3JsLmdvZGFkZHkuY29tL2dkcm9vdC5jcmwwRgYDVR0gBD8wPTA7 # BgRVHSAAMDMwMQYIKwYBBQUHAgEWJWh0dHBzOi8vY2VydHMuZ29kYWRkeS5jb20v # cmVwb3NpdG9yeS8wDQYJKoZIhvcNAQELBQADggEBAFkLU72ShhGnJHvtWzHPHR9s # cMW4br5Ou/a+l1DhMH+6KFxilMLjfjP3+0J2hduVHIwiWHUJDIhlZzkKFgnFoDiX # pMUjkz+0GKYBBkSR46dpJ7RaJX86tzLN3YT/KjgpM6TdZ7KF/qGIIBxQicjcKvZC # AzdM5ojf1a8k8rHD38y17OCZXrdJVCA8lBgMxxxSGEmkbeGzWAvJ2OzZrhwyjihw # DeL+pheehA+9V3CzWukfoIZTu+98/2kL4EjDt5MLyApUxKxdFGc3bMqlLzEIN6pu # b4y8m+JXXSSBr5eXnIStbKw3TGbzYZERIOS+MJ96pCkJsOE0X2R3GEBR34wwpq8w # ggSfMIIDh6ADAgECAhIRIdaZp2SXPvH4Qn7pGcxTQRQwDQYJKoZIhvcNAQEFBQAw # UjELMAkGA1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExKDAmBgNV # BAMTH0dsb2JhbFNpZ24gVGltZXN0YW1waW5nIENBIC0gRzIwHhcNMTYwNTI0MDAw # MDAwWhcNMjcwNjI0MDAwMDAwWjBgMQswCQYDVQQGEwJTRzEfMB0GA1UEChMWR01P # IEdsb2JhbFNpZ24gUHRlIEx0ZDEwMC4GA1UEAxMnR2xvYmFsU2lnbiBUU0EgZm9y # IE1TIEF1dGhlbnRpY29kZSAtIEcyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB # CgKCAQEAsBeuotO2BDBWHlgPse1VpNZUy9j2czrsXV6rJf02pfqEw2FAxUa1WVI7 # QqIuXxNiEKlb5nPWkiWxfSPjBrOHOg5D8NcAiVOiETFSKG5dQHI88gl3p0mSl9Rs # kKB2p/243LOd8gdgLE9YmABr0xVU4Prd/4AsXximmP/Uq+yhRVmyLm9iXeDZGayL # V5yoJivZF6UQ0kcIGnAsM4t/aIAqtaFda92NAgIpA6p8N7u7KU49U5OzpvqP0liT # FUy5LauAo6Ml+6/3CGSwekQPXBDXX2E3qk5r09JTJZ2Cc/os+XKwqRk5KlD6qdA8 # OsroW+/1X1H0+QrZlzXeaoXmIwRCrwIDAQABo4IBXzCCAVswDgYDVR0PAQH/BAQD # AgeAMEwGA1UdIARFMEMwQQYJKwYBBAGgMgEeMDQwMgYIKwYBBQUHAgEWJmh0dHBz # Oi8vd3d3Lmdsb2JhbHNpZ24uY29tL3JlcG9zaXRvcnkvMAkGA1UdEwQCMAAwFgYD # VR0lAQH/BAwwCgYIKwYBBQUHAwgwQgYDVR0fBDswOTA3oDWgM4YxaHR0cDovL2Ny # bC5nbG9iYWxzaWduLmNvbS9ncy9nc3RpbWVzdGFtcGluZ2cyLmNybDBUBggrBgEF # BQcBAQRIMEYwRAYIKwYBBQUHMAKGOGh0dHA6Ly9zZWN1cmUuZ2xvYmFsc2lnbi5j # b20vY2FjZXJ0L2dzdGltZXN0YW1waW5nZzIuY3J0MB0GA1UdDgQWBBTUooRKOFoY # f7pPMFC9ndV6h9YJ9zAfBgNVHSMEGDAWgBRG2D7/3OO+/4Pm9IWbsN1q1hSpwTAN # BgkqhkiG9w0BAQUFAAOCAQEAj6kakW0EpjcgDoOW3iPTa24fbt1kPWghIrX4RzZp # juGlRcckoiK3KQnMVFquxrzNY46zPVBI5bTMrs2SjZ4oixNKEaq9o+/Tsjb8tKFy # v22XY3mMRLxwL37zvN2CU6sa9uv6HJe8tjecpBwwvKu8LUc235IgA+hxxlj2dQWa # NPALWVqCRDSqgOQvhPZHXZbJtsrKnbemuuRQ09Q3uLogDtDTkipbxFm7oW3bPM5E # ncE4Kq3jjb3NCXcaEL5nCgI2ZIi5sxsm7ueeYMRGqLxhM2zPTrmcuWrwnzf+tT1P # mtNN/94gjk6Xpv2fCbxNyhh2ybBNhVDygNIdBvVYBAexGDCCBNAwggO4oAMCAQIC # AQcwDQYJKoZIhvcNAQELBQAwgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6 # b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwg # SW5jLjExMC8GA1UEAxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3Jp # dHkgLSBHMjAeFw0xMTA1MDMwNzAwMDBaFw0zMTA1MDMwNzAwMDBaMIG0MQswCQYD # VQQGEwJVUzEQMA4GA1UECBMHQXJpem9uYTETMBEGA1UEBxMKU2NvdHRzZGFsZTEa # MBgGA1UEChMRR29EYWRkeS5jb20sIEluYy4xLTArBgNVBAsTJGh0dHA6Ly9jZXJ0 # cy5nb2RhZGR5LmNvbS9yZXBvc2l0b3J5LzEzMDEGA1UEAxMqR28gRGFkZHkgU2Vj # dXJlIENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMIIBIjANBgkqhkiG9w0BAQEF # AAOCAQ8AMIIBCgKCAQEAueDLENSvdr3Uk2LrMGS4gQhswwTZYheOL/8+Zc+PzmLm # PFIc2hZFS1WreGtjg2KQzg9pbJnIGhSLTMxFM+qI3J6jryv+gGGdeVfEzy70PzA8 # XUf8mha8wzeWQVGOEUtU+Ci+0Iy+8DA4HvOwJvhmR2Nt3nEmR484R1PRRh2049wA # 6kWsvbxx2apvANvbzTA6eU9fTEf4He9bwsSdYDuxskOR2KQzTuqz1idPrSWKpcb0 # 1dCmrnQFZFeItURV1C0qOj74uL3pMgoClGTEFjpQ8Uqu53kzrwwgB3/o3wQ5wmkC # bGNS+nfBG8h0h8i5kxhQVDVLaU68O9NJLh/cwdJS+wIDAQABo4IBGjCCARYwDwYD # VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFEDCvSeOzDSD # MKIz1/tss/C0LIDOMB8GA1UdIwQYMBaAFDqahQcQZyi27/a9BUFuIMGU2g/eMDQG # CCsGAQUFBwEBBCgwJjAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZ29kYWRkeS5j # b20vMDUGA1UdHwQuMCwwKqAooCaGJGh0dHA6Ly9jcmwuZ29kYWRkeS5jb20vZ2Ry # b290LWcyLmNybDBGBgNVHSAEPzA9MDsGBFUdIAAwMzAxBggrBgEFBQcCARYlaHR0 # cHM6Ly9jZXJ0cy5nb2RhZGR5LmNvbS9yZXBvc2l0b3J5LzANBgkqhkiG9w0BAQsF # AAOCAQEACH5skxDIOLiWqZBL/6FfTwTvbD6ciAbJUI+mc/dXMRu+vOQv2/i601vg # tOfmeWIODKLXamNzMbX1qEikOwgtol2Q17R8JU8RVjDEtkSdeyyd5V7m7wxhqr/k # KhvuhJ64g33BQ85EpxNwDZEf9MgTrYNg2dhyqHMkHrWsIg7KF4liWEQbq4klAQAP # zcQbYttRtNMPUSqb9Lxz/HbONqTN2dgs6q6b9SqykNFNdRiKP4pBkCN9W0v+pANY # m0ayw2Bgg/h9UEHOwqGQw7vvAi/SFVTuRBXZCq6nijPtsS12NibcBOuf92EfFdyH # b+5GliitoSZ9CgmnLgSjjbz4vAQwATCCBRwwggQEoAMCAQICCDeMqUwECkf0MA0G # CSqGSIb3DQEBCwUAMIG0MQswCQYDVQQGEwJVUzEQMA4GA1UECBMHQXJpem9uYTET # MBEGA1UEBxMKU2NvdHRzZGFsZTEaMBgGA1UEChMRR29EYWRkeS5jb20sIEluYy4x # LTArBgNVBAsTJGh0dHA6Ly9jZXJ0cy5nb2RhZGR5LmNvbS9yZXBvc2l0b3J5LzEz # MDEGA1UEAxMqR28gRGFkZHkgU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eSAt # IEcyMB4XDTIwMDEwODExMjIyNFoXDTIxMDMwODE4NTgwMFowXjELMAkGA1UEBhMC # Q0ExEDAOBgNVBAgTB09udGFyaW8xDzANBgNVBAcTBk90dGF3YTEVMBMGA1UEChMM # Q0FOQVJJRSBJbmMuMRUwEwYDVQQDEwxDQU5BUklFIEluYy4wggEiMA0GCSqGSIb3 # DQEBAQUAA4IBDwAwggEKAoIBAQDZhfCjFqiTmN1uLoySixnwaOjf/ZAL9P6SvjlC # aBA2mutoorEgnzUP8HnOIcvMRgEMPmpaZ8egM93Bmx9d41xoarsQpCN3DhYOo+b3 # fWnPucVtpxbul2OFePv63mw/uvr+dqkv4b/f3Tg+ilQbpsNonbvh9MKEFv8Pn9ko # j0ySV+qxz34PxTVAe6g//pel3/3i9fqilCnIEcx4zg/+NKBeOWROSs4oXo3IvBjV # runmz+YuieSr78TqIE6hD8JF2q1wKwfMB3+x7dEXZAus9WtIU/qITATtEfO9QAgr # rYL4F1MLN+osSp8my5eCOjnLTQc47q574V3zQhsIHW7yBXLdAgMBAAGjggGFMIIB # gTAMBgNVHRMBAf8EAjAAMBMGA1UdJQQMMAoGCCsGAQUFBwMDMA4GA1UdDwEB/wQE # AwIHgDA1BgNVHR8ELjAsMCqgKKAmhiRodHRwOi8vY3JsLmdvZGFkZHkuY29tL2dk # aWcyczUtNS5jcmwwXQYDVR0gBFYwVDBIBgtghkgBhv1tAQcXAjA5MDcGCCsGAQUF # BwIBFitodHRwOi8vY2VydGlmaWNhdGVzLmdvZGFkZHkuY29tL3JlcG9zaXRvcnkv # MAgGBmeBDAEEATB2BggrBgEFBQcBAQRqMGgwJAYIKwYBBQUHMAGGGGh0dHA6Ly9v # Y3NwLmdvZGFkZHkuY29tLzBABggrBgEFBQcwAoY0aHR0cDovL2NlcnRpZmljYXRl # cy5nb2RhZGR5LmNvbS9yZXBvc2l0b3J5L2dkaWcyLmNydDAfBgNVHSMEGDAWgBRA # wr0njsw0gzCiM9f7bLPwtCyAzjAdBgNVHQ4EFgQUUPnMg2nmYS8l7rmax3weVkrg # z5AwDQYJKoZIhvcNAQELBQADggEBAIYabiARaY4KhO6oWgNHPOBjoHuqUH7NwRGN # /ztYJznRBZbdD50smoK5GR0FvUZ8TXhYoZOazXe4NlFM4e6YcudU+EA/OF+sZHFB # Wziz1VS6U3sS+cGyJcxvelSoid0q3W3i9/Zy6Nv2kk/DEJp49O47mPNovpL15yyk # X3Vo26GwC9peo4s/cKMzthmgrcF2uLkT+LW44xKhaL7nBTGDMhjno+a3t00SWCId # 7wzgQadIJ1QlFOKm0xgmuiW3LIqCG0apvaOfvWKTPKq68q+FbDPOO48oKrvw1c9K # /m8gcnBLz6PX1REVIs5u3pvdOYBCz6uXyKxnt+Q5jDEK0NskLu0xggUJMIIFBQIB # ATCBwTCBtDELMAkGA1UEBhMCVVMxEDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcT # ClNjb3R0c2RhbGUxGjAYBgNVBAoTEUdvRGFkZHkuY29tLCBJbmMuMS0wKwYDVQQL # EyRodHRwOi8vY2VydHMuZ29kYWRkeS5jb20vcmVwb3NpdG9yeS8xMzAxBgNVBAMT # KkdvIERhZGR5IFNlY3VyZSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMgIIN4yp # TAQKR/QwCQYFKw4DAhoFAKB4MBgGCisGAQQBgjcCAQwxCjAIoAKAAKECgAAwGQYJ # KoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEOMAwGCisGAQQB # gjcCARUwIwYJKoZIhvcNAQkEMRYEFPkyQxl36Mc9syfpz+9/MpOVMMGDMA0GCSqG # SIb3DQEBAQUABIIBAHgM0oaXUqZ2Ns7983wAhWTbcbf9yRionmaL9jSrqMWCpMjp # AIosWesZSIWNCQlfquH6yiy/sIKv7mcpJNNQsy1ER+UKb3a/YolpZ82MSBkS6V7q # YYefyGdmwEf850wTXQ9u3lv+2F0+6NAvrzeVKmzTETQ4TqMftxiZyq396HmrppnH # rT+7Goip+RS10JjBUo2aPo+jHxOLHsGqovgPbv/ZORl8CfMzXRfVdvU1RaWrwApJ # qzueKXWveYLimzQTOb2OLhre1n9zjEMU6nqiy9Dbgkve64qiDyumeu+cAzff6Vn8 # uV1bvSbKGOivtZKfqrnw6zabMyGqxSmQ5Qh08EChggKiMIICngYJKoZIhvcNAQkG # MYICjzCCAosCAQEwaDBSMQswCQYDVQQGEwJCRTEZMBcGA1UEChMQR2xvYmFsU2ln # biBudi1zYTEoMCYGA1UEAxMfR2xvYmFsU2lnbiBUaW1lc3RhbXBpbmcgQ0EgLSBH # MgISESHWmadklz7x+EJ+6RnMU0EUMAkGBSsOAwIaBQCggf0wGAYJKoZIhvcNAQkD # MQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMjAwNTEyMTM0MTMwWjAjBgkq # hkiG9w0BCQQxFgQU3g8dZZQaxUSbRxN+XXwNLLnRY0EwgZ0GCyqGSIb3DQEJEAIM # MYGNMIGKMIGHMIGEBBRjuC+rYfWDkJaVBQsAJJxQKTPseTBsMFakVDBSMQswCQYD # VQQGEwJCRTEZMBcGA1UEChMQR2xvYmFsU2lnbiBudi1zYTEoMCYGA1UEAxMfR2xv # YmFsU2lnbiBUaW1lc3RhbXBpbmcgQ0EgLSBHMgISESHWmadklz7x+EJ+6RnMU0EU # MA0GCSqGSIb3DQEBAQUABIIBAFziuz3KQgEUfwxGJu5VgepwbFBFCjI6DS9ttG9K # 4s9vQh/vfE/GbafO4X2kF5Ix8I9p+epWqjix+oPvigSLFfZzG07fPjAKMabrpDLh # 6uO9LdOoapemMoFRwQ8WzvKwaQ0E6k5mMwJzCUeqLOKeGG0M32Ko1iyls5IoKplU # q9gLEWKb8FLbs/1nLq8hSREdtB9DerGBMj0/34tsRvGXXL0yu2oriB9/zYUR9geG # 0HXUXWyDO9gNJWiCyx1J80VM5TeM/MVHT61wAwf3ojQS5FTh60pU10MYELQse6sV # GSyy6hj3cOIVPz42AL5oPtuSQEWDfMrKCXJxuRVB0UKslXk= # SIG # End signature block |