public/New-AppVentiXPublishingTask.ps1

<#
    .SYNOPSIS
        Creates a new AppVentiX publishing task.
 
    .DESCRIPTION
        The New-AppVentiXPublishingTask function creates a new publishing task for AppVentiX. It allows you to specify various parameters such as the type of package, machine group, priority, name, version, group, path, and more. The function also checks if the package exists and if AppVentiX is licensed before creating the publishing task.
 
    .PARAMETER Type
        Specifies the type of package. Valid values are 'MSIX', 'APPV', and 'Sharedcontainer'.
 
    .PARAMETER MachineGroupFriendlyname
        Specifies the friendly name of the machine group.
 
    .PARAMETER Priority
        Specifies the priority of the publishing task. Default value is 100.
 
    .PARAMETER Group
        Specifies the group of the publishing task.
        Example: 'contoso.com\group1'
 
    .PARAMETER Path
        Specifies the path to the package file.
 
    .PARAMETER AlwaysPublish
        Indicates whether the package should always be published.
 
    .PARAMETER WhenNotExist
        Specifies the action to take when the package does not exist.
        Valid values are 'Add' and 'Skip'.
 
    .PARAMETER ForceApplicationShutdownWhenUnpublishing
        Indicates whether to force application shutdown when unpublishing.
 
    .PARAMETER PublishSeamless
        Indicates whether to publish the package seamlessly.
 
    .PARAMETER ConfigShare
        Specifies the path to the AppVentiX configuration share.
        You can ommit this parameter if Set-AppVentiXConfigShare has been called.
 
    .EXAMPLE
        New-AppVentiXPublishingTask -Type 'MSIX' -MachineGroupFriendlyname 'Group1' -Priority 50 -Name 'Task1' -Version '1.0' -Group 'Group1' -Path 'C:\Packages\Package1.msix' -AlwaysPublish -WhenNotExist 'Add' -PackageFullName 'Package1' -ForceApplicationShutdownWhenUnpublishing -PublishSeamless -Task 'Add'
 
        Creates a new publishing task with the specified parameters.
 
    .NOTES
        Function : New-AppVentiXPublishingTask
        Author : John Billekens
        Copyright: Copyright (c) AppVentiX
        Version : 1.1
#>

function New-AppVentiXPublishingTask {
    [CmdletBinding(DefaultParameterSetName = 'AVD', SupportsShouldProcess, ConfirmImpact = 'Low')]
    Param(
        [Parameter(ParameterSetName = 'AVD', Mandatory)]
        [ValidateSet('MSIX', 'APPV', 'Sharedcontainer')]
        [String]$Type,

        [Parameter(ParameterSetName = 'AVD')]
        [String]$MachineGroupFriendlyname = 'All Machine Groups',

        [Parameter(ParameterSetName = 'AVD')]
        [int]$Priority = 100,

        [Parameter(ParameterSetName = 'AVD', Mandatory)]
        [ValidatePattern('^.*\.*$')]
        [String]$Group,

        [Parameter(ParameterSetName = 'AVD', Mandatory)]
        [System.IO.FileInfo]$Path,

        [Parameter(ParameterSetName = 'AVD')]
        [Switch]$AlwaysPublish,

        [Parameter(ParameterSetName = 'AVD')]
        [ValidateSet('Add', 'Skip')]
        [String]$WhenNotExist,

        [Parameter(ParameterSetName = 'AVD')]
        [Switch]$ForceApplicationShutdownWhenUnpublishing,

        [Parameter(ParameterSetName = 'AVD')]
        [Switch]$PublishSeamless,

        [Parameter(ParameterSetName = 'AVD')]
        [String]$WVDapplicationgroup,

        [Parameter(ParameterSetName = 'AVD')]
        [Switch]$PublishInAzure,

        [Parameter(ParameterSetName = 'AVD')]
        [ValidateNotNullOrEmpty()]
        [String]$ConfigShare = $Script:AppVentix.ConfigShare

    )
    if (Test-AppVentiXIsLicensed -ConfigShare $ConfigShare) {
        if (-Not ($Path.Exists)) {
            Throw [System.Management.Automation.ItemNotFoundException] "Package not found: `"$Path`""
        }
        $publishingTasksFullname = Join-Path -Path $ConfigShare -ChildPath $Script:AppVentiX.PublishingTasksFilename
        Write-Verbose "Reading data from $($publishingTasksFullname)"
        $publishingTasksXml = New-Object -TypeName System.Xml.XmlDocument
        try {
            $publishingTasksXml.Load($publishingTasksFullname)
        } catch {
            Write-Verbose "Could not load the Publishing Tasks file, $($_.Exception.Message)"
            if (Test-Path -Path $publishingTasksFullname) {
                Write-Warning "The Publishing Tasks file exists but is not accessible!"
                Throw "The Publishing Tasks file exists but is not accessible!"
            } else {
                Write-Warning "The Publishing Tasks file does not yet exists, creating a new file!"
            }
        }
        $publishingTasksXml = Format-AppVentiXPublishingTasksXml -XmlDocument $publishingTasksXml
        if (([String]::IsNullOrEmpty($MachineGroupFriendlyname)) -or ($MachineGroupFriendlyname -like 'All Machine Groups')) {
            $MachineGroupFriendlyname = 'All Machine Groups'
            $MachineGroup = 'All'
        } else {
            try {
                $machineGroup = Get-AppVentiXMachineGroup -Name $MachineGroupFriendlyname -ConfigShare $ConfigShare
                if ($null -eq $machineGroup.FriendlyName -or $machineGroup.FriendlyName -notlike $MachineGroupFriendlyname) {
                    Throw "Machine group `"$MachineGroupFriendlyname`" not found!"
                }
            } catch {
                Throw "Machine group `"$MachineGroupFriendlyname`" not found!"
            }
            $MachineGroupFriendlyname = $machineGroup.FriendlyName
            $MachineGroup = $machineGroup.GroupName
        }
        $Action = 'Publish'
        $Id = [GUID]::NewGuid()

        $packageDetails = Get-ManifestDetail -Filename $Path
        $Name = $packageDetails.Name
        $Version = $packageDetails.Version
        $PackageFullName = $packageDetails.PackageFullName

        $ptUserPackagesElement = $publishingTasksXml.SelectSingleNode("//UserPublishingTasks/Packages")
        $ptTaskElement = $ptUserPackagesElement.AppendChild($publishingTasksXml.CreateElement("Task"))
        $null = $($ptTaskElement.AppendChild($publishingTasksXml.CreateElement("Type"))).AppendChild($publishingTasksXml.CreateTextNode($Type))
        $null = $($ptTaskElement.AppendChild($publishingTasksXml.CreateElement("MachineGroup"))).AppendChild($publishingTasksXml.CreateTextNode($MachineGroup))
        $null = $($ptTaskElement.AppendChild($publishingTasksXml.CreateElement("MachineGroupFriendlyname"))).AppendChild($publishingTasksXml.CreateTextNode($MachineGroupFriendlyname))
        $null = $($ptTaskElement.AppendChild($publishingTasksXml.CreateElement("Priority"))).AppendChild($publishingTasksXml.CreateTextNode($Priority))
        $null = $($ptTaskElement.AppendChild($publishingTasksXml.CreateElement("Id"))).AppendChild($publishingTasksXml.CreateTextNode($Id))
        $null = $($ptTaskElement.AppendChild($publishingTasksXml.CreateElement("Action"))).AppendChild($publishingTasksXml.CreateTextNode($Action))
        $null = $($ptTaskElement.AppendChild($publishingTasksXml.CreateElement("Name"))).AppendChild($publishingTasksXml.CreateTextNode($Name))
        $null = $($ptTaskElement.AppendChild($publishingTasksXml.CreateElement("Version"))).AppendChild($publishingTasksXml.CreateTextNode($Version))
        $null = $($ptTaskElement.AppendChild($publishingTasksXml.CreateElement("Group"))).AppendChild($publishingTasksXml.CreateTextNode($Group))
        try {
            $groupSID = Get-GroupSID -GroupName $Group -ErrorAction Stop
            $null = $($ptTaskElement.AppendChild($publishingTasksXml.CreateElement("ADGroupSID"))).AppendChild($publishingTasksXml.CreateTextNode($groupSID))
        } catch {
            Write-Verbose "Could not retrieve the SID for group `"$Group`", $($_.Exception.Message)"
        }
        $null = $($ptTaskElement.AppendChild($publishingTasksXml.CreateElement("Path"))).AppendChild($publishingTasksXml.CreateTextNode($Path))
        $null = $($ptTaskElement.AppendChild($publishingTasksXml.CreateElement("AlwaysPublish"))).AppendChild($publishingTasksXml.CreateTextNode($AlwaysPublish.ToString()))
        $null = $($ptTaskElement.AppendChild($publishingTasksXml.CreateElement("Whennotexist"))).AppendChild($publishingTasksXml.CreateTextNode($WhenNotExist))
        $null = $($ptTaskElement.AppendChild($publishingTasksXml.CreateElement("PackageFullName"))).AppendChild($publishingTasksXml.CreateTextNode($PackageFullName))
        $null = $($ptTaskElement.AppendChild($publishingTasksXml.CreateElement("ForceApplicationShutdownWhenUnpublishing"))).AppendChild($publishingTasksXml.CreateTextNode($ForceApplicationShutdownWhenUnpublishing.ToString()))
        $null = $($ptTaskElement.AppendChild($publishingTasksXml.CreateElement("PublishSeamless"))).AppendChild($publishingTasksXml.CreateTextNode($PublishSeamless.ToString()))
        if ($PublishSeamless) {
            $ptSeamlessElement = $ptTaskElement.AppendChild($publishingTasksXml.CreateElement("Seamless"))
            $seamlessAppCounter = 0
            $publishedApps = @()
            ForEach ($app in $packageDetails.Applications) {
                $ptSeamlessApplicationElement = $ptSeamlessElement.AppendChild($publishingTasksXml.CreateElement("SeamlessApplication"))
                $null = $($ptSeamlessApplicationElement.AppendChild($publishingTasksXml.CreateElement("SeamlessApplicationNumber"))).AppendChild($publishingTasksXml.CreateTextNode($seamlessAppCounter.ToString()))
                $null = $($ptSeamlessApplicationElement.AppendChild($publishingTasksXml.CreateElement("SeamlessApplicationExecutable"))).AppendChild($publishingTasksXml.CreateTextNode($app.AppVentiXExecutable))
                $null = $($ptSeamlessApplicationElement.AppendChild($publishingTasksXml.CreateElement("SeamlessApplicationArgument"))).AppendChild($publishingTasksXml.CreateTextNode(""))
                $null = $($ptSeamlessApplicationElement.AppendChild($publishingTasksXml.CreateElement("SeamlessApplicationFriendlyName"))).AppendChild($publishingTasksXml.CreateTextNode($app.FriendlyName))
                $null = $($ptSeamlessApplicationElement.AppendChild($publishingTasksXml.CreateElement("SeamlessApplicationIconPath"))).AppendChild($publishingTasksXml.CreateTextNode($app.IconWindowsPath))
                $null = $($ptSeamlessApplicationElement.AppendChild($publishingTasksXml.CreateElement("SeamlessApplicationRunVirtual"))).AppendChild($publishingTasksXml.CreateTextNode("False"))
                $publishedApp = @{}
                $publishedApp.Path = 'C:\Program Files\AppVentiX\AppVentiX Agent\AppVentiX Wrapper.exe'
                $publishedApp.identifier = "$($WVDapplicationgroup)/$($app.FriendlyName)"
                $publishedApp.DisplayName = $app.FriendlyName
                $publishedApp.Description = $app.Description
                $publishedApp.RequireCommandLine = $true
                $publishedApp.CommandLine = "$($Id)#$($seamlessAppCounter.ToString())"
                $publishedApp.IconPath = $app.IconWindowsPath
                $publishedApp.IconIndex = 0
                $publishedApps += $publishedApp.Clone()
                $seamlessAppCounter++
            }
            if (-Not [String]::IsNullOrEmpty($WVDapplicationgroup)) {
                $null = $($ptSeamlessElement.AppendChild($publishingTasksXml.CreateElement("SeamlessWVDapplicationgroup"))).AppendChild($publishingTasksXml.CreateTextNode($WVDapplicationgroup))
                if ($PublishInAzure) {
                    Write-Warning "PublishInAzure is not yet supported for AVD, create Application group `"$WVDapplicationgroup`" manually in Azure Portal"
                }
            }
        }
        if ($PSCmdlet.ShouldProcess("$($Script:AppVentiX.PublishingTasksFilename)")) {
            try {
                $publishingTasksXml.Save($publishingTasksFullname)
            } catch {
                Write-Warning "Could not save the file `"$($publishingTasksFullname)`"! No changes made."
            }
        }
    } else {
        Write-Warning 'AppVentiX is not licensed!'
    }
}

# SIG # Begin signature block
# MIIkmgYJKoZIhvcNAQcCoIIkizCCJIcCAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCAPae0PR1ClHiOF
# 9r1oHLVz9JjPHNseF9wxNOSY+YODMKCCHl4wggTzMIID26ADAgECAhAsJ03zZBC0
# i/247uUvWN5TMA0GCSqGSIb3DQEBCwUAMHwxCzAJBgNVBAYTAkdCMRswGQYDVQQI
# ExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcTB1NhbGZvcmQxGDAWBgNVBAoT
# D1NlY3RpZ28gTGltaXRlZDEkMCIGA1UEAxMbU2VjdGlnbyBSU0EgQ29kZSBTaWdu
# aW5nIENBMB4XDTIxMDUwNTAwMDAwMFoXDTI0MDUwNDIzNTk1OVowWzELMAkGA1UE
# BhMCTkwxEjAQBgNVBAcMCVZlbGRob3ZlbjEbMBkGA1UECgwSSm9oYW5uZXMgQmls
# bGVrZW5zMRswGQYDVQQDDBJKb2hhbm5lcyBCaWxsZWtlbnMwggEiMA0GCSqGSIb3
# DQEBAQUAA4IBDwAwggEKAoIBAQCsfgRG81keOHalHfCUgxOa1Qy4VNOnGxB8SL8e
# rjP9SfcF13McP7F1HGka5Be495pTZ+duGbaQMNozwg/5Dg9IRJEeBabeSSJJCbZo
# SNpmUu7NNRRfidQxlPC81LxTVHxJ7In0MEfCVm7rWcri28MRCAuafqOfSE+hyb1Z
# /tKyCyQ5RUq3kjs/CF+VfMHsJn6ZT63YqewRkwHuc7UogTTZKjhPJ9prGLTer8UX
# UgvsGRbvhYZXIEuy+bmx/iJ1yRl1kX4nj6gUYzlhemOnlSDD66YOrkLDhXPMXLym
# AN7h0/W5Bo//R5itgvdGBkXkWCKRASnq/9PTcoxW6mwtgU8xAgMBAAGjggGQMIIB
# jDAfBgNVHSMEGDAWgBQO4TqoUzox1Yq+wbutZxoDha00DjAdBgNVHQ4EFgQUZWMy
# gC0i1u2NZ1msk2Mm5nJm5AswDgYDVR0PAQH/BAQDAgeAMAwGA1UdEwEB/wQCMAAw
# EwYDVR0lBAwwCgYIKwYBBQUHAwMwEQYJYIZIAYb4QgEBBAQDAgQQMEoGA1UdIARD
# MEEwNQYMKwYBBAGyMQECAQMCMCUwIwYIKwYBBQUHAgEWF2h0dHBzOi8vc2VjdGln
# by5jb20vQ1BTMAgGBmeBDAEEATBDBgNVHR8EPDA6MDigNqA0hjJodHRwOi8vY3Js
# LnNlY3RpZ28uY29tL1NlY3RpZ29SU0FDb2RlU2lnbmluZ0NBLmNybDBzBggrBgEF
# BQcBAQRnMGUwPgYIKwYBBQUHMAKGMmh0dHA6Ly9jcnQuc2VjdGlnby5jb20vU2Vj
# dGlnb1JTQUNvZGVTaWduaW5nQ0EuY3J0MCMGCCsGAQUFBzABhhdodHRwOi8vb2Nz
# cC5zZWN0aWdvLmNvbTANBgkqhkiG9w0BAQsFAAOCAQEARjv9ieRocb1DXRWm3XtY
# jjuSRjlvkoPd9wS6DNfsGlSU42BFd9LCKSyRREZVu8FDq7dN0PhD4bBTT+k6AgrY
# KG6f/8yUponOdxskv850SjN2S2FeVuR20pqActMrpd1+GCylG8mj8RGjdrLQ3QuX
# qYKS68WJ39WWYdVB/8Ftajir5p6sAfwHErLhbJS6WwmYjGI/9SekossvU8mZjZwo
# Gbu+fjZhPc4PhjbEh0ABSsPMfGjQQsg5zLFjg/P+cS6hgYI7qctToo0TexGe32DY
# fFWHrHuBErW2qXEJvzSqM5OtLRD06a4lH5ZkhojhMOX9S8xDs/ArDKgX1j1Xm4Tu
# DjCCBYEwggRpoAMCAQICEDlyRDr5IrdR19NsEN0xNZUwDQYJKoZIhvcNAQEMBQAw
# ezELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
# A1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNV
# BAMMGEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczAeFw0xOTAzMTIwMDAwMDBaFw0y
# ODEyMzEyMzU5NTlaMIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMKTmV3IEplcnNl
# eTEUMBIGA1UEBxMLSmVyc2V5IENpdHkxHjAcBgNVBAoTFVRoZSBVU0VSVFJVU1Qg
# TmV0d29yazEuMCwGA1UEAxMlVVNFUlRydXN0IFJTQSBDZXJ0aWZpY2F0aW9uIEF1
# dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAIASZRc2DsPb
# CLPQrFcNdu3NJ9NMrVCDYeKqIE0JLWQJ3M6Jn8w9qez2z8Hc8dOx1ns3KBErR9o5
# xrw6GbRfpr19naNjQrZ28qk7K5H44m/Q7BYgkAk+4uh0yRi0kdRiZNt/owbxiBhq
# kCI8vP4T8IcUe/bkH47U5FHGEWdGCFHLhhRUP7wz/n5snP8WnRi9UY41pqdmyHJn
# 2yFmsdSbeAPAUDrozPDcvJ5M/q8FljUfV1q3/875PbcstvZU3cjnEjpNrkyKt1ya
# tLcgPcp/IjSufjtoZgFE5wFORlObM2D3lL5TN5BzQ/Myw1Pv26r+dE5px2uMYJPe
# xMcM3+EyrsyTO1F4lWeL7j1W/gzQaQ8bD/MlJmszbfduR/pzQ+V+DqVmsSl8MoRj
# VYnEDcGTVDAZE6zTfTen6106bDVc20HXEtqpSQvf2ICKCZNijrVmzyWIzYS4sT+k
# OQ/ZAp7rEkyVfPNrBaleFoPMuGfi6BOdzFuC00yz7Vv/3uVzrCM7LQC/NVV0CUnY
# SVgaf5I25lGSDvMmfRxNF7zJ7EMm0L9BX0CpRET0medXh55QH1dUqD79dGMvsVBl
# CeZYQi5DGky08CVHWfoEHpPUJkZKUIGy3r54t/xnFeHJV4QeD2PW6WK61l9VLupc
# xigIBCU5uA4rqfJMlxwHPw1S9e3vL4IPAgMBAAGjgfIwge8wHwYDVR0jBBgwFoAU
# oBEKIz6W8Qfs4q8p74Klf9AwpLQwHQYDVR0OBBYEFFN5v1qqK0rPVIDh2JvAnfKy
# A2bLMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MBEGA1UdIAQKMAgw
# BgYEVR0gADBDBgNVHR8EPDA6MDigNqA0hjJodHRwOi8vY3JsLmNvbW9kb2NhLmNv
# bS9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2VzLmNybDA0BggrBgEFBQcBAQQoMCYwJAYI
# KwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmNvbW9kb2NhLmNvbTANBgkqhkiG9w0BAQwF
# AAOCAQEAGIdR3HQhPZyK4Ce3M9AuzOzw5steEd4ib5t1jp5y/uTW/qofnJYt7wNK
# fq70jW9yPEM7wD/ruN9cqqnGrvL82O6je0P2hjZ8FODN9Pc//t64tIrwkZb+/UNk
# fv3M0gGhfX34GRnJQisTv1iLuqSiZgR2iJFODIkUzqJNyTKzuugUGrxx8VvwQQuY
# AAoiAxDlDLH5zZI3Ge078eQ6tvlFEyZ1r7uq7z97dzvSxAKRPRkA0xdcOds/exgN
# Rc2ThZYvXd9ZFk8/Ub3VRRg/7UqO6AZhdCMWtQ1QcydER38QXYkqa4UxFMToqWpM
# gLxqeM+4f452cpkMnf7XkQgWoaNflTCCBfUwggPdoAMCAQICEB2iSDBvmyYY0ILg
# ln0z02owDQYJKoZIhvcNAQEMBQAwgYgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpO
# ZXcgSmVyc2V5MRQwEgYDVQQHEwtKZXJzZXkgQ2l0eTEeMBwGA1UEChMVVGhlIFVT
# RVJUUlVTVCBOZXR3b3JrMS4wLAYDVQQDEyVVU0VSVHJ1c3QgUlNBIENlcnRpZmlj
# YXRpb24gQXV0aG9yaXR5MB4XDTE4MTEwMjAwMDAwMFoXDTMwMTIzMTIzNTk1OVow
# fDELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
# A1UEBxMHU2FsZm9yZDEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMSQwIgYDVQQD
# ExtTZWN0aWdvIFJTQSBDb2RlIFNpZ25pbmcgQ0EwggEiMA0GCSqGSIb3DQEBAQUA
# A4IBDwAwggEKAoIBAQCGIo0yhXoYn0nwli9jCB4t3HyfFM/jJrYlZilAhlRGdDFi
# xRDtsocnppnLlTDAVvWkdcapDlBipVGREGrgS2Ku/fD4GKyn/+4uMyD6DBmJqGx7
# rQDDYaHcaWVtH24nlteXUYam9CflfGqLlR5bYNV+1xaSnAAvaPeX7Wpyvjg7Y96P
# v25MQV0SIAhZ6DnNj9LWzwa0VwW2TqE+V2sfmLzEYtYbC43HZhtKn52BxHJAteJf
# 7wtF/6POF6YtVbC3sLxUap28jVZTxvC6eVBJLPcDuf4vZTXyIuosB69G2flGHNyM
# fHEo8/6nxhTdVZFuihEN3wYklX0Pp6F8OtqGNWHTAgMBAAGjggFkMIIBYDAfBgNV
# HSMEGDAWgBRTeb9aqitKz1SA4dibwJ3ysgNmyzAdBgNVHQ4EFgQUDuE6qFM6MdWK
# vsG7rWcaA4WtNA4wDgYDVR0PAQH/BAQDAgGGMBIGA1UdEwEB/wQIMAYBAf8CAQAw
# HQYDVR0lBBYwFAYIKwYBBQUHAwMGCCsGAQUFBwMIMBEGA1UdIAQKMAgwBgYEVR0g
# ADBQBgNVHR8ESTBHMEWgQ6BBhj9odHRwOi8vY3JsLnVzZXJ0cnVzdC5jb20vVVNF
# UlRydXN0UlNBQ2VydGlmaWNhdGlvbkF1dGhvcml0eS5jcmwwdgYIKwYBBQUHAQEE
# ajBoMD8GCCsGAQUFBzAChjNodHRwOi8vY3J0LnVzZXJ0cnVzdC5jb20vVVNFUlRy
# dXN0UlNBQWRkVHJ1c3RDQS5jcnQwJQYIKwYBBQUHMAGGGWh0dHA6Ly9vY3NwLnVz
# ZXJ0cnVzdC5jb20wDQYJKoZIhvcNAQEMBQADggIBAE1jUO1HNEphpNveaiqMm/EA
# AB4dYns61zLC9rPgY7P7YQCImhttEAcET7646ol4IusPRuzzRl5ARokS9At3Wpwq
# QTr81vTr5/cVlTPDoYMot94v5JT3hTODLUpASL+awk9KsY8k9LOBN9O3ZLCmI2pZ
# aFJCX/8E6+F0ZXkI9amT3mtxQJmWunjxucjiwwgWsatjWsgVgG10Xkp1fqW4w2y1
# z99KeYdcx0BNYzX2MNPPtQoOCwR/oEuuu6Ol0IQAkz5TXTSlADVpbL6fICUQDRn7
# UJBhvjmPeo5N9p8OHv4HURJmgyYZSJXOSsnBf/M6BZv5b9+If8AjntIeQ3pFMcGc
# TanwWbJZGehqjSkEAnd8S0vNcL46slVaeD68u28DECV3FTSK+TbMQ5Lkuk/xYpMo
# JVcp+1EZx6ElQGqEV8aynbG8HArafGd+fS7pKEwYfsR7MUFxmksp7As9V1DSyt39
# ngVR5UR43QHesXWYDVQk/fBO4+L4g71yuss9Ou7wXheSaG3IYfmm8SoKC6W59J7u
# mDIFhZ7r+YMp08Ysfb06dy6LN0KgaoLtO0qqlBCk4Q34F8W2WnkzGJLjtXX4oemO
# CiUe5B7xn1qHI/+fpFGe+zmAEc3btcSnqIBv5VPU4OOiwtJbGvoyJi1qV3AcPKRY
# LqPzW0sH3DJZ84enGm1YMIIG7DCCBNSgAwIBAgIQMA9vrN1mmHR8qUY2p3gtuTAN
# BgkqhkiG9w0BAQwFADCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJz
# ZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNU
# IE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNhdGlvbiBB
# dXRob3JpdHkwHhcNMTkwNTAyMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjB9MQswCQYD
# VQQGEwJHQjEbMBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdT
# YWxmb3JkMRgwFgYDVQQKEw9TZWN0aWdvIExpbWl0ZWQxJTAjBgNVBAMTHFNlY3Rp
# Z28gUlNBIFRpbWUgU3RhbXBpbmcgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw
# ggIKAoICAQDIGwGv2Sx+iJl9AZg/IJC9nIAhVJO5z6A+U++zWsB21hoEpc5Hg7Xr
# xMxJNMvzRWW5+adkFiYJ+9UyUnkuyWPCE5u2hj8BBZJmbyGr1XEQeYf0RirNxFrJ
# 29ddSU1yVg/cyeNTmDoqHvzOWEnTv/M5u7mkI0Ks0BXDf56iXNc48RaycNOjxN+z
# xXKsLgp3/A2UUrf8H5VzJD0BKLwPDU+zkQGObp0ndVXRFzs0IXuXAZSvf4DP0REK
# V4TJf1bgvUacgr6Unb+0ILBgfrhN9Q0/29DqhYyKVnHRLZRMyIw80xSinL0m/9NT
# IMdgaZtYClT0Bef9Maz5yIUXx7gpGaQpL0bj3duRX58/Nj4OMGcrRrc1r5a+2kxg
# zKi7nw0U1BjEMJh0giHPYla1IXMSHv2qyghYh3ekFesZVf/QOVQtJu5FGjpvzdeE
# 8NfwKMVPZIMC1Pvi3vG8Aij0bdonigbSlofe6GsO8Ft96XZpkyAcSpcsdxkrk5WY
# nJee647BeFbGRCXfBhKaBi2fA179g6JTZ8qx+o2hZMmIklnLqEbAyfKm/31X2xJ2
# +opBJNQb/HKlFKLUrUMcpEmLQTkUAx4p+hulIq6lw02C0I3aa7fb9xhAV3PwcaP7
# Sn1FNsH3jYL6uckNU4B9+rY5WDLvbxhQiddPnTO9GrWdod6VQXqngwIDAQABo4IB
# WjCCAVYwHwYDVR0jBBgwFoAUU3m/WqorSs9UgOHYm8Cd8rIDZsswHQYDVR0OBBYE
# FBqh+GEZIA/DQXdFKI7RNV8GEgRVMA4GA1UdDwEB/wQEAwIBhjASBgNVHRMBAf8E
# CDAGAQH/AgEAMBMGA1UdJQQMMAoGCCsGAQUFBwMIMBEGA1UdIAQKMAgwBgYEVR0g
# ADBQBgNVHR8ESTBHMEWgQ6BBhj9odHRwOi8vY3JsLnVzZXJ0cnVzdC5jb20vVVNF
# UlRydXN0UlNBQ2VydGlmaWNhdGlvbkF1dGhvcml0eS5jcmwwdgYIKwYBBQUHAQEE
# ajBoMD8GCCsGAQUFBzAChjNodHRwOi8vY3J0LnVzZXJ0cnVzdC5jb20vVVNFUlRy
# dXN0UlNBQWRkVHJ1c3RDQS5jcnQwJQYIKwYBBQUHMAGGGWh0dHA6Ly9vY3NwLnVz
# ZXJ0cnVzdC5jb20wDQYJKoZIhvcNAQEMBQADggIBAG1UgaUzXRbhtVOBkXXfA3oy
# Cy0lhBGysNsqfSoF9bw7J/RaoLlJWZApbGHLtVDb4n35nwDvQMOt0+LkVvlYQc/x
# QuUQff+wdB+PxlwJ+TNe6qAcJlhc87QRD9XVw+K81Vh4v0h24URnbY+wQxAPjeT5
# OGK/EwHFhaNMxcyyUzCVpNb0llYIuM1cfwGWvnJSajtCN3wWeDmTk5SbsdyybUFt
# Z83Jb5A9f0VywRsj1sJVhGbks8VmBvbz1kteraMrQoohkv6ob1olcGKBc2NeoLvY
# 3NdK0z2vgwY4Eh0khy3k/ALWPncEvAQ2ted3y5wujSMYuaPCRx3wXdahc1cFaJqn
# yTdlHb7qvNhCg0MFpYumCf/RoZSmTqo9CfUFbLfSZFrYKiLCS53xOV5M3kg9mzSW
# mglfjv33sVKRzj+J9hyhtal1H3G/W0NdZT1QgW6r8NDT/LKzH7aZlib0PHmLXGTM
# ze4nmuWgwAxyh8FuTVrTHurwROYybxzrF06Uw3hlIDsPQaof6aFBnf6xuKBlKjTg
# 3qj5PObBMLvAoGMs/FwWAKjQxH/qEZ0eBsambTJdtDgJK0kHqv3sMNrxpy/Pt/36
# 0KOE2See+wFmd7lWEOEgbsausfm2usg1XTN2jvF8IAwqd661ogKGuinutFoAsYyr
# 4/kKyVRd1LlqdJ69SK6YMIIG9TCCBN2gAwIBAgIQOUwl4XygbSeoZeI72R0i1DAN
# BgkqhkiG9w0BAQwFADB9MQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3JlYXRlciBN
# YW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRgwFgYDVQQKEw9TZWN0aWdvIExp
# bWl0ZWQxJTAjBgNVBAMTHFNlY3RpZ28gUlNBIFRpbWUgU3RhbXBpbmcgQ0EwHhcN
# MjMwNTAzMDAwMDAwWhcNMzQwODAyMjM1OTU5WjBqMQswCQYDVQQGEwJHQjETMBEG
# A1UECBMKTWFuY2hlc3RlcjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMSwwKgYD
# VQQDDCNTZWN0aWdvIFJTQSBUaW1lIFN0YW1waW5nIFNpZ25lciAjNDCCAiIwDQYJ
# KoZIhvcNAQEBBQADggIPADCCAgoCggIBAKSTKFJLzyeHdqQpHJk4wOcO1NEc7GjL
# AWTkis13sHFlgryf/Iu7u5WY+yURjlqICWYRFFiyuiJb5vYy8V0twHqiDuDgVmTt
# oeWBIHIgZEFsx8MI+vN9Xe8hmsJ+1yzDuhGYHvzTIAhCs1+/f4hYMqsws9iMepZK
# GRNcrPznq+kcFi6wsDiVSs+FUKtnAyWhuzjpD2+pWpqRKBM1uR/zPeEkyGuxmegN
# 77tN5T2MVAOR0Pwtz1UzOHoJHAfRIuBjhqe+/dKDcxIUm5pMCUa9NLzhS1B7cuBb
# /Rm7HzxqGXtuuy1EKr48TMysigSTxleGoHM2K4GX+hubfoiH2FJ5if5udzfXu1Cf
# +hglTxPyXnypsSBaKaujQod34PRMAkjdWKVTpqOg7RmWZRUpxe0zMCXmloOBmvZg
# ZpBYB4DNQnWs+7SR0MXdAUBqtqgQ7vaNereeda/TpUsYoQyfV7BeJUeRdM11EtGc
# b+ReDZvsdSbu/tP1ki9ShejaRFEqoswAyodmQ6MbAO+itZadYq0nC/IbSsnDlEI3
# iCCEqIeuw7ojcnv4VO/4ayewhfWnQ4XYKzl021p3AtGk+vXNnD3MH65R0Hts2B0t
# EUJTcXTC5TWqLVIS2SXP8NPQkUMS1zJ9mGzjd0HI/x8kVO9urcY+VXvxXIc6ZPFg
# SwVP77kv7AkTAgMBAAGjggGCMIIBfjAfBgNVHSMEGDAWgBQaofhhGSAPw0F3RSiO
# 0TVfBhIEVTAdBgNVHQ4EFgQUAw8xyJEqk71j89FdTaQ0D9KVARgwDgYDVR0PAQH/
# BAQDAgbAMAwGA1UdEwEB/wQCMAAwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwgwSgYD
# VR0gBEMwQTA1BgwrBgEEAbIxAQIBAwgwJTAjBggrBgEFBQcCARYXaHR0cHM6Ly9z
# ZWN0aWdvLmNvbS9DUFMwCAYGZ4EMAQQCMEQGA1UdHwQ9MDswOaA3oDWGM2h0dHA6
# Ly9jcmwuc2VjdGlnby5jb20vU2VjdGlnb1JTQVRpbWVTdGFtcGluZ0NBLmNybDB0
# BggrBgEFBQcBAQRoMGYwPwYIKwYBBQUHMAKGM2h0dHA6Ly9jcnQuc2VjdGlnby5j
# b20vU2VjdGlnb1JTQVRpbWVTdGFtcGluZ0NBLmNydDAjBggrBgEFBQcwAYYXaHR0
# cDovL29jc3Auc2VjdGlnby5jb20wDQYJKoZIhvcNAQEMBQADggIBAEybZVj64HnP
# 7xXDMm3eM5Hrd1ji673LSjx13n6UbcMixwSV32VpYRMM9gye9YkgXsGHxwMkysel
# 8Cbf+PgxZQ3g621RV6aMhFIIRhwqwt7y2opF87739i7Efu347Wi/elZI6WHlmjl3
# vL66kWSIdf9dhRY0J9Ipy//tLdr/vpMM7G2iDczD8W69IZEaIwBSrZfUYngqhHmo
# 1z2sIY9wwyR5OpfxDaOjW1PYqwC6WPs1gE9fKHFsGV7Cg3KQruDG2PKZ++q0kmV8
# B3w1RB2tWBhrYvvebMQKqWzTIUZw3C+NdUwjwkHQepY7w0vdzZImdHZcN6CaJJ5O
# X07Tjw/lE09ZRGVLQ2TPSPhnZ7lNv8wNsTow0KE9SK16ZeTs3+AB8LMqSjmswaT5
# qX010DJAoLEZKhghssh9BXEaSyc2quCYHIN158d+S4RDzUP7kJd2KhKsQMFwW5kK
# QPqAbZRhe8huuchnZyRcUI0BIN4H9wHU+C4RzZ2D5fjKJRxEPSflsIZHKgsbhHZ9
# e2hPjbf3E7TtoC3ucw/ZELqdmSx813UfjxDElOZ+JOWVSoiMJ9aFZh35rmR2kehI
# /shVCu0pwx/eOKbAFPsyPfipg2I2yMO+AIccq/pKQhyJA9z1XHxw2V14Tu6fXiDm
# CWp8KwijSPUV/ARP380hHHrl9Y4a1LlAMYIFkjCCBY4CAQEwgZAwfDELMAkGA1UE
# BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2Fs
# Zm9yZDEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMSQwIgYDVQQDExtTZWN0aWdv
# IFJTQSBDb2RlIFNpZ25pbmcgQ0ECECwnTfNkELSL/bju5S9Y3lMwDQYJYIZIAWUD
# BAIBBQCggYQwGAYKKwYBBAGCNwIBDDEKMAigAoAAoQKAADAZBgkqhkiG9w0BCQMx
# DAYKKwYBBAGCNwIBBDAcBgorBgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAvBgkq
# hkiG9w0BCQQxIgQg35j4FGCxJ6oDs85Jay5o96PlpJmilwPZOl3PdeJFllwwDQYJ
# KoZIhvcNAQEBBQAEggEAAlPXrt7mPUsmM1YSYBlkIaculRG3DodSc+4mXxoI4u+7
# 7IwmBbsESKNYMt5nvo/BS/KvXOFalLoq0PtGsQQQva7TDGtMCaaDv+1+NSVPZBey
# zKUDVCv1NIHj+2UqYUqBBYvJ7pmqM83Pbs61vjE8CKc95ayury+6/UxPLnSfKmbM
# 7GTi0SKEzpOkv9ETZXlWhS2uN8PdkqdkRFyJHSOz5/+wDqyILOBs+jjXRnogDdaW
# lQgWXIm/fq0pZ19Z1mYFHWCj+yujDXKT7dCD/u++n8Gmf/b+llatuFIlT1aJA/Yj
# QySwW+wEkcY2ISbvvwfrxyg7wZ59jbCrDyVC3OZJeKGCA0swggNHBgkqhkiG9w0B
# CQYxggM4MIIDNAIBATCBkTB9MQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3JlYXRl
# ciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRgwFgYDVQQKEw9TZWN0aWdv
# IExpbWl0ZWQxJTAjBgNVBAMTHFNlY3RpZ28gUlNBIFRpbWUgU3RhbXBpbmcgQ0EC
# EDlMJeF8oG0nqGXiO9kdItQwDQYJYIZIAWUDBAICBQCgeTAYBgkqhkiG9w0BCQMx
# CwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0yNDAxMjAxMDE3MTlaMD8GCSqG
# SIb3DQEJBDEyBDCMVcoOpBi6pjS2UUA4+EGXjSeE7VuZkL2lO7S7qSqezzeDGklb
# h1i8Yz0F8qjEN1YwDQYJKoZIhvcNAQEBBQAEggIAiLY2FtzNugcYkDkOeZtlVMYF
# qMbz/UQu9t7MaDNe8AlwqbVUXmD4qxKYsRJvXj/DuncSX08uxqbNYylIEXpPqfLZ
# l4b/UvGaSUcLWR2PHfZal0p1ynHwT+f0NnA3z27ysEkSY889gsmrLAQi5cRObUXL
# VfqRTlZP9EYqylnMXu4kQBk18Ous+TFYM/oo09rWetw1jamAXsft4Z2NO3ooiWTJ
# H57y6fHt7qybqgO7wV0qSKTIDXCYAGzMXpCve4ZN5nj/Qetx2Q5D0Dk+Rl22eOup
# BLlaICa4Euiadq70EXMOcRElsetoMsA3B63vKwHBoxPqsaBGY8YavPTiqbuLqK8n
# 4sRSbNUM6nLRaQShreaTELDDYB8TAPE7Ig9Rpp9e04Vyhl2zvSexMyOimI1WzttP
# VZrS15jQtELnsyG4QePY3mmEUg9/AN4M1zm/50gZLACyAcZ6TyxaZnF9VFeBS3K+
# xaId1a3idOq55sZ2nvJzIgdRTyGS06q8OR2eW7mqKe+UmY16hgys50ckeBS7Otpi
# UQ0Mq7B0u8AHe2PQG+X7O3b/VARWvD4aVp9lSVoE7um6gv5A4EgexluVYWPphom7
# L1zwCsIsX6F/LHeZqqgkhZ6cnrR2UWyOBktsXFWgJES11oFMr8L0uXTbkVtKzSLT
# GvQeHgR4sGEcYLSy0CU=
# SIG # End signature block