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 # MIIRbgYJKoZIhvcNAQcCoIIRXzCCEVsCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUXwqcMZkt0Snjugjmsr/POsrX # 13iggg51MIIEfTCCA2WgAwIBAgIDG+cVMA0GCSqGSIb3DQEBCwUAMGMxCzAJBgNV # BAYTAlVTMSEwHwYDVQQKExhUaGUgR28gRGFkZHkgR3JvdXAsIEluYy4xMTAvBgNV # BAsTKEdvIERhZGR5IENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcN # MTQwMTAxMDcwMDAwWhcNMzEwNTMwMDcwMDAwWjCBgzELMAkGA1UEBhMCVVMxEDAO # BgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoTEUdv # RGFkZHkuY29tLCBJbmMuMTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRpZmlj # YXRlIEF1dGhvcml0eSAtIEcyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC # AQEAv3FiCPH6WTT3G8kYo/eASVjpIoMTpsUgQwE7hPHmhUmfJ+r2hBtOoLTbcJjH # MgGxBT4HTu70+k8vWTAi56sZVmvigAf88xZ1gDlRe+X5NbZ0TqmNghPktj+pA4P6 # or6KFWp/3gvDthkUBcrqw6gElDtGfDIN8wBmIsiNaW02jBEYt9OyHGC0OPoCjM7T # 3UYH3go+6118yHz7sCtTpJJiaVElBWEaRIGMLKlDliPfrDqBmg4pxRyp6V0etp6e # MAo5zvGIgPtLXcwy7IViQyU0AlYnAZG0O3AqP26x6JyIAX2f1PnbU21gnb8s51ir # uF9G/M7EGwM8CetJMVxpRrPgRwIDAQABo4IBFzCCARMwDwYDVR0TAQH/BAUwAwEB # /zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFDqahQcQZyi27/a9BUFuIMGU2g/e # MB8GA1UdIwQYMBaAFNLEsNKR1EwRcbNhyz2h/t2oatTjMDQGCCsGAQUFBwEBBCgw # JjAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZ29kYWRkeS5jb20vMDIGA1UdHwQr # MCkwJ6AloCOGIWh0dHA6Ly9jcmwuZ29kYWRkeS5jb20vZ2Ryb290LmNybDBGBgNV # HSAEPzA9MDsGBFUdIAAwMzAxBggrBgEFBQcCARYlaHR0cHM6Ly9jZXJ0cy5nb2Rh # ZGR5LmNvbS9yZXBvc2l0b3J5LzANBgkqhkiG9w0BAQsFAAOCAQEAWQtTvZKGEack # e+1bMc8dH2xwxbhuvk679r6XUOEwf7ooXGKUwuN+M/f7QnaF25UcjCJYdQkMiGVn # OQoWCcWgOJekxSOTP7QYpgEGRJHjp2kntFolfzq3Ms3dhP8qOCkzpN1nsoX+oYgg # HFCJyNwq9kIDN0zmiN/VryTyscPfzLXs4Jlet0lUIDyUGAzHHFIYSaRt4bNYC8nY # 7NmuHDKOKHAN4v6mF56ED71XcLNa6R+ghlO773z/aQvgSMO3kwvIClTErF0UZzds # yqUvMQg3qm5vjLyb4lddJIGvl5echK1srDdMZvNhkREg5L4wn3qkKQmw4TRfZHcY # QFHfjDCmrzCCBNAwggO4oAMCAQICAQcwDQYJKoZIhvcNAQELBQAwgYMxCzAJBgNV # BAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMRow # GAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8GA1UEAxMoR28gRGFkZHkgUm9v # dCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjAeFw0xMTA1MDMwNzAwMDBaFw0z # MTA1MDMwNzAwMDBaMIG0MQswCQYDVQQGEwJVUzEQMA4GA1UECBMHQXJpem9uYTET # MBEGA1UEBxMKU2NvdHRzZGFsZTEaMBgGA1UEChMRR29EYWRkeS5jb20sIEluYy4x # LTArBgNVBAsTJGh0dHA6Ly9jZXJ0cy5nb2RhZGR5LmNvbS9yZXBvc2l0b3J5LzEz # MDEGA1UEAxMqR28gRGFkZHkgU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eSAt # IEcyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAueDLENSvdr3Uk2Lr # MGS4gQhswwTZYheOL/8+Zc+PzmLmPFIc2hZFS1WreGtjg2KQzg9pbJnIGhSLTMxF # M+qI3J6jryv+gGGdeVfEzy70PzA8XUf8mha8wzeWQVGOEUtU+Ci+0Iy+8DA4HvOw # JvhmR2Nt3nEmR484R1PRRh2049wA6kWsvbxx2apvANvbzTA6eU9fTEf4He9bwsSd # YDuxskOR2KQzTuqz1idPrSWKpcb01dCmrnQFZFeItURV1C0qOj74uL3pMgoClGTE # FjpQ8Uqu53kzrwwgB3/o3wQ5wmkCbGNS+nfBG8h0h8i5kxhQVDVLaU68O9NJLh/c # wdJS+wIDAQABo4IBGjCCARYwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC # AQYwHQYDVR0OBBYEFEDCvSeOzDSDMKIz1/tss/C0LIDOMB8GA1UdIwQYMBaAFDqa # hQcQZyi27/a9BUFuIMGU2g/eMDQGCCsGAQUFBwEBBCgwJjAkBggrBgEFBQcwAYYY # aHR0cDovL29jc3AuZ29kYWRkeS5jb20vMDUGA1UdHwQuMCwwKqAooCaGJGh0dHA6 # Ly9jcmwuZ29kYWRkeS5jb20vZ2Ryb290LWcyLmNybDBGBgNVHSAEPzA9MDsGBFUd # IAAwMzAxBggrBgEFBQcCARYlaHR0cHM6Ly9jZXJ0cy5nb2RhZGR5LmNvbS9yZXBv # c2l0b3J5LzANBgkqhkiG9w0BAQsFAAOCAQEACH5skxDIOLiWqZBL/6FfTwTvbD6c # iAbJUI+mc/dXMRu+vOQv2/i601vgtOfmeWIODKLXamNzMbX1qEikOwgtol2Q17R8 # JU8RVjDEtkSdeyyd5V7m7wxhqr/kKhvuhJ64g33BQ85EpxNwDZEf9MgTrYNg2dhy # qHMkHrWsIg7KF4liWEQbq4klAQAPzcQbYttRtNMPUSqb9Lxz/HbONqTN2dgs6q6b # 9SqykNFNdRiKP4pBkCN9W0v+pANYm0ayw2Bgg/h9UEHOwqGQw7vvAi/SFVTuRBXZ # Cq6nijPtsS12NibcBOuf92EfFdyHb+5GliitoSZ9CgmnLgSjjbz4vAQwATCCBRww # ggQEoAMCAQICCDeMqUwECkf0MA0GCSqGSIb3DQEBCwUAMIG0MQswCQYDVQQGEwJV # UzEQMA4GA1UECBMHQXJpem9uYTETMBEGA1UEBxMKU2NvdHRzZGFsZTEaMBgGA1UE # ChMRR29EYWRkeS5jb20sIEluYy4xLTArBgNVBAsTJGh0dHA6Ly9jZXJ0cy5nb2Rh # ZGR5LmNvbS9yZXBvc2l0b3J5LzEzMDEGA1UEAxMqR28gRGFkZHkgU2VjdXJlIENl # cnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTIwMDEwODExMjIyNFoXDTIxMDMw # ODE4NTgwMFowXjELMAkGA1UEBhMCQ0ExEDAOBgNVBAgTB09udGFyaW8xDzANBgNV # BAcTBk90dGF3YTEVMBMGA1UEChMMQ0FOQVJJRSBJbmMuMRUwEwYDVQQDEwxDQU5B # UklFIEluYy4wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZhfCjFqiT # mN1uLoySixnwaOjf/ZAL9P6SvjlCaBA2mutoorEgnzUP8HnOIcvMRgEMPmpaZ8eg # M93Bmx9d41xoarsQpCN3DhYOo+b3fWnPucVtpxbul2OFePv63mw/uvr+dqkv4b/f # 3Tg+ilQbpsNonbvh9MKEFv8Pn9koj0ySV+qxz34PxTVAe6g//pel3/3i9fqilCnI # Ecx4zg/+NKBeOWROSs4oXo3IvBjVrunmz+YuieSr78TqIE6hD8JF2q1wKwfMB3+x # 7dEXZAus9WtIU/qITATtEfO9QAgrrYL4F1MLN+osSp8my5eCOjnLTQc47q574V3z # QhsIHW7yBXLdAgMBAAGjggGFMIIBgTAMBgNVHRMBAf8EAjAAMBMGA1UdJQQMMAoG # CCsGAQUFBwMDMA4GA1UdDwEB/wQEAwIHgDA1BgNVHR8ELjAsMCqgKKAmhiRodHRw # Oi8vY3JsLmdvZGFkZHkuY29tL2dkaWcyczUtNS5jcmwwXQYDVR0gBFYwVDBIBgtg # hkgBhv1tAQcXAjA5MDcGCCsGAQUFBwIBFitodHRwOi8vY2VydGlmaWNhdGVzLmdv # ZGFkZHkuY29tL3JlcG9zaXRvcnkvMAgGBmeBDAEEATB2BggrBgEFBQcBAQRqMGgw # JAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmdvZGFkZHkuY29tLzBABggrBgEFBQcw # AoY0aHR0cDovL2NlcnRpZmljYXRlcy5nb2RhZGR5LmNvbS9yZXBvc2l0b3J5L2dk # aWcyLmNydDAfBgNVHSMEGDAWgBRAwr0njsw0gzCiM9f7bLPwtCyAzjAdBgNVHQ4E # FgQUUPnMg2nmYS8l7rmax3weVkrgz5AwDQYJKoZIhvcNAQELBQADggEBAIYabiAR # aY4KhO6oWgNHPOBjoHuqUH7NwRGN/ztYJznRBZbdD50smoK5GR0FvUZ8TXhYoZOa # zXe4NlFM4e6YcudU+EA/OF+sZHFBWziz1VS6U3sS+cGyJcxvelSoid0q3W3i9/Zy # 6Nv2kk/DEJp49O47mPNovpL15yykX3Vo26GwC9peo4s/cKMzthmgrcF2uLkT+LW4 # 4xKhaL7nBTGDMhjno+a3t00SWCId7wzgQadIJ1QlFOKm0xgmuiW3LIqCG0apvaOf # vWKTPKq68q+FbDPOO48oKrvw1c9K/m8gcnBLz6PX1REVIs5u3pvdOYBCz6uXyKxn # t+Q5jDEK0NskLu0xggJjMIICXwIBATCBwTCBtDELMAkGA1UEBhMCVVMxEDAOBgNV # BAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoTEUdvRGFk # ZHkuY29tLCBJbmMuMS0wKwYDVQQLEyRodHRwOi8vY2VydHMuZ29kYWRkeS5jb20v # cmVwb3NpdG9yeS8xMzAxBgNVBAMTKkdvIERhZGR5IFNlY3VyZSBDZXJ0aWZpY2F0 # ZSBBdXRob3JpdHkgLSBHMgIIN4ypTAQKR/QwCQYFKw4DAhoFAKB4MBgGCisGAQQB # gjcCAQwxCjAIoAKAAKECgAAwGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYK # KwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUwIwYJKoZIhvcNAQkEMRYEFPkyQxl3 # 6Mc9syfpz+9/MpOVMMGDMA0GCSqGSIb3DQEBAQUABIIBAHgM0oaXUqZ2Ns7983wA # hWTbcbf9yRionmaL9jSrqMWCpMjpAIosWesZSIWNCQlfquH6yiy/sIKv7mcpJNNQ # sy1ER+UKb3a/YolpZ82MSBkS6V7qYYefyGdmwEf850wTXQ9u3lv+2F0+6NAvrzeV # KmzTETQ4TqMftxiZyq396HmrppnHrT+7Goip+RS10JjBUo2aPo+jHxOLHsGqovgP # bv/ZORl8CfMzXRfVdvU1RaWrwApJqzueKXWveYLimzQTOb2OLhre1n9zjEMU6nqi # y9Dbgkve64qiDyumeu+cAzff6Vn8uV1bvSbKGOivtZKfqrnw6zabMyGqxSmQ5Qh0 # 8EA= # SIG # End signature block |