public/Enable-AppVentiXSeamlessPublishing.ps1

<#
    .SYNOPSIS
        Enables seamless publishing for the specified publishing task.
 
    .DESCRIPTION
        The Enable-AppVentiXSeamlessPublishing function enables seamless publishing for the specified publishing task.
 
    .PARAMETER Id
        Specifies the ID of the publishing task.
 
    .PARAMETER SubscriptionId
        Specifies the subscription ID of the Azure subscription.
 
    .PARAMETER ResourceGroupName
        Specifies the name of the resource group in which the host pool and application group are located.
 
    .PARAMETER ApplicationGroupName
        Specifies the name of the application group in which the applications are published.
 
    .PARAMETER HostPoolName
        Specifies the name of the host pool in which the applications are published.
 
    .PARAMETER AssignmentName
        Specifies the name of the Azure AD group or user that should be assigned to the application group.
 
    .PARAMETER SeamlessApps
        Specifies the applications that should be published seamlessly.
        Only the following array of objects is supported:
        @(
            [PSCustomObject]@{
                Order = '0'
                Executable = 'MSIXApp1ID#Path\To\MSIXApp1.exe'
                Argument = ''
                IconPath = 'C:\Program Files\WindowsApps\App.1.1.1.1_x64__abcdefghijkl\Assets\App1-Square44x44Logo.scale-100.png'
                FriendlyName = 'App1'
                RunVirtual = $false
            },{
                Order = '1'
                Executable = 'MSIXApp1ID#Path\To\MSIXApp2.exe'
                Argument = ''
                IconPath = 'C:\Program Files\WindowsApps\App.1.1.1.1_x64__abcdefghijkl\Assets\App2-Square44x44Logo.scale-100.png'
                FriendlyName = 'App2'
                RunVirtual = $false
            }
        )
 
    .EXAMPLE
        Enable-AppVentiXSeamlessPublishing -Id '12345678-1234-1234-1234-123456789012' -SubscriptionId '12345678-1234-1234-1234-123456789012' -ResourceGroupName 'MyResourceGroup' -ApplicationGroupName 'MyApplicationGroup' -HostPoolName 'MyHostPool'
        Enables seamless publishing for the publishing task with the specified ID for all applications available in the package.
 
    .EXAMPLE
        Enable-AppVentiXSeamlessPublishing -Id '12345678-1234-1234-1234-123456789012'
        Enables seamless publishing for the publishing task with the specified ID for all applications available in the package.
        Because no Azure parameters are provided, the function will return the parameters that should be used to publish the applications.
 
    .EXAMPLE
        Enable-AppVentiXSeamlessPublishing -Id '12345678-1234-1234-1234-123456789012' -SeamlessApps @(
            [PSCustomObject]@{
                Order = '0'
                Executable = 'MSIXApp1.exe'
                Argument = ''
                IconPath = 'C:\Program Files\WindowsApps\App.1.1.1.1_x64__abcdefghijkl\Assets\App1-Square44x44Logo.scale-100.png'
                FriendlyName = 'App1'
                RunVirtual = $false
            },{
                Order = '1'
                Executable = 'MSIXApp2.exe'
                Argument = ''
                IconPath = 'C:\Program Files\WindowsApps\App.1.1.1.1_x64__abcdefghijkl\Assets\App2-Square44x44Logo.scale-100.png'
                FriendlyName = 'App2'
                RunVirtual = $false
            }
        )
        Enables seamless publishing for the publishing task with the specified ID for the specified applications.
        Becauseno Azure parameters are provided, the function will return the parameters that should be used to publish the applications.
    .NOTES
        Function: Enable-AppVentiXSeamlessPublishing
        Author: John Billekens Consultancy
        Copyright: Copyright (c) AppVentiX
        Version: 1.3
        Requires : Valid AppVentiX license
#>

function Enable-AppVentiXSeamlessPublishing {
    [CmdletBinding(DefaultParameterSetName = 'IDAzureAll')]
    param (
        [Parameter(ParameterSetName = 'IDAzureAll', Mandatory, ValueFromPipelineByPropertyName)]
        [Parameter(ParameterSetName = 'IDAzureApps', Mandatory, ValueFromPipelineByPropertyName)]
        [String]$Id,

        [Parameter(ParameterSetName = 'IDAzureAll', Mandatory)]
        [Parameter(ParameterSetName = 'IDAzureApps', Mandatory)]
        [String]$SubscriptionId,

        [Parameter(ParameterSetName = 'IDAzureAll', Mandatory)]
        [Parameter(ParameterSetName = 'IDAzureApps', Mandatory)]
        [String]$ResourceGroupName,

        [Parameter(ParameterSetName = 'IDAzureAll', Mandatory)]
        [Parameter(ParameterSetName = 'IDAzureApps', Mandatory)]
        [Alias('ApplicationGroup')]
        [String]$ApplicationGroupName,

        [Parameter(ParameterSetName = 'IDAzureAll', Mandatory)]
        [Parameter(ParameterSetName = 'IDAzureApps', Mandatory)]
        [Alias('HostPool')]
        [String]$HostPoolName,

        [Parameter(ParameterSetName = 'IDAzureAll', Mandatory)]
        [Parameter(ParameterSetName = 'IDAzureApps', Mandatory)]
        [String]$AssignmentName,

        [Parameter(ParameterSetName = 'IDAzureAll')]
        [Switch]$RunVirtual,

        [Parameter(ParameterSetName = 'IDAzureApps', Mandatory)]
        [ValidateScript({
                $counter = 0
                $_ | Get-Member -MemberType NoteProperty | Where-Object { $_.Name -in @('Order', 'Executable', 'Argument', 'IconPath', 'FriendlyName', 'RunVirtual', 'Description') } | ForEach-Object { $counter++ }
                if ($counter -eq 7) {
                    $true
                } else {
                    Write-Verbose "Got $counter properties, expected 7 properties. $($_ | Get-Member -MemberType NoteProperty | Format-Table | Out-String)"
                    Write-Error "The SeamlessApps parameter should contain the following properties: Order, Executable, Argument, IconPath, FriendlyName, RunVirtual, Description." -ErrorAction Stop
                }
            })]
        [PSCustomObject[]]$SeamlessApps,

        [Alias('Config', 'Share', 'AppVentixConfigShare')]
        [Parameter(DontShow, ParameterSetName = 'IDAzureAll')]
        [Parameter(DontShow, ParameterSetName = 'IDAzureApps')]
        [ValidateNotNullOrEmpty()]
        [String]$ConfigShare = $Script:AppVentix.ConfigShare
    )
    Begin {
        Write-Verbose "Staring function 'Enable-AppVentiXSeamlessPublishing'"
        if (-Not (Test-AppVentiXIsLicensed -ConfigShare $ConfigShare)) {
            Write-Warning 'AppVentiX is not licensed!'
            return $null
        }
        $target = "Unknown"
        if ($PSCmdlet.ParameterSetName -in 'IDAzureApps', 'IDAzureAll') {
            $target = "Azure"
        }
        switch ($target) {
            "Azure" {
                Write-Verbose "Publishing Seamless applications to Azure."
                $PSDefaultParameterValues['*-Az*:ResourceGroupName'] = $ResourceGroupName
                $PSDefaultParameterValues['*-Az*:SubscriptionId'] = $SubscriptionId

                $azModules = @('Az.Accounts:2.17.0', 'Az.DesktopVirtualization:4.3.0', 'Az.Resources:7.4.0')
                $azModules | ForEach-Object {
                    $module, $version = $_.Split(':')
                    Write-Verbose "Importing the $module module"
                    if (-Not (Get-Module $module -ErrorAction SilentlyContinue | Where-Object { $_.Version -gt [version]"$version" })) {
                        Write-Verbose "The $module module is not yet imported, importing the $module module."
                        if (Get-Module $module -ListAvailable | Where-Object { $_.Version -ge [System.Version]"$version" }) {
                            Write-Verbose "The $module module is available and the version is higher or equal to $version, importing the $module module."
                            Import-Module $module -MinimumVersion $version -Force -ErrorAction SilentlyContinue
                        } else {
                            Write-Error "The $module module is not available or the version is lower than $version." -ErrorAction Stop
                        }
                    } else {
                        Write-Verbose "The $module module is already imported."
                    }
                }
                $attempts = 3
                $accessToken = Get-AzAccessToken -AsSecureString -ErrorAction SilentlyContinue -WarningAction SilentlyContinue
                while ($null -eq $accessToken.ExpiresOn -or $accessToken.ExpiresOn -lt (Get-Date)) {
                    if ($attempts -eq 0) {
                        Write-Error "Failed to connect to Azure." -ErrorAction Stop
                    }
                    $attempts--
                    if ($null -eq $accessToken -or $accessToken.ExpiresOn -lt (Get-Date)) {
                        Write-Host "We are not connected to Azure. Trying to connect to Azure..."
                        $subscription = Connect-AzAccount -Subscription $SubscriptionId -ErrorAction SilentlyContinue
                        $accessToken = Get-AzAccessToken -AsSecureString -ErrorAction SilentlyContinue
                    } else {
                        continue
                    }
                }
                $subscription = Set-AzContext -Subscription $SubscriptionId -ErrorAction SilentlyContinue
                Write-Verbose "We are connected to Azure ($($subscription.Subscription.Name)). Connection expires on '$($accessToken.ExpiresOn.DateTime.ToLocalTime().ToString())'"
            }
            "Citrix" {
                Write-Verbose "Publishing Seamless applications to Citrix."
            }
            "Unknown" {
                Write-Warning "The publishing target is not (yet) supported. Parameters will be provided as output."
            }
        }
    }
    Process {
        Write-Verbose "Processing the publishing task with ID '$Id'."
        $appsToPublish = @()
        switch ($target) {
            "Azure" {
                try {
                    $azHostPool = Get-AzWvdHostPool -Name $HostPoolName -ErrorAction SilentlyContinue
                    if ($null -eq $azHostPool -or $azHostPool.name -ne $HostPoolName) {
                        Write-Error "The host pool '$HostPoolName' could not be found in the resource group '$ResourceGroupName' in the subscription '$SubscriptionId'." -ErrorAction Stop
                    } else {
                        Write-Verbose "The host pool '$HostPoolName' is found in the resource group '$ResourceGroupName' in the subscription '$SubscriptionId'."
                    }

                    $azApplicationGroup = Get-AzWvdApplicationGroup -Name $ApplicationGroupName -ErrorAction SilentlyContinue
                    if ($null -eq $azApplicationGroup) {
                        Write-Verbose "The application group '$ApplicationGroupName' does not (yet) exist in the resource group '$ResourceGroupName', we need to create the application group '$ApplicationGroupName'."
                        $azApplicationGroup = New-AzWvdApplicationGroup -Name $ApplicationGroupName -ApplicationGroupType 'RemoteApp' -Location $azHostPool.Location -HostPoolArmPath $azHostPool.Id -ErrorAction Stop
                        Write-Verbose "The application group '$ApplicationGroupName' is created."
                    } elseif ($azApplicationGroup.ApplicationGroupType -notlike "RemoteApp") {
                        Write-Error "The application group '$ApplicationGroupName' already exists in the resource group '$ResourceGroupName', but it is not a RemoteApp application group." -ErrorAction Stop
                    } else {
                        Write-Verbose "The application group '$ApplicationGroupName' is found in the resource group '$ResourceGroupName'."
                    }
                    if ([String]::IsNullOrEmpty($AssignmentName)) {
                        Write-Verbose "No AAD Assignment name specified, skipping AAD assignment"
                    } else {
                        Write-Verbose "Checking if the AAD Group $($AssignmentName) exists"
                        $azADGroup = Get-AzADGroup -DisplayName "$($AssignmentName)" -ErrorAction SilentlyContinue
                        if ([String]::IsNullOrEmpty($azADGroup)) {
                            Write-Verbose "First attempt didn't got any results, trying again."
                            $azADGroup = Get-AzADGroup -Filter "MailNickname eq '$AssignmentName'"
                        }
                        Write-Verbose "Checking if the AAD User ($($AssignmentName)) exists"
                        $azADUser = Get-AzADUser -DisplayName "$($AssignmentName)" -ErrorAction SilentlyContinue
                        if ($null -eq $azADGroup -and $null -eq $azADUser) {
                            Write-Error "The AAD Group or User '$AssignmentName' could not be found in the Azure AD." -ErrorAction Stop
                        } elseif ($null -ne $azADGroup -and $null -ne $azADUser) {
                            Write-Error "Multiple objects found with the name '$AssignmentName' in the Azure AD." -ErrorAction Stop
                        } elseif ($azADGroup.Count -gt 1 -or $azADUser.Count -gt 1) {
                            Write-Error "Multiple objects found with the name '$AssignmentName' in the Azure AD." -ErrorAction Stop
                        } elseif ($null -ne $azADGroup) {
                            Write-Verbose "The AAD Group '$AssignmentName' is found in the Azure AD (DisplayName: $($azADGroup.DisplayName))."
                            $azAADObjID = $azADGroup.Id
                        } elseif ($null -ne $azADUser) {
                            Write-Verbose "The AAD User '$AssignmentName' is found in the Azure AD (DisplayName: $($azADUser.DisplayName))."
                            $azAADObjID = $azADUser.Id
                        }
                        Write-Verbose "Continue with Object ID: $azAADObjID"

                        Write-Verbose "Checking if the AAD Group is assigned to the Application Group."
                        $azAGRoleAssignment = Get-AzRoleAssignment -ResourceName $ApplicationGroupName -ResourceType "Microsoft.DesktopVirtualization/applicationGroups" -RoleDefinitionName "Desktop Virtualization User" -ErrorAction SilentlyContinue
                        if ($null -eq $azAGRoleAssignment -or $azAADObjID -notin $azAGRoleAssignment.ObjectId) {
                            Write-Verbose "There is no AAD Group assigned to the Application Group, we need to assign the AAD Group to the Application Group."
                            $azAGRoleAssignment = New-AzRoleAssignment -ObjectId $azAADObjID -RoleDefinitionName "Desktop Virtualization User" -ResourceName $ApplicationGroupName -ResourceType 'Microsoft.DesktopVirtualization/applicationGroups' -ErrorAction STOP
                        } else {
                            Write-Verbose "The AAD Group is already assigned to the Application Group."
                        }
                    }

                    Write-Verbose "Checking if there are applications in the application group '$ApplicationGroupName'."
                    $azApplications = Get-AzWvdApplication -GroupName $azApplicationGroup.Name -ErrorAction SilentlyContinue

                    $azApplications | ForEach-Object {
                        $group, $name = $_.name.Split('/')
                        Write-Verbose "Removing application '$name' from application group '$group'."
                        Remove-AzWvdApplication -GroupName $group -Name $name
                    }
                } catch {
                    Write-Error $_.Exception.Message -ErrorAction Stop
                }
            }
            "Unknown" {
                Write-Verbose "Nothing to do, target is not (yet) supported."
            }
        }

        $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-Error "The Publishing Tasks file exists but is not accessible!" -ErrorAction Stop
            } else {
                Write-Error "The Publishing Tasks file does not yet exists!" -ErrorAction Stop
            }
        }
        $publishingTasksXml = Format-AppVentiXPublishingTasksXml -XmlDocument $publishingTasksXml

        $ptTaskElement = $publishingTasksXml.SelectSingleNode("//Task[Id='$($Id)']")

        $SeamlessAppsToAdd = @()
        if ($PSCmdlet.ParameterSetName -in 'IDAzureAll') {
            Write-Verbose "Using the provided ID parameter, retrieving the applications from the manifest."
            $packageDetails = Get-ManifestDetail -Filename $ptTaskElement.Path
            $counter = 0
            $SeamlessAppsToAdd = @()
            ForEach ($app in $packageDetails.Applications) {
                Write-Debug "Processing application: $($app | Format-List | Out-String)"
                $SeamlessApp = [PSCustomObject]@{
                    Order        = $counter
                    Executable   = '{0}#{1}' -f $app.Id, $app.Executable
                    Argument     = ""
                    IconPath     = $app.IconWindowsPath
                    FriendlyName = $app.FriendlyName
                    RunVirtual   = ([bool]$RunVirtual).ToString()
                    Description  = $app.Description
                }
                Write-Debug "Adding app: $($SeamlessApp | Format-List | Out-String)"
                $SeamlessAppsToAdd += $SeamlessApp
                $counter++
            }
        }
        if ($PSCmdlet.ParameterSetName -in 'IDAzureApps') {
            Write-Verbose "Using the provided SeamlessApps parameter, with the following applications:"
            $SeamlessApps | ForEach-Object {
                Write-Debug "Processing application: $($_ | Format-List | Out-String)"
                $SeamlessApp = [PSCustomObject]@{
                    Order        = $_.Order
                    Executable   = $_.Executable
                    Argument     = $_.Argument
                    IconPath     = $_.IconPath
                    FriendlyName = $_.FriendlyName
                    RunVirtual   = $_.RunVirtual.ToString()
                    Description  = $_.Description
                }
                Write-Debug "Adding app: $($SeamlessApp | Format-List | Out-String)"
                $SeamlessAppsToAdd += $SeamlessApp
            }
        }

        Write-Verbose "Retrieving Task element"

        Write-Verbose "Checking if Seamless element exists, if not create it."
        if ($null -eq $ptTaskElement.Seamless) {
            Write-Verbose "Does not exist, adding Seamless element"
            $ptSeamlessElement = $ptTaskElement.AppendChild($publishingTasksXml.CreateElement("Seamless"))
        } else {
            Write-Verbose "Exists, retrieving Seamless element"
            $ptSeamlessElement = $ptTaskElement.SelectSingleNode("Seamless")
        }

        ForEach ($app in $SeamlessAppsToAdd) {
            if ($taskApp = $ptSeamlessElement.SeamlessApplication | Where-Object { $_.SeamlessApplicationNumber -like $app.Order.ToString() }) {
                Write-Verbose "Updating SeamlessApplication element for `"$($app.FriendlyName)`" / `"$($app.Description)`""
                $taskApp.SeamlessApplicationExecutable = $app.Executable
                $taskApp.SeamlessApplicationArgument = $app.Argument
                $taskApp.SeamlessApplicationFriendlyName = $app.FriendlyName
                $taskApp.SeamlessApplicationIconPath = $app.IconPath
                $taskApp.SeamlessApplicationRunVirtual = $app.RunVirtual.ToString()
            } else {
                Write-Verbose "Adding SeamlessApplication element"
                $ptSeamlessApplicationElement = $ptSeamlessElement.AppendChild($publishingTasksXml.CreateElement("SeamlessApplication"))
                Write-Verbose "Settting ApplicationNumber to `"$($app.Order)`""
                $null = $($ptSeamlessApplicationElement.AppendChild($publishingTasksXml.CreateElement("SeamlessApplicationNumber"))).AppendChild($publishingTasksXml.CreateTextNode($app.Order.ToString()))
                Write-Verbose "Settting ApplicationExecutable to `"$($app.Executable)`""
                $null = $($ptSeamlessApplicationElement.AppendChild($publishingTasksXml.CreateElement("SeamlessApplicationExecutable"))).AppendChild($publishingTasksXml.CreateTextNode($app.Executable))
                Write-Verbose "Settting ApplicationArgument to `"$($app.Argument)`""
                $null = $($ptSeamlessApplicationElement.AppendChild($publishingTasksXml.CreateElement("SeamlessApplicationArgument"))).AppendChild($publishingTasksXml.CreateTextNode($app.Argument))
                if ($ptTaskElement.Type -like 'APPV') {
                    Write-Verbose "Package type is APPV, setting FriendlyName and IconPath to empty string"
                    $seamlessApplicationFriendlyName = ''
                    $seamlessApplicationIconPath = ''
                } elseif ($ptTaskElement.Type -like 'MSIX') {
                    Write-Verbose "Package type is MSIX, setting FriendlyName and IconPath to the values from the manifest"
                    $seamlessApplicationFriendlyName = $app.FriendlyName
                    $seamlessApplicationIconPath = $app.IconPath
                }
                Write-Verbose "Settting ApplicationFriendlyName to `"$($seamlessApplicationFriendlyName)`""
                $null = $($ptSeamlessApplicationElement.AppendChild($publishingTasksXml.CreateElement("SeamlessApplicationFriendlyName"))).AppendChild($publishingTasksXml.CreateTextNode($seamlessApplicationFriendlyName))
                Write-Verbose "Settting ApplicationIconPath to `"$($seamlessApplicationIconPath)`""
                $null = $($ptSeamlessApplicationElement.AppendChild($publishingTasksXml.CreateElement("SeamlessApplicationIconPath"))).AppendChild($publishingTasksXml.CreateTextNode($seamlessApplicationIconPath))
                Write-Verbose "Settting ApplicationRunVirtual to `"$($app.RunVirtual)`""
                $null = $($ptSeamlessApplicationElement.AppendChild($publishingTasksXml.CreateElement("SeamlessApplicationRunVirtual"))).AppendChild($publishingTasksXml.CreateTextNode($app.RunVirtual))
            }
            switch ($target) {
                "Azure" {
                    $appsToPublish += @{
                        GroupName           = $ApplicationGroupName
                        Name                = $app.FriendlyName
                        ResourceGroupName   = $ResourceGroupName
                        FilePath            = $Script:Appventix.PublishingExeFilepath
                        CommandLineArgument = $('{0}#{1}' -f $Id, $app.Order.ToString())
                        SubscriptionId      = $SubscriptionId
                        Description         = $app.Description
                        IconIndex           = 0
                        IconPath            = $app.IconPath
                        CommandLineSetting  = 'Require'
                        FriendlyName        = $app.FriendlyName
                        ShowInPortal        = $true
                    }
                }
                "Unknown" {
                    $appsToPublish += [PSCustomObject]@{
                        PackageName = $ptTaskElement.Name
                        Name        = $app.SeamlessApplicationFriendlyName
                        Program     = $Script:AppVentix.PublishingExeFilepath
                        Parameter   = '{0}#{1}' -f $ID, $app.SeamlessApplicationNumber
                        IconPath    = $app.SeamlessApplicationIconPath
                    }
                }
            }
        }
        Write-Verbose "Adding the Application Group to the Seamless element."
        if ($null -eq $ptSeamlessElement.SeamlessWVDapplicationgroup) {
            Write-Verbose "Does not exist, adding SeamlessWVDapplicationgroup element"
            $null = $($ptSeamlessElement.AppendChild($publishingTasksXml.CreateElement("SeamlessWVDapplicationgroup"))).AppendChild($publishingTasksXml.CreateTextNode($ApplicationGroupName))
        } else {
            Write-Verbose "Updating SeamlessWVDapplicationgroup element"
            $ptSeamlessElement.SeamlessWVDapplicationgroup = $ApplicationGroupName
        }

        Write-Verbose "Adding the SubscriptionID to the Seamless element."
        if ($null -eq $ptSeamlessElement.SeamlessWVDsubscriptionID) {
            Write-Verbose "Does not exist, adding SeamlessWVDsubscriptionID element"
            $null = $($ptSeamlessElement.AppendChild($publishingTasksXml.CreateElement("SeamlessWVDsubscriptionID"))).AppendChild($publishingTasksXml.CreateTextNode($SubscriptionId))
        } else {
            Write-Verbose "Updating SeamlessWVDsubscriptionID element"
            $ptSeamlessElement.SeamlessWVDsubscriptionID = $SubscriptionId
        }

        Write-Verbose "Adding the SubscriptionName to the Seamless element."
        if ($null -eq $ptSeamlessElement.SeamlessWVDsubscriptionName) {
            Write-Verbose "Does not exist, adding SeamlessWVDsubscriptionName element"
            $null = $($ptSeamlessElement.AppendChild($publishingTasksXml.CreateElement("SeamlessWVDsubscriptionName"))).AppendChild($publishingTasksXml.CreateTextNode($subscription.Subscription.Name))
        } else {
            Write-Verbose "Updating SeamlessWVDsubscriptionName element"
            $ptSeamlessElement.SeamlessWVDsubscriptionName = $subscription.Subscription.Name
        }

        Write-Verbose "Adding the ResourceGroupName to the Seamless element."
        if ($null -eq $ptSeamlessElement.SeamlessWVDresourcegroup) {
            Write-Verbose "Does not exist, adding SeamlessWVDresourcegroup element"
            $null = $($ptSeamlessElement.AppendChild($publishingTasksXml.CreateElement("SeamlessWVDresourcegroup"))).AppendChild($publishingTasksXml.CreateTextNode($ResourceGroupName))
        } else {
            Write-Verbose "Updating SeamlessWVDresourcegroup element"
            $ptSeamlessElement.SeamlessWVDresourcegroup = $ResourceGroupName
        }

        Write-Verbose "Enable seamless publishing for the publishing task."
        if ($null -eq $ptTaskElement.PublishSeamless) {
            Write-Verbose "Does not exist, adding PublishSeamless element"
            $null = $($ptTaskElement.AppendChild($publishingTasksXml.CreateElement("PublishSeamless"))).AppendChild($publishingTasksXml.CreateTextNode("True"))
        } else {
            Write-Verbose "Updating SeamlessApplication element"
            $ptTaskElement.PublishSeamless = "True"
        }

        Write-Verbose "Save the Publishing Tasks file."
        try {
            $publishingTasksXml.Save($publishingTasksFullname)
        } catch {
            Write-Error "Could not save the Publishing Tasks file, $($_.Exception.Message)" -ErrorAction Stop
        }
        switch ($target) {
            "Azure" {
                Write-Verbose "Save the Azure Application Group to the Publishing Tasks file."
                if (-Not $ptSeamlessElement.SeamlessWVDapplicationgroup) {
                    $null = $($ptSeamlessElement.AppendChild($publishingTasksXml.CreateElement("SeamlessWVDapplicationgroup"))).AppendChild($publishingTasksXml.CreateTextNode($ApplicationGroupName))
                }
                ForEach ($param in $appsToPublish) {
                    Write-Verbose "Publishing application '$($param.Name)' in application group '$($param.GroupName)'."
                    $null = New-AzWvdApplication @param -ErrorAction Stop
                }
            }
            "Unknown" {
                ForEach ($param in $appsToPublish) {
                    Write-Output $param
                }
            }
        }
    }
    End {
        Write-Verbose "Cleaning up variables"
        Clear-Variable -Name ptTaskElement -ErrorAction SilentlyContinue
        Clear-Variable -Name ptSeamlessElement -ErrorAction SilentlyContinue
        Clear-Variable -Name ptSeamlessApplicationElement -ErrorAction SilentlyContinue
        Write-Verbose "Ending function 'Enable-AppVentiXSeamlessPublishing'"
    }
}

# SIG # Begin signature block
# MIIndQYJKoZIhvcNAQcCoIInZjCCJ2ICAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBXEtbyFcDQIqNj
# AreYAh//kvl4pfP8azDj6lB39QhagqCCICkwggXJMIIEsaADAgECAhAbtY8lKt8j
# AEkoya49fu0nMA0GCSqGSIb3DQEBDAUAMH4xCzAJBgNVBAYTAlBMMSIwIAYDVQQK
# ExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2Vy
# dGlmaWNhdGlvbiBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBUcnVzdGVkIE5l
# dHdvcmsgQ0EwHhcNMjEwNTMxMDY0MzA2WhcNMjkwOTE3MDY0MzA2WjCBgDELMAkG
# A1UEBhMCUEwxIjAgBgNVBAoTGVVuaXpldG8gVGVjaG5vbG9naWVzIFMuQS4xJzAl
# BgNVBAsTHkNlcnR1bSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIGA1UEAxMb
# Q2VydHVtIFRydXN0ZWQgTmV0d29yayBDQSAyMIICIjANBgkqhkiG9w0BAQEFAAOC
# Ag8AMIICCgKCAgEAvfl4+ObVgAxknYYblmRnPyI6HnUBfe/7XGeMycxca6mR5rlC
# 5SBLm9qbe7mZXdmbgEvXhEArJ9PoujC7Pgkap0mV7ytAJMKXx6fumyXvqAoAl4Va
# qp3cKcniNQfrcE1K1sGzVrihQTib0fsxf4/gX+GxPw+OFklg1waNGPmqJhCrKtPQ
# 0WeNG0a+RzDVLnLRxWPa52N5RH5LYySJhi40PylMUosqp8DikSiJucBb+R3Z5yet
# /5oCl8HGUJKbAiy9qbk0WQq/hEr/3/6zn+vZnuCYI+yma3cWKtvMrTscpIfcRnNe
# GWJoRVfkkIJCu0LW8GHgwaM9ZqNd9BjuiMmNF0UpmTJ1AjHuKSbIawLmtWJFfzcV
# WiNoidQ+3k4nsPBADLxNF8tNorMe0AZa3faTz1d1mfX6hhpneLO/lv403L3nUlbl
# s+V1e9dBkQXcXWnjlQ1DufyDljmVe2yAWk8TcsbXfSl6RLpSpCrVQUYJIP4ioLZb
# MI28iQzV13D4h1L92u+sUS4Hs07+0AnacO+Y+lbmbdu1V0vc5SwlFcieLnhO+Nqc
# noYsylfzGuXIkosagpZ6w7xQEmnYDlpGizrrJvojybawgb5CAKT41v4wLsfSRvbl
# jnX98sy50IdbzAYQYLuDNbdeZ95H7JlI8aShFf6tjGKOOVVPORa5sWOd/7cCAwEA
# AaOCAT4wggE6MA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFLahVDkCw6A/joq8
# +tT4HKbROg79MB8GA1UdIwQYMBaAFAh2zcsH/yT2xc3tu5C84oQ3RnX3MA4GA1Ud
# DwEB/wQEAwIBBjAvBgNVHR8EKDAmMCSgIqAghh5odHRwOi8vY3JsLmNlcnR1bS5w
# bC9jdG5jYS5jcmwwawYIKwYBBQUHAQEEXzBdMCgGCCsGAQUFBzABhhxodHRwOi8v
# c3ViY2Eub2NzcC1jZXJ0dW0uY29tMDEGCCsGAQUFBzAChiVodHRwOi8vcmVwb3Np
# dG9yeS5jZXJ0dW0ucGwvY3RuY2EuY2VyMDkGA1UdIAQyMDAwLgYEVR0gADAmMCQG
# CCsGAQUFBwIBFhhodHRwOi8vd3d3LmNlcnR1bS5wbC9DUFMwDQYJKoZIhvcNAQEM
# BQADggEBAFHCoVgWIhCL/IYx1MIy01z4S6Ivaj5N+KsIHu3V6PrnCA3st8YeDrJ1
# BXqxC/rXdGoABh+kzqrya33YEcARCNQOTWHFOqj6seHjmOriY/1B9ZN9DbxdkjuR
# mmW60F9MvkyNaAMQFtXx0ASKhTP5N+dbLiZpQjy6zbzUeulNndrnQ/tjUoCFBMQl
# lVXwfqefAcVbKPjgzoZwpic7Ofs4LphTZSJ1Ldf23SIikZbr3WjtP6MZl9M7JYjs
# NhI9qX7OAo0FmpKnJ25FspxihjcNpDOO16hO0EoXQ0zF8ads0h5YbBRRfopUofbv
# n3l6XYGaFpAP4bvxSgD5+d2+7arszgowggZFMIIELaADAgECAhAIMk+dt9qRb2Pk
# 8qM8Xl1RMA0GCSqGSIb3DQEBCwUAMFYxCzAJBgNVBAYTAlBMMSEwHwYDVQQKExhB
# c3NlY28gRGF0YSBTeXN0ZW1zIFMuQS4xJDAiBgNVBAMTG0NlcnR1bSBDb2RlIFNp
# Z25pbmcgMjAyMSBDQTAeFw0yNDA0MDQxNDA0MjRaFw0yNzA0MDQxNDA0MjNaMGsx
# CzAJBgNVBAYTAk5MMRIwEAYDVQQHDAlTY2hpam5kZWwxIzAhBgNVBAoMGkpvaG4g
# QmlsbGVrZW5zIENvbnN1bHRhbmN5MSMwIQYDVQQDDBpKb2huIEJpbGxla2VucyBD
# b25zdWx0YW5jeTCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBAMslntDb
# SQwHZXwFhmibivbnd0Qfn6sqe/6fos3pKzKxEsR907RkDMet2x6RRg3eJkiIr3TF
# PwqBooyXXgK3zxxpyhGOcuIqyM9J28DVf4kUyZHsjGO/8HFjrr3K1hABNUszP0o7
# H3o6J31eqV1UmCXYhQlNoW9FOmRC1amlquBmh7w4EKYEytqdmdOBavAD5Xq4vLPx
# NP6kyA+B2YTtk/xM27TghtbwFGKnu9Vwnm7dFcpLxans4ONt2OxDQOMA5NwgcUv/
# YTpjhq9qoz6ivG55NRJGNvUXsM3w2o7dR6Xh4MuEGrTSrOWGg2A5EcLH1XqQtkF5
# cZnAPM8W/9HUp8ggornWnFVQ9/6Mga+ermy5wy5XrmQpN+x3u6tit7xlHk1Hc+4X
# Y4a4ie3BPXG2PhJhmZAn4ebNSBwNHh8z7WTT9X9OFERepGSytZVeEP7hgyptSLcu
# hpwWeR4QdBb7dV++4p3PsAUQVHFpwkSbrRTv4EiJ0Lcz9P1HPGFoHiFAQQIDAQAB
# o4IBeDCCAXQwDAYDVR0TAQH/BAIwADA9BgNVHR8ENjA0MDKgMKAuhixodHRwOi8v
# Y2NzY2EyMDIxLmNybC5jZXJ0dW0ucGwvY2NzY2EyMDIxLmNybDBzBggrBgEFBQcB
# AQRnMGUwLAYIKwYBBQUHMAGGIGh0dHA6Ly9jY3NjYTIwMjEub2NzcC1jZXJ0dW0u
# Y29tMDUGCCsGAQUFBzAChilodHRwOi8vcmVwb3NpdG9yeS5jZXJ0dW0ucGwvY2Nz
# Y2EyMDIxLmNlcjAfBgNVHSMEGDAWgBTddF1MANt7n6B0yrFu9zzAMsBwzTAdBgNV
# HQ4EFgQUO6KtBpOBgmrlANVAnyiQC6W6lJwwSwYDVR0gBEQwQjAIBgZngQwBBAEw
# NgYLKoRoAYb2dwIFAQQwJzAlBggrBgEFBQcCARYZaHR0cHM6Ly93d3cuY2VydHVt
# LnBsL0NQUzATBgNVHSUEDDAKBggrBgEFBQcDAzAOBgNVHQ8BAf8EBAMCB4AwDQYJ
# KoZIhvcNAQELBQADggIBAEQsN8wgPMdWVkwHPPTN+jKpdns5AKVFjcn00psf2NGV
# VgWWNQBIQc9lEuTBWb54IK6Ga3hxQRZfnPNo5HGl73YLmFgdFQrFzZ1lnaMdIcyh
# 8LTWv6+XNWfoyCM9wCp4zMIDPOs8LKSMQqA/wRgqiACWnOS4a6fyd5GUIAm4Cuap
# tpFYr90l4Dn/wAdXOdY32UhgzmSuxpUbhD8gVJUaBNVmQaRqeU8y49MxiVrUKJXd
# e1BCrtR9awXbqembc7Nqvmi60tYKlD27hlpKtj6eGPjkht0hHEsgzU0Fxw7ZJghY
# G2wXfpF2ziN893ak9Mi/1dmCNmorGOnybKYfT6ff6YTCDDNkod4egcMZdOSv+/Qv
# +HAeIgEvrxE9QsGlzTwbRtbm6gwYYcVBs/SsVUdBn/TSB35MMxRhHE5iC3aUTkDb
# ceo/XP3uFhVL4g2JZHpFfCSu2TQrrzRn2sn07jfMvzeHArCOJgBW1gPqR3WrJ4hU
# xL06Rbg1gs9tU5HGGz9KNQMfQFQ70Wz7UIhezGcFcRfkIfSkMmQYYpsc7rfzj+z0
# ThfDVzzJr2dMOFsMlfj1T6l22GBq9XQx0A4lcc5Fl9pRxbOuHHWFqIBD/BCEhwni
# OCySzqENd2N+oz8znKooSISStnkNaYXt6xblJF2dx9Dn89FK7d1IquNxOwt0tI5d
# MIIGlTCCBH2gAwIBAgIQCcXM+LtmfXE3qsFZgAbLMTANBgkqhkiG9w0BAQwFADBW
# MQswCQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBTLkEu
# MSQwIgYDVQQDExtDZXJ0dW0gVGltZXN0YW1waW5nIDIwMjEgQ0EwHhcNMjMxMTAy
# MDgzMjIzWhcNMzQxMDMwMDgzMjIzWjBQMQswCQYDVQQGEwJQTDEhMB8GA1UECgwY
# QXNzZWNvIERhdGEgU3lzdGVtcyBTLkEuMR4wHAYDVQQDDBVDZXJ0dW0gVGltZXN0
# YW1wIDIwMjMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC5Frrqxud9
# kjaqgkAo85Iyt6ecN343OWPztNOFkORvsc6ukhucOOQQ+szxH0jsi3ARjBwG1b9o
# QwnDx1COOkOpwm2HzY2zxtJe2X2qC+H8DMt4+nUNAYFuMEMjReq5ptDTI3JidDEb
# gcxKdr2azfCwmJ3FpqGpKr1LbtCD2Y7iLrwZOxODkdVYKEyJL0UPJ2A18JgNR54+
# CZ0/pVfCfbOEZag65oyU3A33ZY88h5mhzn9WIPF/qLR5qt9HKe9u8Y+uMgz8MKQa
# gH/ajWG/uYcqeQK28AS3Eh5AcSwl4xFfwHGaFwExxBWSXLZRGUbn9aFdirSZKKde
# 20p1COlmZkxImJY+bxQYSgw5nEM0jPg6rePD+0IQQc4APK6dSHAOQS3QvBJrfzTW
# lCQokGtOvxcNIs5cOvaANmTcGcLgkH0eHgMBpLFlcyzE0QkY8Heh+xltZFEiAvK5
# gbn8CHs8oo9o0/JjLqdWYLrW4HnES43/NC1/sOaCVmtslTaFoW/WRRbtJaRrK/03
# jFjrN921dCntRRinB/Ew3MQ1kxPN604WCMeLvAOpT3F5KbBXoPDrMoW9OGTYnYqv
# 88A6hTbVFRs+Ei8UJjk4IlfOknHWduimRKQ4LYDY1GDSA33YUZ/c3Pootanc2iWP
# Navjy/ieDYIdH8XVbRfWqchnDpTE+0NFcwIDAQABo4IBYzCCAV8wDAYDVR0TAQH/
# BAIwADAdBgNVHQ4EFgQUx2k8Lua941lH/xkSwdk06EHP448wHwYDVR0jBBgwFoAU
# vlQCL79AbHNDzqwJJU6eQ0Qa7uAwDgYDVR0PAQH/BAQDAgeAMBYGA1UdJQEB/wQM
# MAoGCCsGAQUFBwMIMDMGA1UdHwQsMCowKKAmoCSGImh0dHA6Ly9jcmwuY2VydHVt
# LnBsL2N0c2NhMjAyMS5jcmwwbwYIKwYBBQUHAQEEYzBhMCgGCCsGAQUFBzABhhxo
# dHRwOi8vc3ViY2Eub2NzcC1jZXJ0dW0uY29tMDUGCCsGAQUFBzAChilodHRwOi8v
# cmVwb3NpdG9yeS5jZXJ0dW0ucGwvY3RzY2EyMDIxLmNlcjBBBgNVHSAEOjA4MDYG
# CyqEaAGG9ncCBQELMCcwJQYIKwYBBQUHAgEWGWh0dHBzOi8vd3d3LmNlcnR1bS5w
# bC9DUFMwDQYJKoZIhvcNAQEMBQADggIBAHjd7rE6Q+b32Ws4vTJeC0HcGDi7mfQU
# nbaJ9nFFOQpizPX+YIpHuK89TPkOdDF7lOEmTZzVQpw0kwpIZDuB8lSM0Gw9KloO
# vXIsGjF/KgTNxYM5aViQNMtoIiF6W9ysmubDHF7lExSToPd1r+N0zYGXlE1uEX4o
# 988K/Z7kwgE/GC649S1OEZ5IGSGmirtcruLX/xhjIDA5S/cVfz0We/ElHamHs+Uf
# W3/IxTigvvq4JCbdZHg9DsjkW+UgGGAVtkxB7qinmWJamvdwpgujAwOT1ym/giPT
# W5C8/MnkL18ZgVQ38sqKqFdqUS+ZIVeXKfV58HaWtV2Lip1Y0luL7Mswb856jz7z
# XINk79H4XfbWOryf7AtWBjrus28jmHWK3gXNhj2StVcOI48Dc6CFfXDMo/c/E/ab
# 217kTYhiht2rCWeGS5THQ3bZVx+lUPLaDe3kVXjYvxMYQKWu04QX6+vURFSeL3WV
# rUSO6nEnZu7X2EYci5MUmmUdEEiAVZO/03yLlNWUNGX72/949vU+5ZN9r9EGdp7X
# 3W7mLL1Tx4gLmHnrB97O+e9RYK6370MC52siufu11p3n8OG5s2zJw2J6LpD+HLby
# CgfRId9Q5UKgsj0A1QuoBut8FI6YdaH3sR1ponEv6GsNYrTyBtSR77csUWLUCyVb
# osF3+ae0+SofMIIGuTCCBKGgAwIBAgIRAJmjgAomVTtlq9xuhKaz6jkwDQYJKoZI
# hvcNAQEMBQAwgYAxCzAJBgNVBAYTAlBMMSIwIAYDVQQKExlVbml6ZXRvIFRlY2hu
# b2xvZ2llcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRo
# b3JpdHkxJDAiBgNVBAMTG0NlcnR1bSBUcnVzdGVkIE5ldHdvcmsgQ0EgMjAeFw0y
# MTA1MTkwNTMyMThaFw0zNjA1MTgwNTMyMThaMFYxCzAJBgNVBAYTAlBMMSEwHwYD
# VQQKExhBc3NlY28gRGF0YSBTeXN0ZW1zIFMuQS4xJDAiBgNVBAMTG0NlcnR1bSBD
# b2RlIFNpZ25pbmcgMjAyMSBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
# ggIBAJ0jzwQwIzvBRiznM3M+Y116dbq+XE26vest+L7k5n5TeJkgH4Cyk74IL9uP
# 61olRsxsU/WBAElTMNQI/HsE0uCJ3VPLO1UufnY0qDHG7yCnJOvoSNbIbMpT+Cci
# 75scCx7UsKK1fcJo4TXetu4du2vEXa09Tx/bndCBfp47zJNsamzUyD7J1rcNxOw5
# g6FJg0ImIv7nCeNn3B6gZG28WAwe0mDqLrvU49chyKIc7gvCjan3GH+2eP4mYJAS
# flBTQ3HOs6JGdriSMVoD1lzBJobtYDF4L/GhlLEXWgrVQ9m0pW37KuwYqpY42grp
# /kSYE4BUQrbLgBMNKRvfhQPskDfZ/5GbTCyvlqPN+0OEDmYGKlVkOMenDO/xtMrM
# INRJS5SY+jWCi8PRHAVxO0xdx8m2bWL4/ZQ1dp0/JhUpHEpABMc3eKax8GI1F03m
# SJVV6o/nmmKqDE6TK34eTAgDiBuZJzeEPyR7rq30yOVw2DvetlmWssewAhX+cnSa
# aBKMEj9O2GgYkPJ16Q5Da1APYO6n/6wpCm1qUOW6Ln1J6tVImDyAB5Xs3+Jriasa
# iJ7P5KpXeiVV/HIsW3ej85A6cGaOEpQA2gotiUqZSkoQUjQ9+hPxDVb/Lqz0tMjp
# 6RuLSKARsVQgETwoNQZ8jCeKwSQHDkpwFndfCceZ/OfCUqjxAgMBAAGjggFVMIIB
# UTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTddF1MANt7n6B0yrFu9zzAMsBw
# zTAfBgNVHSMEGDAWgBS2oVQ5AsOgP46KvPrU+Bym0ToO/TAOBgNVHQ8BAf8EBAMC
# AQYwEwYDVR0lBAwwCgYIKwYBBQUHAwMwMAYDVR0fBCkwJzAloCOgIYYfaHR0cDov
# L2NybC5jZXJ0dW0ucGwvY3RuY2EyLmNybDBsBggrBgEFBQcBAQRgMF4wKAYIKwYB
# BQUHMAGGHGh0dHA6Ly9zdWJjYS5vY3NwLWNlcnR1bS5jb20wMgYIKwYBBQUHMAKG
# Jmh0dHA6Ly9yZXBvc2l0b3J5LmNlcnR1bS5wbC9jdG5jYTIuY2VyMDkGA1UdIAQy
# MDAwLgYEVR0gADAmMCQGCCsGAQUFBwIBFhhodHRwOi8vd3d3LmNlcnR1bS5wbC9D
# UFMwDQYJKoZIhvcNAQEMBQADggIBAHWIWA/lj1AomlOfEOxD/PQ7bcmahmJ9l0Q4
# SZC+j/v09CD2csX8Yl7pmJQETIMEcy0VErSZePdC/eAvSxhd7488x/Cat4ke+AUZ
# ZDtfCd8yHZgikGuS8mePCHyAiU2VSXgoQ1MrkMuqxg8S1FALDtHqnizYS1bIMOv8
# znyJjZQESp9RT+6NH024/IqTRsRwSLrYkbFq4VjNn/KV3Xd8dpmyQiirZdrONoPS
# lCRxCIi54vQcqKiFLpeBm5S0IoDtLoIe21kSw5tAnWPazS6sgN2oXvFpcVVpMcq0
# C4x/CLSNe0XckmmGsl9z4UUguAJtf+5gE8GVsEg/ge3jHGTYaZ/MyfujE8hOmKBA
# UkVa7NMxRSB1EdPFpNIpEn/pSHuSL+kWN/2xQBJaDFPr1AX0qLgkXmcEi6PFnaw5
# T17UdIInA58rTu3mefNuzUtse4AgYmxEmJDodf8NbVcU6VdjWtz0e58WFZT7tST6
# EWQmx/OoHPelE77lojq7lpsjhDCzhhp4kfsfszxf9g2hoCtltXhCX6NqsqwTT7xe
# 8LgMkH4hVy8L1h2pqGLT2aNCx7h/F95/QvsTeGGjY7dssMzq/rSshFQKLZ8lPb8h
# FTmiGDJNyHga5hZ59IGynk08mHhBFM/0MLeBzlAQq1utNjQprztZ5vv/NJy8ua9A
# GbwkMWkOMIIGuTCCBKGgAwIBAgIRAOf/acc7Nc5LkSbYdHxopYcwDQYJKoZIhvcN
# AQEMBQAwgYAxCzAJBgNVBAYTAlBMMSIwIAYDVQQKExlVbml6ZXRvIFRlY2hub2xv
# Z2llcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3Jp
# dHkxJDAiBgNVBAMTG0NlcnR1bSBUcnVzdGVkIE5ldHdvcmsgQ0EgMjAeFw0yMTA1
# MTkwNTMyMDdaFw0zNjA1MTgwNTMyMDdaMFYxCzAJBgNVBAYTAlBMMSEwHwYDVQQK
# ExhBc3NlY28gRGF0YSBTeXN0ZW1zIFMuQS4xJDAiBgNVBAMTG0NlcnR1bSBUaW1l
# c3RhbXBpbmcgMjAyMSBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB
# AOkSHwQ17bldesWmlUG+imV/TnfRbSV102aO2/hhKH9/t4NAoVoipzu0ePujH67y
# 8iwlmWuhqRR4xLeLdPxolEL55CzgUXQaq+Qzr5Zk7ySbNl/GZloFiYwuzwWS2AVg
# LPLCZd5DV8QTF+V57Y6lsdWTrrl5dEeMfsxhkjM2eOXabwfLy6UH2ZHzAv9bS/Sm
# Mo1PobSx+vHWST7c4aiwVRvvJY2dWRYpTipLEu/XqQnqhUngFJtnjExqTokt4Hyz
# Osr2/AYOm8YOcoJQxgvc26+LAfXHiBkbQkBdTfHak4DP3UlYolICZHL+XSzSXlsR
# gqiWD4MypWGU4A13xiHmaRBZowS8FET+QAbMiqBaHDM3Y6wohW07yZ/mw9ZKu/Km
# VIAEBhrXesxifPB+DTyeWNkeCGq4IlgJr/Ecr1px6/1QPtj66yvXl3uauzPPGEXU
# k6vUym6nZyE1IGXI45uGVI7XqvCt99WuD9LNop9Kd1LmzBGGvxucOo0lj1M3IRi8
# FimAX3krunSDguC5HgD75nWcUgdZVjm/R81VmaDPEP25Wj+C1reicY5CPckLGBjH
# QqsJe7jJz1CJXBMUtZs10cVKMEK3n/xD2ku5GFWhx0K6eFwe50xLUIZD9GfT7s/5
# /MyBZ1Ep8Q6H+GMuudDwF0mJitk3G8g6EzZprfMQMc3DAgMBAAGjggFVMIIBUTAP
# BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBS+VAIvv0Bsc0POrAklTp5DRBru4DAf
# BgNVHSMEGDAWgBS2oVQ5AsOgP46KvPrU+Bym0ToO/TAOBgNVHQ8BAf8EBAMCAQYw
# EwYDVR0lBAwwCgYIKwYBBQUHAwgwMAYDVR0fBCkwJzAloCOgIYYfaHR0cDovL2Ny
# bC5jZXJ0dW0ucGwvY3RuY2EyLmNybDBsBggrBgEFBQcBAQRgMF4wKAYIKwYBBQUH
# MAGGHGh0dHA6Ly9zdWJjYS5vY3NwLWNlcnR1bS5jb20wMgYIKwYBBQUHMAKGJmh0
# dHA6Ly9yZXBvc2l0b3J5LmNlcnR1bS5wbC9jdG5jYTIuY2VyMDkGA1UdIAQyMDAw
# LgYEVR0gADAmMCQGCCsGAQUFBwIBFhhodHRwOi8vd3d3LmNlcnR1bS5wbC9DUFMw
# DQYJKoZIhvcNAQEMBQADggIBALiTWXfJTBX9lAcIoKd6oCzwQZOfARQkt0OmiQ39
# 0yEqMrStHmpfycggfPGlBHdMDDYhHDVTGyvY+WIbdsIWpJ1BNRt9pOrpXe8HMR5s
# Ou71AWOqUqfEIXaHWOEs0UWmVs8mJb4lKclOHV8oSoR0p3GCX2tVO+XF8Qnt7E6f
# bkwZt3/AY/C5KYzFElU7TCeqBLuSagmM0X3Op56EVIMM/xlWRaDgRna0hLQze5mY
# HJGv7UuTCOO3wC1bzeZWdlPJOw5v4U1/AljsNLgWZaGRFuBwdF62t6hOKs86v+jP
# IMqFPwxNJN/ou22DqzpP+7TyYNbDocrThlEN9D2xvvtBXyYqA7jhYY/fW9edUqhZ
# UmkUGM++Mvz9lyT/nBdfaKqM5otK0U5H8hCSL4SGfjOVyBWbbZlUIE8X6XycDBRR
# KEK0q5JTsaZksoKabFAyRKJYgtObwS1UPoDGcmGirwSeGMQTJSh+WR5EXZaEWJVA
# 6ZZPBlGvjgjFYaQ0kLq1OitbmuXZmX7Z70ks9h/elK0A8wOg8oiNVd3o1bb59ms1
# QF4OjZ45rkWfsGuz8ctB9/leCuKzkx5Rt1WAOsXy7E7pws+9k+jrePrZKw2DnmlN
# aT19QgX2I+hFtvhC6uOhj/CgjVEA4q1i1OJzpoAmre7zdEg+kZcFIkrDHgokA5mc
# IMK1MYIGojCCBp4CAQEwajBWMQswCQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNv
# IERhdGEgU3lzdGVtcyBTLkEuMSQwIgYDVQQDExtDZXJ0dW0gQ29kZSBTaWduaW5n
# IDIwMjEgQ0ECEAgyT5232pFvY+TyozxeXVEwDQYJYIZIAWUDBAIBBQCggYQwGAYK
# KwYBBAGCNwIBDDEKMAigAoAAoQKAADAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIB
# BDAcBgorBgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAvBgkqhkiG9w0BCQQxIgQg
# YDSu+FrVIUFsrgIebdOd0rixPCv/9bJOXFduOmm/fWUwDQYJKoZIhvcNAQEBBQAE
# ggGApz01Jty1fpLBBZnjBB1NHCNk0glgpXkehTcUaOTNRE70st1vPDnimcDSiimo
# GBNS0VD7kmcjZVPmROpaetkkQlTKvrK2mHD6nowe3WLUbtNr48m9BAQSilgsUUZO
# XBHsC8VepWQv+OXgkYEJr1DoNFJ9quABbKGFE0jiiMyVTQzr5+4WVp/P3sjtBhUp
# vRLYTj9wJHH7JH+CciER/SJ6WT8b1b2bd9UT4yciV9lv48jngMPepNVRTbV9Yy2d
# 33GWl8qCJXzCn5LApkU+p3ucWTGKBgsqjVhViuuhYaLg3pYQaWPGB483C66KtvEi
# YNleySZlvEPkHiwJ4Sh9mQtIVI7o3UMokPweIDDiF3vbdqX8IzQNkNNSdj1v4Zuq
# PXTYe85OJzZ//73l2mU+DfvwvNE7mjdTGT+x/vZn1kUxLFlnEQAiBeC9FkBRNy6r
# sFIG5iznV+xbjgwzABZtNvSR2RopjohIIJdpYHtZQa/jTFcj2fJQLqcadsjzyC5k
# W8kYoYIEAjCCA/4GCSqGSIb3DQEJBjGCA+8wggPrAgEBMGowVjELMAkGA1UEBhMC
# UEwxITAfBgNVBAoTGEFzc2VjbyBEYXRhIFN5c3RlbXMgUy5BLjEkMCIGA1UEAxMb
# Q2VydHVtIFRpbWVzdGFtcGluZyAyMDIxIENBAhAJxcz4u2Z9cTeqwVmABssxMA0G
# CWCGSAFlAwQCAgUAoIIBVjAaBgkqhkiG9w0BCQMxDQYLKoZIhvcNAQkQAQQwHAYJ
# KoZIhvcNAQkFMQ8XDTI0MDkyNzE5MDcxM1owNwYLKoZIhvcNAQkQAi8xKDAmMCQw
# IgQg6pVLsdBAtDFASNhln49hXYh0LMzgZ5LgVgJNSwA60xwwPwYJKoZIhvcNAQkE
# MTIEMOIB8plBe83zbhQfW5UJAJBNlst7GnHZewoUTBufH5wnsEGMnos3o0ZbveRA
# /8AnNDCBnwYLKoZIhvcNAQkQAgwxgY8wgYwwgYkwgYYEFA9PuFUe/9j23n9nJrQ8
# E9Bqped3MG4wWqRYMFYxCzAJBgNVBAYTAlBMMSEwHwYDVQQKExhBc3NlY28gRGF0
# YSBTeXN0ZW1zIFMuQS4xJDAiBgNVBAMTG0NlcnR1bSBUaW1lc3RhbXBpbmcgMjAy
# MSBDQQIQCcXM+LtmfXE3qsFZgAbLMTANBgkqhkiG9w0BAQEFAASCAgCBcGO05TGi
# 8iBH/38R2VAUaI1NgcIRhd50mqwPVRq/MWMdejyUCepkm037Gy90cPQAga1uqjrz
# y9NbLzKlV5sv+UVWc5VUByS4p4us/WVdvxvjmzGbPcnGpb4vHFWIbrCq2xo1YvlU
# exGSgCPmu5QlEpnPuOdk4CTz8EOYaBdXMQ+KxEg/9f6CYvhcwGoOYxZ+sXdoJlfH
# yORTJ9xMxqVISD1VvGsK52cxTeZ7oIIeQUyFQhKjV3RJwFotpF02VgGB3beb3oAH
# eNXlHncyw4cu2ierjx9xUb+0DChqMPMxdOSj4mGcspo82F5Ne4ikb7EVCwn4s42h
# WSgHsbz13kustxm0Tt16qjmp50goZY/hEQbHaAzuATs12QbjL860mN1qx0v45ud1
# EuAOwUr36ko5UMKDZpX5GN3O6YDnmJ+F0MVbYt1Zm6QHwpyetNI4e7o2X8lPrT/Z
# JIOAgKY+eJjnpejN4WJSU7IcWMitXp4E+czGQ5z1SrD0N+q9zTTYDDJ1hLr6fyCC
# xj9nNf84sGp+W7KL9MxYzINGu/HACe3JZRBoM8b3tud7/U0nR7nQWOHuHp1Obv/x
# Drw/uovGHlgyd8Kejd5gs/safbIdlsJnOR1h72X8oZlFJXJhxpDENkZP1sPh0BJB
# MzIUnQhVZqZM8OD2mO7koStHtkzoEOOKXA==
# SIG # End signature block