AMPowerShellTemplate.psm1
<#
.Synopsis This function creates a new PowerShell Module, PowerShell Manifest file and default Pester tests including default PSScriptAnalyser tests for all files. .DESCRIPTION Long description .EXAMPLE New-AMPowerShellModule -Name MyModule -Path C:\MyPath\ -Author 'Flemming Rohde' -CompanyName Automize -Copyright 2018 -ModuleVersion 1.0.0.0 -Description testing -Verbose .EXAMPLE Another example of how to use this cmdlet .INPUTS Inputs to this cmdlet (if any) .OUTPUTS Output from this cmdlet (if any) .NOTES General notes .COMPONENT The component this cmdlet belongs to .ROLE The role this cmdlet belongs to .FUNCTIONALITY The functionality that best describes this cmdlet #> Function New-AMPowerShellModule { [CmdletBinding(SupportsShouldProcess = $true)] param( [Parameter(Mandatory = $true)][ValidateNotNullOrEmpty()][String]$Name, [Parameter(Mandatory = $true)][ValidateNotNullOrEmpty()][String]$Path, [Parameter(Mandatory = $true)][ValidateNotNullOrEmpty()][String]$Author, [Parameter(Mandatory = $true)][ValidateNotNullOrEmpty()][String]$CompanyName, [Parameter(Mandatory = $true)][ValidateNotNullOrEmpty()][String]$Copyright, [Parameter(Mandatory = $true)][ValidateNotNullOrEmpty()][String]$ModuleVersion, [Parameter(Mandatory = $true)][ValidateNotNullOrEmpty()][String]$Description ) Begin { } Process { if ($pscmdlet.ShouldProcess("PowerShell Module name: $Name", "New")) { $ModuleFolderPath = New-Item -Path $Path -Name $Name -ItemType Directory -Verbose New-Item -Path $ModuleFolderPath -Name 'Tests' -ItemType Directory -Verbose Out-File -FilePath "$ModuleFolderPath\Temp.psm1" -Encoding utf8 -Verbose $TemplateContent = @' Function New-Function { <# .Synopsis Short description .DESCRIPTION Long description .EXAMPLE Example of how to use this cmdlet .EXAMPLE Another example of how to use this cmdlet .INPUTS Inputs to this cmdlet (if any) .OUTPUTS Output from this cmdlet (if any) .NOTES General notes .COMPONENT The component this cmdlet belongs to .ROLE The role this cmdlet belongs to .FUNCTIONALITY The functionality that best describes this cmdlet #> [CmdletBinding(SupportsShouldProcess=$true)] param ( #Not mandatory parameter example [Parameter( Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] [AllowNull()] [String]$param1, #Mandatory parameter example [Parameter( Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] [ValidateNotNullOrEmpty()] [String]$Param2 ) Begin { } Process { try { if ($pscmdlet.ShouldProcess("Target", "Operation")) { } } catch { throw } } End { } } '@ $TemplateContent | Set-Content -Path "$ModuleFolderPath\Temp.psm1" -Encoding UTF8 Get-Content -Path "$ModuleFolderPath\Temp.psm1" | ForEach-Object {$PSItem.TrimEnd()} | Set-Content "$ModuleFolderPath\$Name.psm1" -Encoding UTF8 Remove-Item -Path "$ModuleFolderPath\Temp.psm1" -Force $ModulePath = (Get-Module -Name AMPowerShellTemplate).path $CurrentLocation = Get-Location Push-Location -Path $ModulePath.Substring(0, $ModulePath.LastIndexOf("\")) $Parameters = Get-Content -Path .\DefaultTests.json | ConvertFrom-Json $newTestScriptFileInfoSplat = @{ Copyright = $Copyright Description = $Description Version = $ModuleVersion CompanyName = $CompanyName Guid = [Guid]::NewGuid().Guid Author = $Author Path = "$ModuleFolderPath\Tests\Temp.tests.ps1" } New-ScriptFileInfo @newTestScriptFileInfoSplat (Get-Content -Path "$ModuleFolderPath\Tests\Temp.tests.ps1").Replace("Param()",$Parameters.DefaultTests.Module.Content) | Set-Content "$ModuleFolderPath\Tests\Temp.tests.ps1" -Encoding UTF8 Get-Content -Path "$ModuleFolderPath\Tests\Temp.tests.ps1" | ForEach-Object {$PSItem.TrimEnd()} | Set-Content "$ModuleFolderPath\Tests\$Name.tests.ps1" -Encoding UTF8 Remove-Item -Path "$ModuleFolderPath\Tests\temp.tests.ps1" -Force $ModuleManifestParams = @{ RootModule = "$Name.psm1" Path = "$ModuleFolderPath\$Name.psd1" GUID = [System.Guid]::NewGuid() Author = $Author CompanyName = $CompanyName Copyright = $Copyright ModuleVersion = $ModuleVersion Description = $Description FunctionsToExport = @() CmdletsToExport = @() AliasesToExport = @() Verbose = $true } New-ModuleManifest @ModuleManifestParams Push-Location $ModuleFolderPath Invoke-Pester ".\Tests\$Name.tests.ps1" Set-Location $CurrentLocation } } End { } } <# .Synopsis This function creates a new PowerShell Script and default Pester tests including default PSScriptAnalyser tests for all files. .DESCRIPTION Long description .EXAMPLE New-AMPowerShellScript -Name MyScript -Path C:\MyPath -Verbose .EXAMPLE Another example of how to use this cmdlet .INPUTS Inputs to this cmdlet (if any) .OUTPUTS Output from this cmdlet (if any) .NOTES General notes .COMPONENT The component this cmdlet belongs to .ROLE The role this cmdlet belongs to .FUNCTIONALITY The functionality that best describes this cmdlet #> Function New-AMPowerShellScript { [CmdletBinding(SupportsShouldProcess = $true)] param( [Parameter(Mandatory = $true)][ValidateNotNullOrEmpty()][String]$Name, [Parameter(Mandatory = $true)][ValidateNotNullOrEmpty()][String]$Path, [Parameter(Mandatory = $true)][ValidateNotNullOrEmpty()][String]$Author, [Parameter(Mandatory = $true)][ValidateNotNullOrEmpty()][String]$CompanyName, [Parameter(Mandatory = $true)][ValidateNotNullOrEmpty()][String]$Copyright, [Parameter(Mandatory = $true)][ValidateNotNullOrEmpty()][String]$ScriptVersion, [Parameter(Mandatory = $true)][ValidateNotNullOrEmpty()][String]$Description ) Begin { } Process { if ($pscmdlet.ShouldProcess("PowerShell Script name: $Name", "New")) { $ScriptFolderPath = New-Item -Path $Path -Name $Name -ItemType Directory -Verbose $newScriptFileInfoSplat = @{ Copyright = $Copyright Description = $Description Version = $ScriptVersion CompanyName = $CompanyName Guid = [Guid]::NewGuid().Guid Author = $Author Path = "$ScriptFolderPath\Temp.ps1" } New-ScriptFileInfo @newScriptFileInfoSplat $TemplateContent = @' [CmdletBinding(SupportsShouldProcess=$true)] param ( #Not mandatory parameter example [Parameter( Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] [AllowNull()] [String]$param1, #Mandatory parameter example [Parameter( Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] [ValidateNotNullOrEmpty()] [String]$Param2 ) Begin { } Process { try { if ($pscmdlet.ShouldProcess("Target", "Operation")) { } } catch { throw } } End { } '@ (Get-Content -Path "$ScriptFolderPath\Temp.ps1").Replace("Param()",$TemplateContent) | Set-Content "$ScriptFolderPath\Temp.ps1" Get-Content -Path "$ScriptFolderPath\Temp.ps1" | ForEach-Object {$PSItem.TrimEnd()} | Set-Content "$ScriptFolderPath\$Name.ps1" Remove-Item -Path "$ScriptFolderPath\Temp.ps1" -Force $ModulePath = (Get-Module -Name AMPowerShellTemplate).path $CurrentLocation = Get-Location Push-Location -Path $ModulePath.Substring(0, $ModulePath.LastIndexOf("\")) $Parameters = Get-Content -Path .\DefaultTests.json | ConvertFrom-Json Push-Location $ScriptFolderPath $newTestScriptFileInfoSplat = @{ Copyright = $Copyright Description = $Description Version = $ScriptVersion CompanyName = $CompanyName Guid = [Guid]::NewGuid().Guid Author = $Author Path = "$ScriptFolderPath\Temp.tests.ps1" } New-ScriptFileInfo @newTestScriptFileInfoSplat (Get-Content -Path "$ScriptFolderPath\Temp.tests.ps1").Replace("Param()",$Parameters.DefaultTests.Script.Content) | Set-Content "$ScriptFolderPath\Temp.tests.ps1" Get-Content -Path "$ScriptFolderPath\Temp.tests.ps1" | ForEach-Object {$PSItem.TrimEnd()} | Set-Content "$ScriptFolderPath\$Name.tests.ps1" Remove-Item -Path "$ScriptFolderPath\temp.tests.ps1" -Force Invoke-Pester Set-Location $CurrentLocation } } End { } } Export-ModuleMember -Function New-AMPowerShellModule Export-ModuleMember -Function New-AMPowerShellScript # SIG # Begin signature block # MIIXwwYJKoZIhvcNAQcCoIIXtDCCF7ACAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUuF7lSpF4YpgDPdk4I4yytILi # VPKgghL2MIID7jCCA1egAwIBAgIQfpPr+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 # ggUlMIIEDaADAgECAhAG+v2wvXnjGcvHbHMjoqQyMA0GCSqGSIb3DQEBCwUAMHIx # CzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3 # dy5kaWdpY2VydC5jb20xMTAvBgNVBAMTKERpZ2lDZXJ0IFNIQTIgQXNzdXJlZCBJ # RCBDb2RlIFNpZ25pbmcgQ0EwHhcNMTYxMDE0MDAwMDAwWhcNMTkxMDIzMTIwMDAw # WjBiMQswCQYDVQQGEwJESzETMBEGA1UECBMKU3lkZGFubWFyazEQMA4GA1UEBxMH # S29sZGluZzEVMBMGA1UEChMMQXV0b21pemUgUC9TMRUwEwYDVQQDEwxBdXRvbWl6 # ZSBQL1MwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDD2i1LjPMTWQ/Z # IUu9hVd4zXoU0k4xoRI1hdS4T2uvNdQPIGksD0SIK86+cBqKLVe8V+Do4mkKmmc3 # OskJnetN0ebst/8/ssJBSTc9zrEjmMdwspRog0Wjnb37bJWo0/Oown86BPafFCJT # oFoTBq4rnERtHAX8W7eNky8Lv7VMzcyM7poaeh7LSRhoetd1j6WpOWlAnbzu+tis # kixhl+uViQRBMl7nAzHxAvoq+Qx9fF4WhRXP1IhL0I+xiEdFiUQBaEOGBX7H/yXc # qmK7yWux+mpCd1L+t9LjqwiG2YjamlzaRaq9xd8C/HNUX/c/mnQltsWE8GuMoTpX # oL+eEq8fAgMBAAGjggHFMIIBwTAfBgNVHSMEGDAWgBRaxLl7KgqjpepxA8Bg+S32 # ZXUOWDAdBgNVHQ4EFgQUtkZqp/lfcNEd55nXFliTnGvgwoMwDgYDVR0PAQH/BAQD # AgeAMBMGA1UdJQQMMAoGCCsGAQUFBwMDMHcGA1UdHwRwMG4wNaAzoDGGL2h0dHA6 # Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9zaGEyLWFzc3VyZWQtY3MtZzEuY3JsMDWgM6Ax # hi9odHRwOi8vY3JsNC5kaWdpY2VydC5jb20vc2hhMi1hc3N1cmVkLWNzLWcxLmNy # bDBMBgNVHSAERTBDMDcGCWCGSAGG/WwDATAqMCgGCCsGAQUFBwIBFhxodHRwczov # L3d3dy5kaWdpY2VydC5jb20vQ1BTMAgGBmeBDAEEATCBhAYIKwYBBQUHAQEEeDB2 # MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wTgYIKwYBBQUH # MAKGQmh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFNIQTJBc3N1 # cmVkSURDb2RlU2lnbmluZ0NBLmNydDAMBgNVHRMBAf8EAjAAMA0GCSqGSIb3DQEB # CwUAA4IBAQA0zGCo40Bv+7KNre6TTDWf/2k0Tzauzwy3oesHg3pd7ZgQcPTU5er3 # vLXCKQwb8bmsPw3XpL0u1CkjdiqaO6S4qv3pGbyg9qnDXeFPJhg+i5VaTGb+PMSa # +nquQtdHhxfj5VEdt6nJlG/cBPMf/cH3O7/AzngCY1KGClKhtgLphHVF15oMj2Rt # Bu/jHSqWQAZOIXg7lvNfcRDI6DHwtMXVa4pVDJJM26SsLfpdoJnVOAbWUbkzf8BX # QDDp/pG/M9mrADKmPb+dy5EnX0SWwyZd3t/cIw7+AkpXbKGv3TJLSKQMdvW+bqZ0 # /VCcF796baLjQYXi28I4pkAabr5gt2u4MIIFMDCCBBigAwIBAgIQBAkYG1/Vu2Z1 # U0O1b5VQCDANBgkqhkiG9w0BAQsFADBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMM # RGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQD # ExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwHhcNMTMxMDIyMTIwMDAwWhcN # MjgxMDIyMTIwMDAwWjByMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQg # SW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMTEwLwYDVQQDEyhEaWdpQ2Vy # dCBTSEEyIEFzc3VyZWQgSUQgQ29kZSBTaWduaW5nIENBMIIBIjANBgkqhkiG9w0B # AQEFAAOCAQ8AMIIBCgKCAQEA+NOzHH8OEa9ndwfTCzFJGc/Q+0WZsTrbRPV/5aid # 2zLXcep2nQUut4/6kkPApfmJ1DcZ17aq8JyGpdglrA55KDp+6dFn08b7KSfH03sj # lOSRI5aQd4L5oYQjZhJUM1B0sSgmuyRpwsJS8hRniolF1C2ho+mILCCVrhxKhwjf # DPXiTWAYvqrEsq5wMWYzcT6scKKrzn/pfMuSoeU7MRzP6vIK5Fe7SrXpdOYr/mzL # fnQ5Ng2Q7+S1TqSp6moKq4TzrGdOtcT3jNEgJSPrCGQ+UpbB8g8S9MWOD8Gi6CxR # 93O8vYWxYoNzQYIH5DiLanMg0A9kczyen6Yzqf0Z3yWT0QIDAQABo4IBzTCCAckw # EgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwEwYDVR0lBAwwCgYI # KwYBBQUHAwMweQYIKwYBBQUHAQEEbTBrMCQGCCsGAQUFBzABhhhodHRwOi8vb2Nz # cC5kaWdpY2VydC5jb20wQwYIKwYBBQUHMAKGN2h0dHA6Ly9jYWNlcnRzLmRpZ2lj # ZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcnQwgYEGA1UdHwR6MHgw # OqA4oDaGNGh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJ # RFJvb3RDQS5jcmwwOqA4oDaGNGh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdp # Q2VydEFzc3VyZWRJRFJvb3RDQS5jcmwwTwYDVR0gBEgwRjA4BgpghkgBhv1sAAIE # MCowKAYIKwYBBQUHAgEWHGh0dHBzOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwCgYI # YIZIAYb9bAMwHQYDVR0OBBYEFFrEuXsqCqOl6nEDwGD5LfZldQ5YMB8GA1UdIwQY # MBaAFEXroq/0ksuCMS1Ri6enIZ3zbcgPMA0GCSqGSIb3DQEBCwUAA4IBAQA+7A1a # JLPzItEVyCx8JSl2qB1dHC06GsTvMGHXfgtg/cM9D8Svi/3vKt8gVTew4fbRknUP # UbRupY5a4l4kgU4QpO4/cY5jDhNLrddfRHnzNhQGivecRk5c/5CxGwcOkRX7uq+1 # UcKNJK4kxscnKqEpKBo6cSgCPC6Ro8AlEeKcFEehemhor5unXCBc2XGxDI+7qPjF # Emifz0DLQESlE/DmZAwlCEIysjaKJAL+L3J+HNdJRZboWR3p+nRka7LrZkPas7CM # 1ekN3fYBIM6ZMWM9CBoYs4GbT8aTEAb8B4H6i9r5gkn3Ym6hU/oSlBiFLpKR6mhs # RDKyZqHnGKSaZFHvMYIENzCCBDMCAQEwgYYwcjELMAkGA1UEBhMCVVMxFTATBgNV # BAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTExMC8G # A1UEAxMoRGlnaUNlcnQgU0hBMiBBc3N1cmVkIElEIENvZGUgU2lnbmluZyBDQQIQ # Bvr9sL154xnLx2xzI6KkMjAJBgUrDgMCGgUAoHgwGAYKKwYBBAGCNwIBDDEKMAig # AoAAoQKAADAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgorBgEEAYI3AgEL # MQ4wDAYKKwYBBAGCNwIBFTAjBgkqhkiG9w0BCQQxFgQU1gr+9uRYTZ0BT2NVDUXV # cJDIa98wDQYJKoZIhvcNAQEBBQAEggEARIIDpLWyizf5bHt54Pzq2Kl2yiYMtC8x # 8kwyZ2XlBYPTw4VmVkUnq5oSMgDDFs1Q8kt8iEV3njU7OYPAOMsR7KYFZKDOk0MA # ltMOlhFMMu/OrmcFBDpVVKh0TkPB9InJPGcDQaWa+3vR6KSL+ifoHn8rLhiW7KQb # YatTys2bw0yHV2AtHH+UqFEuDjfzQrtRT4+8rHUWUx34t7hvHXg46771UQC1jRNW # D3PNmEAN0Z1exot1B5Ot9Ju486hywPa/u1OxIz+IP4g/QTnh0ijD1WO5k0JkmLGM # 3JCA21Yk+GCKYTaJ5RK6HbJvOV/Nt4u01ScgqtIkYleQ1XShvGhYI6GCAgswggIH # BgkqhkiG9w0BCQYxggH4MIIB9AIBATByMF4xCzAJBgNVBAYTAlVTMR0wGwYDVQQK # ExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEwMC4GA1UEAxMnU3ltYW50ZWMgVGltZSBT # dGFtcGluZyBTZXJ2aWNlcyBDQSAtIEcyAhAOz/Q4yP6/NW4E2GqYGxpQMAkGBSsO # AwIaBQCgXTAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEP # Fw0xODEwMjkxNzU2MDFaMCMGCSqGSIb3DQEJBDEWBBQ1bGnGWdI4SdE+VyjeSwJ5 # fgqBVzANBgkqhkiG9w0BAQEFAASCAQA/SFyRM5CLsKUHf8dZSRq5reQh3kzUEVZW # 3dTNBYLaUqSpYstFK1by39DyBZZAHVl5anolaS9vhMawUU/7QnBee1+xLylMSE2k # pSQU+KBoC9E6AZLzHuBTCrVG2lU9LfX+qpeeuaWPeCR7lWp2fzKdRDjBH6/pb2Oq # ydhGBFRT5kjKLNJZ0yyTImfdYAQw4JsGMqsMdeIjYOaVHh0nlJFlGh1w43bJv084 # RksbtmE3pQ/q/bXicnhJBSIKZxpmkddNpMQjKWcGSRsoat03znSFdm2H0+crxoqN # NdH0cVQ6eEnsrPwH70O/ONm5WF8lhds2osZ3UkbqQhkM6kbgj7+0 # SIG # End signature block |