# Note: AosEnvironmentUtilities imports CommonRollbackUtilities. Using -Force to import a nested module, which
# exports a specific list of functions, will remove any already imported functions from being available to the caller.
Import-Module "$PSScriptRoot\AosEnvironmentUtilities.psm1" -DisableNameChecking

$global:logfile = ""
$AosWebsiteName = Get-AosWebSiteName
$BatchService = "DynamicsAxBatch"
$PrintService = "DynamicsAXPrintService"

$configEncryptor = "Microsoft.Dynamics.AX.Framework.ConfigEncryptor.exe"

$ErrorActionPreference = "Stop"

function Initialize-Log([string]$log)
{
    if (Test-Path -Path $log)
    {
        Write-Output "Removing the existing log file '$log'."
        Remove-Item -Path $log -Force | Out-Null
    }

    Write-Output "Creating the log file '$log'."
    New-Item -Path $log -ItemType File -Force | Out-Null
    $global:logfile = $log
}

function Write-Log([string]$message)
{
    $datetime = Get-Date -Format "MM-dd-yyyy:HH:mm:ss"
    Add-Content -Path $global:logfile -Value "$datetime`: $message" | Out-Null
    Write-Output "$datetime`: $message"
}

function Log-Error([string]$error, [switch]$throw)
{
    Write-Error $error
    if ($throw)
    {
        throw $error
    }
}

function Create-Backup([string]$webroot, [string]$backupdir)
{
    $orig_webconfig = Join-Path -Path $webroot -ChildPath "web.config"
    $orig_wifconfig = Join-Path -Path $webroot -ChildPath "wif.config"
    $orig_wifservicesconfig = Join-Path -Path $webroot -ChildPath "wif.services.config"

    $backup_webconfig = Join-Path -Path $backupdir -ChildPath "web.config.backup"
    $backup_wifconfig = Join-Path -Path $backupdir -ChildPath "wif.config.backup"
    $backup_wifservicesconfig = Join-Path -Path $backupdir -ChildPath "wif.services.config.backup"

    Copy-Item -Path $orig_webconfig -Destination $backup_webconfig -Force | Out-Null
    Write-Log "Copied '$orig_webconfig' to '$backup_webconfig."

    Copy-Item -Path $orig_wifconfig -Destination $backup_wifconfig -Force | Out-Null
    Write-Log "Copied '$orig_wifconfig' to '$backup_wifconfig'."

    Copy-Item -Path $orig_wifservicesconfig -Destination $backup_wifservicesconfig -Force | Out-Null
    Write-Log "Copied '$orig_wifservicesconfig' to '$backup_wifservicesconfig'."
}

# This is the main entry point to control what is upgraded.
function Upgrade-Web-Config([string]$webroot, [int]$platformVersion)
{
    $script:PlatformReleaseVersion = $platformVersion
    Decrypt-Config -webroot:$webroot
    $webconfig = Join-Path -Path $webroot -ChildPath "Web.config"
    $batchconfig = Join-Path -Path $webroot -ChildPath "bin\Batch.exe.config"
    $wifconfig = Join-Path -Path $webroot -ChildPath "Wif.config"

    Upgrade-HttpProtocol-NewNames -webconfig:$webconfig
    Upgrade-WebConfig-NewKeys -webconfig:$webconfig
    Upgrade-WebConfig-DeleteKeys -webconfig:$webconfig
    Upgrade-WebConfig-updateKeys -webconfig:$webconfig
    Upgrade-WebConfig-Add-DependentAssemblies -webconfig:$webconfig
    Upgrade-WebConfig-Update-DependentAssemblyBinding -webconfig:$webconfig
    Upgrade-WebConfig-AssemblyReferences -webconfig:$webconfig
    Upgrade-WebConfig-rootLocations -webconfig:$webconfig
    Upgrade-WebConfig-rootLocationsWithSecurity -webconfig:$webconfig
    Upgrade-WebConfig-rootLocations-PCFControls -webconfig:$webconfig
    Upgrade-WebConfig-rootLocations-ReliableCommunicationManager -webconfig:$webconfig
    Upgrade-WebConfig-rootLocations-TelemetryManager -webconfig:$webconfig
    Upgrade-WebConfig-rootLocationsWithSecurity-byName -webconfig:$webconfig -locationname "api"
    Upgrade-WebConfig-rootLocationsWithSecurity-byName -webconfig:$webconfig -locationname "data"
    Upgrade-WebConfig-rootLocationsWithSecurity-byName -webconfig:$webconfig -locationname "metadata"
    Upgrade-WebConfig-rootLocationsWithSecurity-byName -webconfig:$webconfig -locationname "FederationMetadata"
    Upgrade-WebConfig-rootLocationsWithSecurity-byName -webconfig:$webconfig -locationname "services"
    Upgrade-WebConfig-rootLocationsWithSecurity-byName -webconfig:$webconfig -locationname "soap"
    Upgrade-WebConfig-rootLocationsWithSecurity-byName -webconfig:$webconfig -locationname "FileManagement"
    Upgrade-WebConfig-rootLocationsWithSecurity-byName -webconfig:$webconfig -locationname "Services/SessionManager.svc"    
    Upgrade-WebConfig-rootLocationsWithSecurity-byName -webconfig:$webconfig -locationname "apps"
    Upgrade-WebConfig-rootLocationsWithSecurity-byName -webconfig:$webconfig -locationname "debug"
    Upgrade-WebConfig-rootLocationsWithSecurity-byName -webconfig:$webconfig -locationname "Resources/Scripts"
    Upgrade-WebConfig-rootLocationsWithSecurity-byName -webconfig:$webconfig -locationname "punchout"
    Upgrade-WebConfig-rootLocationsWithSecurity-byName -webconfig:$webconfig -locationname "DynamicsAx/Services/DispatchService.svc"
    Upgrade-WebConfig-rootLocationsWithSecurity-byName -webconfig:$webconfig -locationname "DynamicsAx/Services/DispatchServiceWebHttp.svc"
    Upgrade-WebConfig-RemoveAssemblies -webConfig:$webconfig
    Upgrade-WebConfig-RemoveWcfActivityLog -webConfig:$webconfig
    Upgrade-WebConfig-Add-LcsEnvironmentId -webConfig:$webconfig
    Upgrade-WebConfig-ExcludeIdentityModelFromInheritance -webConfig:$webconfig
    Upgrade-WebConfig-debugCompilation -webConfig:$webconfig
    Upgrade-WebConfig-targetFrameworkCompilation -webConfig:$webconfig
    Upgrade-WebConfig-Add-StaticContent -webConfig:$webconfig
    Upgrade-WebConfig-Add-RequestHandlers -webConfig:$webconfig
    Upgrade-WebConfig-Add-RequestFilteringFileExtensions -webConfig:$webconfig
    Upgrade-WebConfig-Add-SecurityrequestFilteringVerbsElements -webConfig:$webconfig
    Upgrade-WebConfig-Update-LogoutModule -webConfig:$webconfig
    Upgrade-WebConfig-Update-SecureCookieHttpModule -webConfig:$webconfig

    if (Test-Path -Path $batchconfig)
    {
        Upgrade-BatchConfig-Add-DependentAssemblies -batchconfig:$batchconfig
    }

    Upgrade-WifConfig-Add-CustomTokenHandler -wifconfig:$wifconfig

    Encrypt-Config -webroot:$webroot
}

function Add-DependencyAssembly([System.Xml.XmlDocument] $xmlDoc, [string] $assemblyName, [string] $publickey, [string] $oldVersion, [string] $newVersion, [string] $culture)
{
    $ns = New-Object System.Xml.XmlNamespaceManager($xmlDoc.NameTable)
    $ns.AddNamespace("ab", "urn:schemas-microsoft-com:asm.v1")

    $DependencyNode = $xmlDoc.SelectSingleNode("/configuration/runtime/ab:assemblyBinding", $ns)

    [System.Xml.XmlElement] $dependencyElement = $xmlDoc.CreateElement("dependentAssembly", "urn:schemas-microsoft-com:asm.v1")
    [System.Xml.XmlElement] $assemblyElement = $xmlDoc.CreateElement("assemblyIdentity", "urn:schemas-microsoft-com:asm.v1")


    $nameAttribute = $xmlDoc.CreateAttribute('name')
    $nameAttribute.Value = $assemblyName

    $publicKeyAttribute = $xmlDoc.CreateAttribute('publicKeyToken')
    $publicKeyAttribute.Value = $publickey

    $assemblyElement.Attributes.Append($nameAttribute)
    $assemblyElement.Attributes.Append($publicKeyAttribute)

    #This attribute is optional so only add the attribute if a value is passed in for culture
    if (!([String]::IsNullOrWhiteSpace($culture)))
    {
        $cultureAttribute = $xmlDoc.CreateAttribute('culture')
        $cultureAttribute.Value = $culture
        $assemblyElement.Attributes.Append($cultureAttribute)
    }

    $dependencyElement.AppendChild($assemblyElement)

    #This element is optional so only add the node if a value is passed in for old
    if (!([String]::IsNullOrWhiteSpace($oldVersion)))
    {
        [System.Xml.XmlElement] $bindingElement = $xmlDoc.CreateElement("bindingRedirect", "urn:schemas-microsoft-com:asm.v1")
        $oldVersionAttribute = $xmlDoc.CreateAttribute('oldVersion')
        $oldVersionAttribute.Value = $oldVersion

        $newVersionAttribute = $xmlDoc.CreateAttribute('newVersion')
        $newVersionAttribute.Value = $newVersion

        $bindingElement.Attributes.Append($oldVersionAttribute)
        $bindingElement.Attributes.Append($newVersionAttribute)
        $dependencyElement.AppendChild($bindingElement)
    }

    $DependencyNode.AppendChild($dependencyElement)
}

function Update-DependentAssemblyBinding([System.Xml.XmlDocument] $xmlDoc, [string] $assemblyName, [string] $oldVersion, [string] $newVersion)
{
    $ns = New-Object System.Xml.XmlNamespaceManager($xmlDoc.NameTable)
    $ns.AddNamespace("ab", "urn:schemas-microsoft-com:asm.v1")

    if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
    {
        $bindingNode = $xmlDoc.SelectSingleNode("/configuration/runtime/ab:assemblyBinding/ab:dependentAssembly/ab:bindingRedirect[../ab:assemblyIdentity[@name='$assemblyName']]", $ns)
        $bindingNode.oldVersion = $oldVersion
        $bindingNode.newVersion = $newVersion
    }
}

function Remove-DependentAssemblyBinding([System.Xml.XmlDocument] $xmlDoc, [string] $assemblyName)
{
    $ns = New-Object System.Xml.XmlNamespaceManager($xmlDoc.NameTable)
    $ns.AddNamespace("ab", "urn:schemas-microsoft-com:asm.v1")

    if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
    {
        $bindingNode = $xmlDoc.SelectSingleNode("/configuration/runtime/ab:assemblyBinding/ab:dependentAssembly/ab:bindingRedirect[../ab:assemblyIdentity[@name='$assemblyName']]", $ns)
        $NodetoRemove = $bindingNode.ParentNode
        $NodetoRemove.ParentNode.RemoveChild($NodetoRemove)
    }
}

function Upgrade-WebConfig-Update-DependentAssemblyBinding([string] $webConfig)
{
    [System.Xml.XmlDocument] $xmlDoc = New-Object System.Xml.XmlDocument
    $xmlDoc.Load($webconfig)

    $owinVersion = '3.0.1.0'
    $owinBinding = '0.0.0.0-3.0.1.0'

    # Check if update 42 or later
    if ($PlatformReleaseVersion -ge 5968)
    {
        # Check if update 56 or later
        if ($PlatformReleaseVersion -ge 6730)
        {
           $owinVersion = '4.2.2.0'
           $owinBinding = '0.0.0.0-4.2.2.0'
        }
        elseif ($PlatformReleaseVersion -ge 6192)
        {
           $owinVersion = '4.1.1.0'
           $owinBinding = '0.0.0.0-4.1.1.0'
        }
        else
        {
          $owinVersion = '3.1.0.0'
          $owinBinding = '0.0.0.0-3.1.0.0'
        }
    }

    Update-DependentAssemblyBinding -xmlDoc:$xmlDoc -assemblyName:'Microsoft.Owin' -oldVersion:$owinBinding -newVersion:$owinVersion
    Update-DependentAssemblyBinding -xmlDoc:$xmlDoc -assemblyName:'Microsoft.Owin.Security' -oldVersion:$owinBinding -newVersion:$owinVersion

	# Check if update 43 or later
    if ($PlatformReleaseVersion -ge 6009)
	{
		Update-DependentAssemblyBinding -xmlDoc:$xmlDoc -assemblyName:'Microsoft.Data.Services.Client' -oldVersion:'5.6.0.0-5.8.4.0' -newVersion:'5.8.4.0'
		Update-DependentAssemblyBinding -xmlDoc:$xmlDoc -assemblyName:'Microsoft.Data.OData' -oldVersion:'0.0.0.0-5.8.4.0' -newVersion:'5.8.4.0'
		Update-DependentAssemblyBinding -xmlDoc:$xmlDoc -assemblyName:'Microsoft.Data.Edm' -oldVersion:'5.6.0.0-5.8.4.0' -newVersion:'5.8.4.0'
	}

    # Check if update 48 or later
    if ($PlatformReleaseVersion -ge 6232)
	{
        # remove duplicate entry of Microsoft.OData.Edm
        $assemblyName = 'Microsoft.OData.Edm'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }

        if (!(Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc))
        {
            Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-6.19.0.11114' -newVersion:'6.19.0.11114'
        }
        else
        {
		    Update-DependentAssemblyBinding -xmlDoc:$xmlDoc -assemblyName:$assemblyName -oldVersion:'0.0.0.0-6.19.0.11114' -newVersion:'6.19.0.11114'
        }

		Update-DependentAssemblyBinding -xmlDoc:$xmlDoc -assemblyName:'Microsoft.OData.Core' -oldVersion:'0.0.0.0-6.19.0.11114' -newVersion:'6.19.0.11114'
		Update-DependentAssemblyBinding -xmlDoc:$xmlDoc -assemblyName:'Microsoft.Spatial' -oldVersion:'0.0.0.0-6.19.0.11114' -newVersion:'6.19.0.11114'
	}

    # Check if update 57 or later
    if ($PlatformReleaseVersion -ge 6825)
	{
        # Add redirect of Microsoft.WindowsAzure.Storage
        $assemblyName = 'Microsoft.WindowsAzure.Storage'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }

        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-9.3.2.0' -newVersion:'9.3.2.0'
	}

    # check if update 58 or later
    if ($PlatformReleaseVersion -ge 6931)
	{
        # Add redirect of System.Security.Cryptography.Cng
        $assemblyName = 'System.Security.Cryptography.Cng'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }

        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'b03f5f7f11d50a3a' -oldVersion:'0.0.0.0-4.3.3.0' -newVersion:'4.3.3.0'

        # Add Owin redirects
        $assemblyName = 'Microsoft.Owin'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-4.2.2.0' -newVersion:'4.2.2.0'
        
        $assemblyName = 'Microsoft.Owin.Security'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-4.2.2.0' -newVersion:'4.2.2.0'

        #Add redirect for System.IdentityModel.Tokens.Jwt
        $assemblyName = 'System.IdentityModel.Tokens.Jwt'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
    }

    # check if update 60 or later
    if ($PlatformReleaseVersion -ge 6974)
    {
        # Add redirect of Microsoft.OData.Core
        $assemblyName = 'Microsoft.OData.Core'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-6.19.0.11114' -newVersion:'6.19.0.11114'
        
	    # Add redirect of Microsoft.Spatial
        $assemblyName = 'Microsoft.Spatial'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-6.19.0.11114' -newVersion:'6.19.0.11114'

        # Add redirect of Microsoft.OData.Edm
        $assemblyName = 'Microsoft.OData.Edm'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-6.19.0.11114' -newVersion:'6.19.0.11114'
    }

    # check if update 62 or later
    if ($PlatformReleaseVersion -gt 7080)
    {
        $assemblyName = 'System.Buffers'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'cc7b13ffcd2ddd51' -oldVersion:'0.0.0.0-4.0.3.0' -newVersion:'4.0.3.0'

        $assemblyName = 'System.Memory'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'cc7b13ffcd2ddd51' -oldVersion:'0.0.0.0-4.0.1.1' -newVersion:'4.0.1.1'

        $assemblyName = 'System.Text.Json'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'cc7b13ffcd2ddd51' -oldVersion:'0.0.0.0-6.0.0.8' -newVersion:'6.0.0.8'
    }

    # check if update 61 or later
    if ($PlatformReleaseVersion -gt 7060)
    {
        $assemblyName = 'Microsoft.IdentityModel.Abstractions'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-6.32.1.0' -newVersion:'6.32.1.0'

        $assemblyName = 'Microsoft.IdentityModel.Protocools.OpenIdConnect'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-6.32.1.0' -newVersion:'6.32.1.0'

        $assemblyName = 'Microsoft.IdentityModel.Protocols.SignedHttpRequest'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-6.32.1.0' -newVersion:'6.32.1.0'

        $assemblyName = 'Microsoft.IdentityModel.Protocols'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-6.32.1.0' -newVersion:'6.32.1.0'

        $assemblyName = 'Microsoft.IdentityModel.Logging'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-6.32.1.0' -newVersion:'6.32.1.0'

        $assemblyName = 'Microsoft.IdentityModel.Tokens'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-6.32.1.0' -newVersion:'6.32.1.0'

        $assemblyName = 'Microsoft.IdentityModel.JsonWebTokens'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-6.32.1.0' -newVersion:'6.32.1.0'

        $assemblyName = 'Microsoft.IdentityModel.Validators'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-6.32.1.0' -newVersion:'6.32.1.0'
    }

    # check if later than update 63 (forked from 7120)
    if ($PlatformReleaseVersion -gt 7120)
    {
        # Add redirect of System.Runtime.CompilerServices.Unsafe
        $assemblyName = 'System.Runtime.CompilerServices.Unsafe'

        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }

        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'b03f5f7f11d50a3a' -oldVersion:'0.0.0.0-6.0.0.0' -newVersion:'6.0.0.0'

        # Add redirect of System.Diagnostics.DiagnosticSource
        $assemblyName = 'System.Diagnostics.DiagnosticSource'

        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }

        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'cc7b13ffcd2ddd51' -oldVersion:'0.0.0.0-6.0.0.0' -newVersion:'6.0.0.0'

        
        # Add redirect of Bond.Attributes
        $assemblyName = 'Bond.Attributes'

        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }

        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'87e9ead25a117286' -oldVersion:'0.0.0.0-9.0.3.100' -newVersion:'11.0.0.100'


        # Add redirect of Bond.IO
        $assemblyName = 'Bond.IO'

        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }

        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'87e9ead25a117286' -oldVersion:'0.0.0.0-9.0.3.100' -newVersion:'11.0.0.100'

        # Add redirect of Bond.Reflection
        $assemblyName = 'Bond.Reflection'

        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }

        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'87e9ead25a117286' -oldVersion:'0.0.0.0-9.0.3.100' -newVersion:'11.0.0.100'

        # Add redirect of Bond.IO
        $assemblyName = 'Bond'

        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }

        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'87e9ead25a117286' -oldVersion:'0.0.0.0-9.0.3.100' -newVersion:'11.0.0.100'

        # Add redirect of Bond.JSON
        $assemblyName = 'Bond.JSON'

        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }

        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'87e9ead25a117286' -oldVersion:'0.0.0.0-9.0.3.100' -newVersion:'11.0.0.100'

         # Add redirect of Microsoft.Cloud.InstrumentationFramework.Events
        $assemblyName = 'Microsoft.Cloud.InstrumentationFramework.Events'

        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }

        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-3.3.9.1' -newVersion:'3.4.1.1'

         # Add redirect of Microsoft.Cloud.InstrumentationFramework.Metrics
        $assemblyName = 'Microsoft.Cloud.InstrumentationFramework.Metrics'

        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }

        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-3.3.9.1' -newVersion:'3.4.1.1'

         # Add redirect of Microsoft.Cloud.InstrumentationFramework.Health
        $assemblyName = 'Microsoft.Cloud.InstrumentationFramework.Health'

        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }

        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-3.3.9.1' -newVersion:'3.4.1.1'

        $assemblyName = 'Microsoft.ApplicationInsights'

        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }

        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-2.21.0.429' -newVersion:'2.21.0.429'

        $assemblyName = 'Microsoft.AI.DependencyCollector'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }

        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-2.21.0.429' -newVersion:'2.21.0.429'

        $assemblyName = 'Microsoft.AI.PerfCounterCollector'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }

        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-2.21.0.429' -newVersion:'2.21.0.429'

        $assemblyName = 'Microsoft.AI.Web'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }

        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-2.21.0.429' -newVersion:'2.21.0.429'

        $assemblyName = 'Microsoft.AI.WindowsServer'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }

        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-2.21.0.429' -newVersion:'2.21.0.429'

        $assemblyName = 'Microsoft.AI.ServerTelemetryChannel'

        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }

        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-2.21.0.429' -newVersion:'2.21.0.429'

        # Add redirect of System.Collections.Immutable
        $assemblyName = 'System.Collections.Immutable'

        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }

        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'b03f5f7f11d50a3a' -oldVersion:'0.0.0.0-5.0.0.0' -newVersion:'5.0.0.0'

        # Add redirect of Azure.Core
        $assemblyName = 'Azure.Core'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'92742159e12e44c8' -oldVersion:'0.0.0.0-1.35.0.0' -newVersion:'1.35.0.0'

        # Add redirect of Azure.Storage.Common
        $assemblyName = 'Azure.Storage.Common'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'92742159e12e44c8' -oldVersion:'0.0.0.0-12.15.0.0' -newVersion:'12.15.0.0'

        # Add redirect of Microsoft.Bcl.AsyncInterfaces
        $assemblyName = 'Microsoft.Bcl.AsyncInterfaces'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'cc7b13ffcd2ddd51' -oldVersion:'0.0.0.0-4.2.0.1' -newVersion:'4.2.0.1'
    }

    # check if later than update 64 (forked from 7198)
    if ($PlatformReleaseVersion -gt 7198)
    {
        $assemblyName = 'Microsoft.IdentityModel.Abstractions'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-7.3.1.0' -newVersion:'7.3.1.0'

        $assemblyName = 'Microsoft.Identity.Client'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'0a613f4dd989e8ae' -oldVersion:'0.0.0.0-4.56.0.0' -newVersion:'4.56.0.0'

        $assemblyName = 'Microsoft.IdentityModel.Protocools.OpenIdConnect'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-7.3.1.0' -newVersion:'7.3.1.0'

        $assemblyName = 'Microsoft.IdentityModel.Protocols.SignedHttpRequest'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-7.3.1.0' -newVersion:'7.3.1.0'

        $assemblyName = 'Microsoft.IdentityModel.Protocols'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-7.3.1.0' -newVersion:'7.3.1.0'

        $assemblyName = 'Microsoft.IdentityModel.Logging'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-7.3.1.0' -newVersion:'7.3.1.0'

        $assemblyName = 'Microsoft.IdentityModel.Tokens'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-7.3.1.0' -newVersion:'7.3.1.0'

        $assemblyName = 'Microsoft.IdentityModel.JsonWebTokens'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-7.3.1.0' -newVersion:'7.3.1.0'

        $assemblyName = 'Microsoft.IdentityModel.Validators'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-7.3.1.0' -newVersion:'7.3.1.0'

        $assemblyName = 'Microsoft.Graph'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-3.19.0.0' -newVersion:'3.19.0.0'

        $assemblyName = 'Microsoft.Graph.Core'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-1.22.0.0' -newVersion:'1.22.0.0'
    }

    # check if update 65 or later (64 forked from 7279)
    if ($PlatformReleaseVersion -gt 7279)
    {
        # Add redirect of Microsoft.Bcl.AsyncInterfaces
        $assemblyName = 'Microsoft.Bcl.AsyncInterfaces'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'cc7b13ffcd2ddd51' -oldVersion:'0.0.0.0-8.0.0.0' -newVersion:'8.0.0.0'

        # Add redirect of Microsoft.Extensions.Primitives
        $assemblyName = 'Microsoft.Extensions.Primitives'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-5.0.0.0' -newVersion:'5.0.0.0'

        # Add redirect of Microsoft.Extensions.DependencyInjection
        $assemblyName = 'Microsoft.Extensions.DependencyInjection'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-3.1.28.0' -newVersion:'3.1.28.0'

        # Add redirect of Microsoft.Extensions.DependencyInjection.Abstractions
        $assemblyName = 'Microsoft.Extensions.DependencyInjection.Abstractions'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-3.1.28.0' -newVersion:'3.1.28.0'

        # Add redirect of Microsoft.Extensions.Options
        $assemblyName = 'Microsoft.Extensions.Options'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-3.1.28.0' -newVersion:'3.1.28.0'

        # Add redirect of Microsoft.Extensions.Logging.Abstractions
        $assemblyName = 'Microsoft.Extensions.Logging.Abstractions'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-3.1.28.0' -newVersion:'3.1.28.0'

        # Add redirect of Microsoft.Extensions.Configuration.Abstractions
        $assemblyName = 'Microsoft.Extensions.Configuration.Abstractions'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-5.0.0.0' -newVersion:'5.0.0.0'

        # Add redirect of Microsoft.Extensions.Configuration
        $assemblyName = 'Microsoft.Extensions.Configuration'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-5.0.0.0' -newVersion:'5.0.0.0'

        # Add redirect of Microsoft.Extensions.Configuration.Binder
        $assemblyName = 'Microsoft.Extensions.Configuration.Binder'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-3.1.28.0' -newVersion:'3.1.28.0'

        # Add redirect of Microsoft.Extensions.Logging
        $assemblyName = 'Microsoft.Extensions.Logging'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-3.1.28.0' -newVersion:'3.1.28.0'

        # Add redirect of Microsoft.Extensions.Configuration.EnvironmentVariables
        $assemblyName = 'Microsoft.Extensions.Configuration.EnvironmentVariables'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-3.1.28.0' -newVersion:'3.1.28.0'

        # Add redirect of Microsoft.Extensions.Caching.Abstractions
        $assemblyName = 'Microsoft.Extensions.Caching.Abstractions'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-3.1.28.0' -newVersion:'3.1.28.0'

        # Add redirect of Microsoft.Extensions.Caching.Memory
        $assemblyName = 'Microsoft.Extensions.Caching.Memory'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-3.1.28.0' -newVersion:'3.1.28.0'

        # Add redirect of Microsoft.Extensions.Logging.Configuration
        $assemblyName = 'Microsoft.Extensions.Logging.Configuration'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-3.1.28.0' -newVersion:'3.1.28.0'

        # Add redirect of Microsoft.Extensions.Options.ConfigurationExtensions
        $assemblyName = 'Microsoft.Extensions.Options.ConfigurationExtensions'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-3.1.28.0' -newVersion:'3.1.28.0'

        # Add redirect of System.ComponentModel.Annotations
        $assemblyName = 'System.ComponentModel.Annotations'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-3.1.28.0' -newVersion:'3.1.28.0'

        # Add redirect of Microsoft.Powerapps.Coreframework
        $assemblyName = 'CoreFramework'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-3.42.2277.41' -newVersion:'3.42.2277.41' -culture:'neutral'

        # Add redirect of Microsoft.Identity.Client
        $assemblyName = 'Microsoft.Identity.Client'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'0a613f4dd989e8ae' -oldVersion:'0.0.0.0-4.61.3.0' -newVersion:'4.61.3.0' -culture:'neutral'

        # Add redirect of Azure.Core
        $assemblyName = 'Azure.Core'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'92742159e12e44c8' -oldVersion:'0.0.0.0-1.40.0.0' -newVersion:'1.40.0.0' -culture:'neutral'

        # Add redirect of Azure.Storage.Common
        $assemblyName = 'Azure.Storage.Common'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'92742159e12e44c8' -oldVersion:'0.0.0.0-12.19.0.0' -newVersion:'12.19.0.0' -culture:'neutral'
    }

    # check if update 66 or later (65 forked from 7367)
    if ($PlatformReleaseVersion -gt 7367)
    {
        # Add redirect of System.Text.Json
        $assemblyName = 'System.Text.Json'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'cc7b13ffcd2ddd51' -oldVersion:'0.0.0.0-8.0.0.4' -newVersion:'8.0.0.4'

        # Add redirect of Azure.Core
        $assemblyName = 'Azure.Core'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'92742159e12e44c8' -oldVersion:'0.0.0.0-1.41.0.0' -newVersion:'1.41.0.0'

        # Add redirect of Microsoft.ApplicationInsights
        $assemblyName = 'Microsoft.ApplicationInsights'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-2.22.0.997' -newVersion:'2.22.0.997'

        # Add redirect of Microsoft.IdentityModel.Logging
        $assemblyName = 'Microsoft.IdentityModel.Logging'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-7.3.1.0' -newVersion:'7.3.1.0'

        # Add redirect of OpenTelemetry.Audit.Geneva
        $assemblyName = 'OpenTelemetry.Audit.Geneva'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'7bd6737fe5b67e3c' -oldVersion:'0.0.0.0-2.1.1.0' -newVersion:'2.1.1.0'

        # Add redirect of System.Formats.Asn1
        $assemblyName = 'System.Formats.Asn1'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'cc7b13ffcd2ddd51' -oldVersion:'0.0.0.0-8.0.0.1' -newVersion:'8.0.0.1'
    }

    # check if later than update 66 (forked from 7434)
    if ($PlatformReleaseVersion -gt 7433)
    {        
        # Add redirect of Bond.Attributes
        $assemblyName = 'Bond.Attributes'

        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }

        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'87e9ead25a117286' -oldVersion:'0.0.0.0-11.0.0.100' -newVersion:'13.0.0.100'


        # Add redirect of Bond.IO
        $assemblyName = 'Bond.IO'

        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }

        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'87e9ead25a117286' -oldVersion:'0.0.0.0-11.0.0.100' -newVersion:'13.0.0.100'

        # Add redirect of Bond.Reflection
        $assemblyName = 'Bond.Reflection'

        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }

        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'87e9ead25a117286' -oldVersion:'0.0.0.0-11.0.0.100' -newVersion:'13.0.0.100'

        # Add redirect of Bond.IO
        $assemblyName = 'Bond'

        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }

        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'87e9ead25a117286' -oldVersion:'0.0.0.0-11.0.0.100' -newVersion:'13.0.0.100'

        # Add redirect of Bond.JSON
        $assemblyName = 'Bond.JSON'

        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }

        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'87e9ead25a117286' -oldVersion:'0.0.0.0-11.0.0.100' -newVersion:'13.0.0.100'

         # Add redirect of Microsoft.Cloud.InstrumentationFramework.Events
        $assemblyName = 'Microsoft.Cloud.InstrumentationFramework.Events'

        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }

        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-3.4.1.1' -newVersion:'3.5.1.1'

         # Add redirect of Microsoft.Cloud.InstrumentationFramework.Metrics
        $assemblyName = 'Microsoft.Cloud.InstrumentationFramework.Metrics'

        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }

        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-3.4.1.1' -newVersion:'3.5.1.1'

         # Add redirect of Microsoft.Cloud.InstrumentationFramework.Health
        $assemblyName = 'Microsoft.Cloud.InstrumentationFramework.Health'

        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }

        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-3.4.1.1' -newVersion:'3.5.1.1'
    }

       # check if later than update 67 (TBD)
    if ($PlatformReleaseVersion -gt 7461 )
    {        
        # Add redirect of System.IO.Hashing
        $assemblyName = 'System.IO.Hashing'

        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }

        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'cc7b13ffcd2ddd51' -oldVersion:'0.0.0.0-6.0.0.1' -newVersion:'6.0.0.1'


        # Add redirect of BitFaster.Caching
        $assemblyName = 'BitFaster.Caching'

        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }

        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'65c36bc48e4e3803' -oldVersion:'0.0.0.0-2.2.0.0' -newVersion:'2.2.0.0'

        # Add redirect of System.Diagnostics.DiagnosticSource
        $assemblyName = 'System.Diagnostics.DiagnosticSource'

        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'cc7b13ffcd2ddd51' -oldVersion:'0.0.0.0-7.0.0.2' -newVersion:'7.0.0.2'

        # Add redirect of System.Text.Json
        $assemblyName = 'System.Text.Json'

        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }

        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'cc7b13ffcd2ddd51' -oldVersion:'0.0.0.0-8.0.0.5' -newVersion:'8.0.0.5'
    }

    # check if later than update 68
    if ($PlatformReleaseVersion -gt 7521 )
    {        
        # Add redirect of System.Diagnostics.DiagnosticSource
        $assemblyName = 'System.Diagnostics.DiagnosticSource'

        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }

        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'cc7b13ffcd2ddd51' -oldVersion:'0.0.0.0-8.0.0.0' -newVersion:'8.0.0.0'

        # Add redirect of System.Collections.Immutable
        $assemblyName = 'System.Collections.Immutable'

        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }

        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'b03f5f7f11d50a3a' -oldVersion:'0.0.0.0-7.0.0.0' -newVersion:'7.0.0.0'

        # Add redirect of Microsoft.Extensions.Primitives
        $assemblyName = 'Microsoft.Extensions.Primitives'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-8.0.0.0' -newVersion:'8.0.0.0'

         # Add redirect of Microsoft.Extensions.DependencyInjection
        $assemblyName = 'Microsoft.Extensions.DependencyInjection'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-8.0.0.0' -newVersion:'8.0.0.0'

        # Add redirect of Microsoft.Extensions.DependencyInjection.Abstractions
        $assemblyName = 'Microsoft.Extensions.DependencyInjection.Abstractions'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-8.0.0.0' -newVersion:'8.0.0.0'

        # Add redirect of Microsoft.Extensions.Options
        $assemblyName = 'Microsoft.Extensions.Options'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-8.0.0.0' -newVersion:'8.0.0.0'

         # Add redirect of Microsoft.Extensions.Logging.Abstractions
        $assemblyName = 'Microsoft.Extensions.Logging.Abstractions'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-8.0.0.0' -newVersion:'8.0.0.0'

        # Add redirect of Microsoft.Extensions.Configuration.Abstractions
        $assemblyName = 'Microsoft.Extensions.Configuration.Abstractions'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-8.0.0.0' -newVersion:'8.0.0.0'

        # Add redirect of Microsoft.Extensions.Configuration
        $assemblyName = 'Microsoft.Extensions.Configuration'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-8.0.0.0' -newVersion:'8.0.0.0'

        # Add redirect of Microsoft.Extensions.Configuration.Binder
        $assemblyName = 'Microsoft.Extensions.Configuration.Binder'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-8.0.0.0' -newVersion:'8.0.0.0'

        # Add redirect of Microsoft.Extensions.Logging
        $assemblyName = 'Microsoft.Extensions.Logging'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-8.0.0.0' -newVersion:'8.0.0.0'

        # Add redirect of Microsoft.Extensions.Logging.Configuration
        $assemblyName = 'Microsoft.Extensions.Logging.Configuration'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-8.0.0.0' -newVersion:'8.0.0.0'

        # Add redirect of Microsoft.Extensions.Configuration.EnvironmentVariables
        $assemblyName = 'Microsoft.Extensions.Configuration.EnvironmentVariables'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-8.0.0.0' -newVersion:'8.0.0.0'

        # Add redirect of Microsoft.Extensions.Options.ConfigurationExtensions
        $assemblyName = 'Microsoft.Extensions.Options.ConfigurationExtensions'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-8.0.0.0' -newVersion:'8.0.0.0'
    }

    # check if dealing with PU68 or newer
    if ($PlatformReleaseVersion -gt 7521 ) # 7521 is PU67
    {
        # Add redirect of System.Diagnostics.DiagnosticSource
        $assemblyName = 'System.Diagnostics.DiagnosticSource'

        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'cc7b13ffcd2ddd51' -oldVersion:'0.0.0.0-8.0.0.1' -newVersion:'8.0.0.1'

        # Add redirect of System.Collections.Immutable
        $assemblyName = 'System.Collections.Immutable'

        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'b03f5f7f11d50a3a' -oldVersion:'0.0.0.0-8.0.0.0' -newVersion:'8.0.0.0'

        # Add redirect of System.Reflection.Metadata
        $assemblyName = 'System.Reflection.Metadata'

        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }

        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'b03f5f7f11d50a3a' -oldVersion:'0.0.0.0-8.0.0.1' -newVersion:'8.0.0.1'

        # Add redirect of Microsoft.Extensions.Caching.Abstractions
        $assemblyName = 'Microsoft.Extensions.Caching.Abstractions'

        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }        

        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-6.0.0.1' -newVersion:'6.0.0.1'

        # Add redirect of Microsoft.Extensions.Caching.Memory
        $assemblyName = 'Microsoft.Extensions.Caching.Memory'

        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }        

        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-6.0.0.3' -newVersion:'6.0.0.3'
    }

     # For 7.0.7595.0/PU68 and greater
    if ($PlatformReleaseVersion -ge 7595)
    {
        $assemblyName = 'Microsoft.Identity.Client'

        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }

        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'0a613f4dd989e8ae' -oldVersion:'0.0.0.0-4.68.0.0' -newVersion:'4.68.0.0'

        $assemblyName = 'Microsoft.Identity.Client.NativeInterop'

        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }

        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'0a613f4dd989e8ae' -oldVersion:'0.0.0.0-0.18.0.0' -newVersion:'1.0.0.0'

        # Add redirect of System.IO.Hashing
        $assemblyName = 'System.IO.Hashing'

        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'cc7b13ffcd2ddd51' -oldVersion:'0.0.0.0-8.0.0.0' -newVersion:'8.0.0.0'

        # Add redirect of BitFaster.Caching
        $assemblyName = 'BitFaster.Caching'

        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'65c36bc48e4e3803' -oldVersion:'0.0.0.0-2.5.0.0' -newVersion:'2.5.0.0'

        # Add redirect of System.IdentityModel.Tokens.Jwt
        $assemblyName = 'System.IdentityModel.Tokens.Jwt'

        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-8.3.0.0' -newVersion:'8.3.0.0'

        # Add redirect of Azure.Core
        $assemblyName = 'Azure.Core'

        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'92742159e12e44c8' -oldVersion:'0.0.0.0-1.44.1.0' -newVersion:'1.44.1.0'

        # Add redirect of Azure.Storage.Common
        $assemblyName = 'Azure.Storage.Common'

        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'92742159e12e44c8' -oldVersion:'0.0.0.0-12.22.0.0' -newVersion:'12.22.0.0'

        # Add redirect of Microsoft.IdentityModel.Abstractions
        $assemblyName = 'Microsoft.IdentityModel.Abstractions'

        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-8.3.0.0' -newVersion:'8.3.0.0'

        # Add redirect of Microsoft.IdentityModel.Protocols
        $assemblyName = 'Microsoft.IdentityModel.Protocols'

        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-8.3.0.0' -newVersion:'8.3.0.0'

        # Add redirect of Microsoft.IdentityModel.Protocols.OpenIdConnect
        $assemblyName = 'Microsoft.IdentityModel.Protocols.OpenIdConnect'

        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-8.3.0.0' -newVersion:'8.3.0.0'
		
		# Add redirect of Microsoft.IdentityModel.Protocols.WsFederation
        $assemblyName = 'Microsoft.IdentityModel.Protocols.WsFederation'

        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-8.3.0.0' -newVersion:'8.3.0.0'


        # Add redirect of Microsoft.IdentityModel.Tokens
        $assemblyName = 'Microsoft.IdentityModel.Tokens'

        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-8.3.0.0' -newVersion:'8.3.0.0'

        # Add redirect of Microsoft.IdentityModel.Tokens.Saml
        $assemblyName = 'Microsoft.IdentityModel.Tokens.Saml'

        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-8.3.0.0' -newVersion:'8.3.0.0'

        # Add redirect of Microsoft.IdentityModel.Xml
        $assemblyName = 'Microsoft.IdentityModel.Xml'

        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-8.3.0.0' -newVersion:'8.3.0.0'

        # Add redirect of OpenTelemetry.Exporter.Geneva
        $assemblyName = 'OpenTelemetry.Exporter.Geneva'

        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'7bd6737fe5b67e3c' -oldVersion:'0.0.0.0-1.6.0.0' -newVersion:'1.6.0.0'

        # Add redirect of Microsoft.IdentityModel.Logging
        $assemblyName = 'Microsoft.IdentityModel.Logging'

        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-8.3.0.0' -newVersion:'8.3.0.0'

                # Add redirect of Microsoft.Identity.ServerAuthorization
        $assemblyName = 'Microsoft.Identity.ServerAuthorization'

        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-4.9.0.0' -newVersion:'4.9.0.0'

                # Add redirect of System.Memory.Data
        $assemblyName = 'System.Memory.Data'

        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'cc7b13ffcd2ddd51' -oldVersion:'0.0.0.0-6.0.0.0' -newVersion:'6.0.0.0'
    }

    # For PU69 or newer
    if ($PlatformReleaseVersion -gt 7606)
    {
        # Add redirect of Microsoft.Identity.Client
        $assemblyName = 'Microsoft.Identity.Client'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'0a613f4dd989e8ae' -oldVersion:'0.0.0.0-4.70.0.0' -newVersion:'4.70.0.0'

        # Add redirect of Microsoft.Identity.Client.NativeInterop
        $assemblyName = 'Microsoft.Identity.Client.NativeInterop'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'0a613f4dd989e8ae' -oldVersion:'0.0.0.0-0.18.1.0' -newVersion:'0.18.1.0'

        # Add redirect of Azure.Core
        $assemblyName = 'Azure.Core'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'92742159e12e44c8' -oldVersion:'0.0.0.0-1.45.0.0' -newVersion:'1.45.0.0'

        # Add redirect of System.ClientModel
        $assemblyName = 'System.ClientModel'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'92742159e12e44c8' -oldVersion:'0.0.0.0-1.3.0.0' -newVersion:'1.3.0.0'

        # Add redirect of System.Text.Encodings.Web
        $assemblyName = 'System.Text.Encodings.Web'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'cc7b13ffcd2ddd51' -oldVersion:'0.0.0.0-8.0.0.0' -newVersion:'8.0.0.0'
    }

    $xmlDoc.Save($webconfig)
} 
    

function Get-DependentAssemblyExists([string] $assemblyName, [System.Xml.XmlDocument] $xmlDoc)
{
    $dependentAssemblyExists = $false
    $ns = New-Object System.Xml.XmlNamespaceManager($xmlDoc.NameTable)
    $ns.AddNamespace("ab", "urn:schemas-microsoft-com:asm.v1")
    $assemblyNode = $xmlDoc.SelectSingleNode("/configuration/runtime/ab:assemblyBinding/ab:dependentAssembly/ab:assemblyIdentity[@name='$assemblyName']", $ns)
    if ($assemblyNode -ne $null)
    {
        $dependentAssemblyExists = $true
    }
    return $dependentAssemblyExists
}

function Update-AppContextSwitchOverrides([string] $keyValue, [System.Xml.XmlDocument] $xmlDoc)
{
    Write-Output "Value to be added to AppContextSwitchOverrides = '$keyValue'"
    $appContextSwitchOverrides = $xmlDoc.SelectSingleNode("/configuration/runtime/AppContextSwitchOverrides");
    if($appContextSwitchOverrides -ne $null -and $appContextSwitchOverrides.value -notmatch $keyValue)
    {
        Write-Output "Current AppContextSwitchOverrides value = '$($appContextSwitchOverrides.value)'"
        $appContextSwitchOverrides.value = $appContextSwitchOverrides.value + ";" + $keyValue
        Write-Output "Updated AppContextSwitchOverrides value = '$($appContextSwitchOverrides.value)'"
    }
}

function Upgrade-WebConfig-Add-DependentAssemblies([string] $webConfig)
{
    [System.Xml.XmlDocument] $xmlDoc = New-Object System.Xml.XmlDocument
    $xmlDoc.Load($webconfig)

    $assemblyName = 'System.Web.http'
    if (!(Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc))
    {
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-5.0.0.0' -newVersion:'5.2.2.0'
    }
    $assemblyName = 'System.Web.Http.WebHost'
    if (!(Get-DependentAssemblyExists -assemblyName:$assemblyName  -xmlDoc:$xmlDoc))
    {
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-5.0.0.0' -newVersion:'5.2.2.0'
    }
    $assemblyName = 'System.Net.Http'
    if (!(Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc))
    {
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'b03f5f7f11d50a3a'
    }

    if ($PlatformReleaseVersion -gt 5221)
    {
        Write-Log "Upgrading ApplicationInsights binding redirect for web.config (PU25)"
        #Add app insights and dependencies binding redirects
        $assemblyName = 'Microsoft.AspNet.TelemetryCorrelation'
        if (!(Get-DependentAssemblyExists -assemblyName:$assemblyName  -xmlDoc:$xmlDoc))
        {
            Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-1.0.5.0' -newVersion:'1.0.5.0'
        }
        $assemblyName = 'System.Diagnostics.DiagnosticSource'
        if (!(Get-DependentAssemblyExists -assemblyName:$assemblyName  -xmlDoc:$xmlDoc))
        {
            Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'cc7b13ffcd2ddd51' -oldVersion:'0.0.0.0-6.0.0.1' -newVersion:'6.0.0.1'
        }
        $assemblyName = 'Microsoft.AI.Agent.Intercept'
        if (!(Get-DependentAssemblyExists -assemblyName:$assemblyName  -xmlDoc:$xmlDoc))
        {
            Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-2.4.0.0' -newVersion:'2.4.0.0'
        }
        $assemblyName = 'Microsoft.ApplicationInsights'
        if (!(Get-DependentAssemblyExists -assemblyName:$assemblyName  -xmlDoc:$xmlDoc))
        {
            Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-2.9.0.0' -newVersion:'2.9.0.0'
        }
        $assemblyName = 'Microsoft.AI.DependencyCollector'
        if (!(Get-DependentAssemblyExists -assemblyName:$assemblyName  -xmlDoc:$xmlDoc))
        {
            Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-2.9.0.0' -newVersion:'2.9.0.0'
        }
        $assemblyName = 'Microsoft.AI.PerfCounterCollector'
        if (!(Get-DependentAssemblyExists -assemblyName:$assemblyName  -xmlDoc:$xmlDoc))
        {
            Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-2.9.0.0' -newVersion:'2.9.0.0'
        }
        $assemblyName = 'Microsoft.AI.Web'
        if (!(Get-DependentAssemblyExists -assemblyName:$assemblyName  -xmlDoc:$xmlDoc))
        {
            Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-2.9.0.0' -newVersion:'2.9.0.0'
        }
        $assemblyName = 'Microsoft.AI.WindowsServer'
        if (!(Get-DependentAssemblyExists -assemblyName:$assemblyName  -xmlDoc:$xmlDoc))
        {
            Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-2.9.0.0' -newVersion:'2.9.0.0'
        }
        $assemblyName = 'Microsoft.AI.ServerTelemetryChannel'
        if (!(Get-DependentAssemblyExists -assemblyName:$assemblyName  -xmlDoc:$xmlDoc))
        {
            Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-2.9.0.0' -newVersion:'2.9.0.0'
        }
    }

    if ($PlatformReleaseVersion -gt 4641)
    {
        $assemblyName = 'System.Net.Http.Formatting'
        if (!(Get-DependentAssemblyExists -assemblyName:$assemblyName  -xmlDoc:$xmlDoc))
        {
            Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-5.2.2.0' -newVersion:'5.2.3.0'
        }
    }
    $assemblyName = 'Microsoft.Dynamics.Client.InteractionService'
    if (!(Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc))
    {
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'6.0.0.0' -newVersion:'7.0.0.0' -culture:'neutral'
    }
    $assemblyName = 'Microsoft.Owin.Security'
    if (!(Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc))
    {
      $owinVersion = '3.0.1.0'
      $owinBinding = '0.0.0.0-3.0.1.0'

      # Check if update 42 or later
      if ($PlatformReleaseVersion -ge 5968)
      {
        # Check if update 56 or later
        if ($PlatformReleaseVersion -ge 6730)
        {
           $owinVersion = '4.2.2.0'
           $owinBinding = '0.0.0.0-4.2.2.0'
        }
        elseif ($PlatformReleaseVersion -ge 6192)
        {
           $owinVersion = '4.1.1.0'
           $owinBinding = '0.0.0.0-4.1.1.0'
        }
        else
        {
          $owinVersion = '3.1.0.0'
          $owinBinding = '0.0.0.0-3.1.0.0'
        }
      }

      Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-3.0.1.0' -newVersion:'3.0.1.0' -culture:'neutral'

    }
    $assemblyName = 'Microsoft.Diagnostics.Tracing.EventSource'
    if (!(Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc))
    {
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'b03f5f7f11d50a3a' -oldVersion:'1.1.17.0' -newVersion:'1.1.28.0' -culture:'neutral'
    }

    #Add check forupdate 4
    if ($PlatformReleaseVersion -ge 4425)
    {
        $assemblyName = 'Newtonsoft.Json'
        if (!(Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc))
        {
            Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'30ad4fe6b2a6aeed' -oldVersion:'0.0.0.0-9.0.0.0' -newVersion:'9.0.0.0' -culture:'neutral'
        }
        $assemblyName = 'Microsoft.IdentityModel.Clients.ActiveDirectory'
        if (!(Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc))
        {
            Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-2.23.0.0' -newVersion:'2.23.0.0' -culture:'neutral'
        }
        $assemblyName = 'Microsoft.Azure.ActiveDirectory.GraphClient'
        if (!(Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc))
        {
            Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-2.1.1.0' -newVersion:'2.1.1.0' -culture:'neutral'
        }
    }

    # PU50+
    if ($PlatformReleaseVersion -gt 6316)
    {
        $assemblyName = 'BouncyCastle.Crypto'
        if (!(Get-DependentAssemblyExists -assemblyName:$assemblyName  -xmlDoc:$xmlDoc))
        {
            Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'0e99375e54769942' -oldVersion:'0.0.0.0-1.9.0.0' -newVersion:'1.9.0.0'
        }
    }

    if ($PlatformReleaseVersion -gt 6841)
    {
        $assemblyName = 'Microsoft.Graph'
        if (!(Get-DependentAssemblyExists -assemblyName:$assemblyName  -xmlDoc:$xmlDoc))
        {
            Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-1.14.0.0' -newVersion:'1.7.0.0'
        }

        $assemblyName = 'Microsoft.Graph.Core'
        if (!(Get-DependentAssemblyExists -assemblyName:$assemblyName  -xmlDoc:$xmlDoc))
        {
            Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-1.14.0.0' -newVersion:'1.7.0.0'
        }
    }

    #PU64 or greater
    if ($PlatformReleaseVersion -gt 7198) #7198 is PU63
    {
        $assemblyName = 'System.IdentityModel.Tokens.Jwt'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-7.3.1.0' -newVersion:'4.0.40306.1554' -culture:'neutral'

        $assemblyName = 'Microsoft.WindowsAzure.ServiceRuntime'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-2.7.0.0' -newVersion:'2.6.0.0' -culture:'neutral'

        $assemblyName = 'Microsoft.IdentityModel.Clients.ActiveDirectory'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-3.19.8.16603' -newVersion:'2.23.0.0' -culture:'neutral'

        $assemblyName = 'CoreFramework'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-3.8.1811.356' -newVersion:'3.8.1811.356' -culture:'neutral'

        $assemblyName = 'System.Reactive.Core'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'94bc3704cddfc263' -oldVersion:'0.0.0.0-3.0.3000.0' -newVersion:'3.0.3000.0' -culture:'neutral'
        $assemblyName = 'Microsoft.Extensions.Primitives'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-2.1.1.0' -newVersion:'1.1.1.0' -culture:'neutral'

        $assemblyName = 'Microsoft.Extensions.DependencyInjection.Abstractions'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-2.1.1.0' -newVersion:'1.1.1.0' -culture:'neutral'

        $assemblyName = 'Microsoft.Extensions.Options'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-2.1.1.0' -newVersion:'1.1.2.0' -culture:'neutral'

        $assemblyName = 'Microsoft.Extensions.Logging.Abstractions'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-2.1.1.0' -newVersion:'1.1.2.0' -culture:'neutral'

        $assemblyName = 'Microsoft.Extensions.Configuration.Abstractions'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-2.1.1.0' -newVersion:'1.1.2.0' -culture:'neutral'

        $assemblyName = 'Microsoft.Extensions.Configuration'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-2.1.1.0' -newVersion:'1.1.2.0' -culture:'neutral'

        $assemblyName = 'Microsoft.Extensions.Configuration.Binder'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-2.1.10.0' -newVersion:'1.1.2.0' -culture:'neutral'

        $assemblyName = 'Microsoft.Extensions.Logging'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-2.1.1.0' -newVersion:'1.1.2.0' -culture:'neutral'

        $assemblyName = 'Microsoft.Extensions.Configuration.EnvironmentVariables'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-2.1.1.0' -newVersion:'1.1.2.0' -culture:'neutral'


        $assemblyName = 'System.Web.Http'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-5.2.6.0' -newVersion:'5.2.2.0' -culture:'neutral'

        $assemblyName = 'System.Collections.Immutable'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'b03f5f7f11d50a3a' -oldVersion:'0.0.0.0-6.0.0.0' -newVersion:'6.0.0.0' -culture:'neutral'

        $assemblyName = 'System.Reflection.Metadata'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'b03f5f7f11d50a3a' -oldVersion:'0.0.0.0-6.0.0.1' -newVersion:'6.0.0.1' -culture:'neutral'
    
        $assemblyName = 'Microsoft.Graph'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-3.19.0.0' -newVersion:'3.19.0.0'

        $assemblyName = 'Microsoft.Graph.Core'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-1.22.0.0' -newVersion:'1.22.0.0'
    }

    #PU65 or greater
    if ($PlatformReleaseVersion -gt 7279) #7279 is PU64
    {
        # Add redirect of Microsoft.Bcl.AsyncInterfaces
        $assemblyName = 'Microsoft.Bcl.AsyncInterfaces'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'cc7b13ffcd2ddd51' -oldVersion:'0.0.0.0-6.0.0.0' -newVersion:'6.0.0.0'

        # Add redirect of Microsoft.Extensions.Primitives
        $assemblyName = 'Microsoft.Extensions.Primitives'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-3.1.28.0' -newVersion:'3.1.28.0'


        # Add redirect of Microsoft.Extensions.DependencyInjection
        $assemblyName = 'Microsoft.Extensions.DependencyInjection'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-3.1.28.0' -newVersion:'3.1.28.0'

        # Add redirect of Microsoft.Extensions.DependencyInjection.Abstractions
        $assemblyName = 'Microsoft.Extensions.DependencyInjection.Abstractions'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-3.1.28.0' -newVersion:'3.1.28.0'

        # Add redirect of Microsoft.Extensions.Options
        $assemblyName = 'Microsoft.Extensions.Options'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-3.1.28.0' -newVersion:'3.1.28.0'

        # Add redirect of Microsoft.Extensions.Logging.Abstractions
        $assemblyName = 'Microsoft.Extensions.Logging.Abstractions'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-3.1.28.0' -newVersion:'3.1.28.0'

        # Add redirect of Microsoft.Extensions.Configuration.Abstractions
        $assemblyName = 'Microsoft.Extensions.Configuration.Abstractions'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-3.1.28.0' -newVersion:'3.1.28.0'

        # Add redirect of Microsoft.Extensions.Configuration
        $assemblyName = 'Microsoft.Extensions.Configuration'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-3.1.28.0' -newVersion:'3.1.28.0'

        # Add redirect of Microsoft.Extensions.Configuration.Binder
        $assemblyName = 'Microsoft.Extensions.Configuration.Binder'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-3.1.28.0' -newVersion:'3.1.28.0'

        # Add redirect of Microsoft.Extensions.Logging
        $assemblyName = 'Microsoft.Extensions.Logging'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-3.1.28.0' -newVersion:'3.1.28.0'

        # Add redirect of Microsoft.Extensions.Configuration.EnvironmentVariables
        $assemblyName = 'Microsoft.Extensions.Configuration.EnvironmentVariables'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-3.1.28.0' -newVersion:'3.1.28.0'

        # Add redirect of Microsoft.Extensions.Caching.Abstractions
        $assemblyName = 'Microsoft.Extensions.Caching.Abstractions'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-3.1.28.0' -newVersion:'3.1.28.0'

        # Add redirect of Microsoft.Extensions.Caching.Memory
        $assemblyName = 'Microsoft.Extensions.Caching.Memory'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-3.1.28.0' -newVersion:'3.1.28.0'

        # Add redirect of Microsoft.Extensions.Logging.Configuration
        $assemblyName = 'Microsoft.Extensions.Logging.Configuration'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-3.1.28.0' -newVersion:'3.1.28.0'

        # Add redirect of Microsoft.Extensions.Options.ConfigurationExtensions
        $assemblyName = 'Microsoft.Extensions.Options.ConfigurationExtensions'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-3.1.28.0' -newVersion:'3.1.28.0'

        # Add redirect of System.ComponentModel.Annotations
        $assemblyName = 'System.ComponentModel.Annotations'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-3.1.28.0' -newVersion:'3.1.28.0'

        # Add redirect of Microsoft.Powerapps.Coreframework
        $assemblyName = 'CoreFramework'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-3.42.2277.41' -newVersion:'3.42.2277.41' -culture:'neutral'
    }

    $xmlDoc.Save($webconfig);
}

function Upgrade-BatchConfig-Add-DependentAssemblies([string] $batchConfig)
{
    [System.Xml.XmlDocument] $xmlDoc = New-Object System.Xml.XmlDocument
    $xmlDoc.Load($batchConfig)

    #Append Switch.System.IdentityModel.DisableCngCertificates=true to AppContextSwitchOverrides if PU is 47 or above
    if ($PlatformReleaseVersion -ge 6192)
    {
        $keyValue = 'Switch.System.IdentityModel.DisableCngCertificates=true'
        Update-AppContextSwitchOverrides -keyValue: $keyValue -xmlDoc:$xmlDoc
    }

    $assemblyName = 'Microsoft.Diagnostics.Tracing.EventSource'
    if (!(Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc))
    {
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'b03f5f7f11d50a3a' -oldVersion:'1.1.17.0' -newVersion:'1.1.28.0' -culture:'neutral'
    }

    if ($PlatformReleaseVersion -gt 5221)
    {
        Write-Log "Upgrading ApplicationInsights binding redirect for batch.config (PU25)"
        #Add app insights and dependencies binding redirects
        $assemblyName = 'Microsoft.AspNet.TelemetryCorrelation'
        if (!(Get-DependentAssemblyExists -assemblyName:$assemblyName  -xmlDoc:$xmlDoc))
        {
            Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-1.0.5.0' -newVersion:'1.0.5.0'
        }
        $assemblyName = 'System.Diagnostics.DiagnosticSource'
        if (!(Get-DependentAssemblyExists -assemblyName:$assemblyName  -xmlDoc:$xmlDoc))
        {
            Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'cc7b13ffcd2ddd51' -oldVersion:'0.0.0.0-4.0.3.1' -newVersion:'4.0.3.1'
        }
        $assemblyName = 'Microsoft.AI.Agent.Intercept'
        if (!(Get-DependentAssemblyExists -assemblyName:$assemblyName  -xmlDoc:$xmlDoc))
        {
            Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-2.4.0.0' -newVersion:'2.4.0.0'
        }
        $assemblyName = 'Microsoft.ApplicationInsights'
        if (!(Get-DependentAssemblyExists -assemblyName:$assemblyName  -xmlDoc:$xmlDoc))
        {
            Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-2.9.0.0' -newVersion:'2.9.0.0'
        }
        $assemblyName = 'Microsoft.AI.DependencyCollector'
        if (!(Get-DependentAssemblyExists -assemblyName:$assemblyName  -xmlDoc:$xmlDoc))
        {
            Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-2.9.0.0' -newVersion:'2.9.0.0'
        }
        $assemblyName = 'Microsoft.AI.PerfCounterCollector'
        if (!(Get-DependentAssemblyExists -assemblyName:$assemblyName  -xmlDoc:$xmlDoc))
        {
            Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-2.9.0.0' -newVersion:'2.9.0.0'
        }
        $assemblyName = 'Microsoft.AI.Web'
        if (!(Get-DependentAssemblyExists -assemblyName:$assemblyName  -xmlDoc:$xmlDoc))
        {
            Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-2.9.0.0' -newVersion:'2.9.0.0'
        }
        $assemblyName = 'Microsoft.AI.WindowsServer'
        if (!(Get-DependentAssemblyExists -assemblyName:$assemblyName  -xmlDoc:$xmlDoc))
        {
            Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-2.9.0.0' -newVersion:'2.9.0.0'
        }
        $assemblyName = 'Microsoft.AI.ServerTelemetryChannel'
        if (!(Get-DependentAssemblyExists -assemblyName:$assemblyName  -xmlDoc:$xmlDoc))
        {
            Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-2.9.0.0' -newVersion:'2.9.0.0'
        }
    }

    #Check if update 12 or later
    if ($PlatformReleaseVersion -ge 4709)
    {
        $assemblyName = 'Newtonsoft.Json'
        if (!(Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc))
        {
            Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'30ad4fe6b2a6aeed' -oldVersion:'0.0.0.0-9.0.0.0' -newVersion:'9.0.0.0' -culture:'neutral'
        }
    }

    #Add check for update 23 or later
    if ($PlatformReleaseVersion -ge 5126)
    {
        $assemblyName = 'Microsoft.IdentityModel.Clients.ActiveDirectory'
        if (!(Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc))
        {
            Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-2.23.0.0' -newVersion:'2.23.0.0' -culture:'neutral'
        }
        else
        {
            Update-DependentAssemblyBinding -xmlDoc:$xmlDoc -assemblyName:$assemblyName -oldVersion:'0.0.0.0-2.23.0.0' -newVersion:'2.23.0.0'
        }
    }

	# Check if update 43 or later
    if ($PlatformReleaseVersion -ge 6009)
	{
		Update-DependentAssemblyBinding -xmlDoc:$xmlDoc -assemblyName:'Microsoft.Data.Services.Client' -oldVersion:'5.6.0.0-5.8.4.0' -newVersion:'5.8.4.0'
		Update-DependentAssemblyBinding -xmlDoc:$xmlDoc -assemblyName:'Microsoft.Data.OData' -oldVersion:'0.0.0.0-5.8.4.0' -newVersion:'5.8.4.0'
		Update-DependentAssemblyBinding -xmlDoc:$xmlDoc -assemblyName:'Microsoft.Data.Edm' -oldVersion:'5.6.0.0-5.8.4.0' -newVersion:'5.8.4.0'
	}

    # PU50+
    if ($PlatformReleaseVersion -gt 6316)
    {
        $assemblyName = 'BouncyCastle.Crypto'
        if (!(Get-DependentAssemblyExists -assemblyName:$assemblyName  -xmlDoc:$xmlDoc))
        {
            Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'0e99375e54769942' -oldVersion:'0.0.0.0-1.9.0.0' -newVersion:'1.9.0.0'
        }
    }

    if ($PlatformReleaseVersion -gt 6594)
    {
        $assemblyName = 'Microsoft.Graph'
        if (!(Get-DependentAssemblyExists -assemblyName:$assemblyName  -xmlDoc:$xmlDoc))
        {
            Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-1.14.0.0' -newVersion:'1.7.0.0'
        }

        $assemblyName = 'Microsoft.Graph.Core'
        if (!(Get-DependentAssemblyExists -assemblyName:$assemblyName  -xmlDoc:$xmlDoc))
        {
            Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-1.14.0.0' -newVersion:'1.7.0.0'
        }
    }

    # check if update 61 or later
    if ($PlatformReleaseVersion -gt 7060)
    {
        $assemblyName = 'Microsoft.IdentityModel.Abstractions'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-6.32.1.0' -newVersion:'6.32.1.0'

        $assemblyName = 'Microsoft.IdentityModel.Protocools.OpenIdConnect'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-6.32.1.0' -newVersion:'6.32.1.0'

        $assemblyName = 'Microsoft.IdentityModel.Protocols.SignedHttpRequest'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-6.32.1.0' -newVersion:'6.32.1.0'

        $assemblyName = 'Microsoft.IdentityModel.Protocols'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-6.32.1.0' -newVersion:'6.32.1.0'

        $assemblyName = 'Microsoft.IdentityModel.Logging'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-6.32.1.0' -newVersion:'6.32.1.0'

        $assemblyName = 'Microsoft.IdentityModel.Tokens'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-6.32.1.0' -newVersion:'6.32.1.0'

        $assemblyName = 'Microsoft.IdentityModel.JsonWebTokens'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-6.32.1.0' -newVersion:'6.32.1.0'

        $assemblyName = 'Microsoft.IdentityModel.Validators'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-6.32.1.0' -newVersion:'6.32.1.0'
    }

    # check if update 63 or later
    if ($PlatformReleaseVersion -gt 7120) # 7120 is PU62
    {
        $assemblyName = 'Microsoft.ApplicationInsights'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }

        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-2.21.0.429' -newVersion:'2.21.0.429'

        $assemblyName = 'Microsoft.AI.DependencyCollector'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }

        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-2.21.0.429' -newVersion:'2.21.0.429'

        $assemblyName = 'Microsoft.AI.PerfCounterCollector'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }

        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-2.21.0.429' -newVersion:'2.21.0.429'

        $assemblyName = 'Microsoft.AI.Web'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }

        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-2.21.0.429' -newVersion:'2.21.0.429'

        $assemblyName = 'Microsoft.AI.WindowsServer'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }

        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-2.21.0.429' -newVersion:'2.21.0.429'

        $assemblyName = 'Microsoft.AI.ServerTelemetryChannel'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }

        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-2.21.0.429' -newVersion:'2.21.0.429'

        # Add redirect of System.Runtime.CompilerServices.Unsafe
        # Per webconfig changes on https://msdyneng.visualstudio.com/DefaultCollection/AX%20Servicing/_git/PackageInfrastructure/pullrequest/240320
        $assemblyName = 'System.Runtime.CompilerServices.Unsafe'

        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }

        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'b03f5f7f11d50a3a' -oldVersion:'0.0.0.0-6.0.0.0' -newVersion:'6.0.0.0'

        # Add redirect of System.Diagnostics.DiagnosticSource
        # Per webconfig changes on https://msdyneng.visualstudio.com/DefaultCollection/AX%20Servicing/_git/PackageInfrastructure/pullrequest/243700
        $assemblyName = 'System.Diagnostics.DiagnosticSource'

        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }

        # Add redirect of System.Collections.Immutable
        # Per webconfig changes on https://msdyneng.visualstudio.com/DefaultCollection/AX%20Servicing/_git/PackageInfrastructure/pullrequest/244022
        $assemblyName = 'System.Collections.Immutable'

        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }

        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'b03f5f7f11d50a3a' -oldVersion:'0.0.0.0-5.0.0.0' -newVersion:'5.0.0.0'
    }

    # check if update 64 or later
    if ($PlatformReleaseVersion -gt 7198)
    {
        $assemblyName = 'Microsoft.IdentityModel.Abstractions'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-7.3.1.0' -newVersion:'7.3.1.0'

        $assemblyName = 'Microsoft.IdentityModel.Protocools.OpenIdConnect'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-7.3.1.0' -newVersion:'7.3.1.0'

        $assemblyName = 'Microsoft.IdentityModel.Protocols.SignedHttpRequest'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-7.3.1.0' -newVersion:'7.3.1.0'

        $assemblyName = 'Microsoft.IdentityModel.Protocols'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-7.3.1.0' -newVersion:'7.3.1.0'

        $assemblyName = 'Microsoft.IdentityModel.Logging'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-7.3.1.0' -newVersion:'7.3.1.0'

        $assemblyName = 'Microsoft.IdentityModel.Tokens'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-7.3.1.0' -newVersion:'7.3.1.0'

        $assemblyName = 'Microsoft.IdentityModel.JsonWebTokens'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-7.3.1.0' -newVersion:'7.3.1.0'

        $assemblyName = 'Microsoft.IdentityModel.Validators'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-7.3.1.0' -newVersion:'7.3.1.0'

        $assemblyName = 'Microsoft.Graph'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-3.19.0.0' -newVersion:'3.19.0.0'

        $assemblyName = 'Microsoft.Graph.Core'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-1.22.0.0' -newVersion:'1.22.0.0'


        # Replicating changes for webconfig from https://msdyneng.visualstudio.com/DefaultCollection/AX%20Servicing/_git/PackageInfrastructure/pullrequest/256704
        # because that it increments versions added by https://msdyneng.visualstudio.com/DefaultCollection/AX%20Servicing/_git/PackageInfrastructure/pullrequest/244022
        $assemblyName = 'System.Collections.Immutable'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'b03f5f7f11d50a3a' -oldVersion:'0.0.0.0-6.0.0.0' -newVersion:'6.0.0.0' -culture:'neutral'

        $assemblyName = 'System.Reflection.Metadata'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'b03f5f7f11d50a3a' -oldVersion:'0.0.0.0-6.0.0.1' -newVersion:'6.0.0.1' -culture:'neutral'
        # EndReplicating
    }

    #PU65 or greater
    if ($PlatformReleaseVersion -gt 7279) #7279 is PU64
    {
        # Replicating changes for webconfig from https://msdyneng.visualstudio.com/DefaultCollection/AX%20Servicing/_git/PackageInfrastructure/pullrequest/262184
        # Add redirect of Microsoft.Bcl.AsyncInterfaces
        $assemblyName = 'Microsoft.Bcl.AsyncInterfaces'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'cc7b13ffcd2ddd51' -oldVersion:'0.0.0.0-6.0.0.0' -newVersion:'6.0.0.0'

        # Add redirect of Microsoft.Extensions.Primitives
        $assemblyName = 'Microsoft.Extensions.Primitives'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-3.1.28.0' -newVersion:'3.1.28.0'


        # Add redirect of Microsoft.Extensions.DependencyInjection
        $assemblyName = 'Microsoft.Extensions.DependencyInjection'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-3.1.28.0' -newVersion:'3.1.28.0'

        # Add redirect of Microsoft.Extensions.DependencyInjection.Abstractions
        $assemblyName = 'Microsoft.Extensions.DependencyInjection.Abstractions'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-3.1.28.0' -newVersion:'3.1.28.0'

        # Add redirect of Microsoft.Extensions.Options
        $assemblyName = 'Microsoft.Extensions.Options'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-3.1.28.0' -newVersion:'3.1.28.0'

        # Add redirect of Microsoft.Extensions.Logging.Abstractions
        $assemblyName = 'Microsoft.Extensions.Logging.Abstractions'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-3.1.28.0' -newVersion:'3.1.28.0'

        # Add redirect of Microsoft.Extensions.Configuration.Abstractions
        $assemblyName = 'Microsoft.Extensions.Configuration.Abstractions'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-3.1.28.0' -newVersion:'3.1.28.0'

        # Add redirect of Microsoft.Extensions.Configuration
        $assemblyName = 'Microsoft.Extensions.Configuration'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-3.1.28.0' -newVersion:'3.1.28.0'

        # Add redirect of Microsoft.Extensions.Configuration.Binder
        $assemblyName = 'Microsoft.Extensions.Configuration.Binder'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-3.1.28.0' -newVersion:'3.1.28.0'

        # Add redirect of Microsoft.Extensions.Logging
        $assemblyName = 'Microsoft.Extensions.Logging'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-3.1.28.0' -newVersion:'3.1.28.0'

        # Add redirect of Microsoft.Extensions.Configuration.EnvironmentVariables
        $assemblyName = 'Microsoft.Extensions.Configuration.EnvironmentVariables'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-3.1.28.0' -newVersion:'3.1.28.0'

        # Add redirect of Microsoft.Extensions.Caching.Abstractions
        $assemblyName = 'Microsoft.Extensions.Caching.Abstractions'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-3.1.28.0' -newVersion:'3.1.28.0'

        # Add redirect of Microsoft.Extensions.Caching.Memory
        $assemblyName = 'Microsoft.Extensions.Caching.Memory'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-3.1.28.0' -newVersion:'3.1.28.0'

        # Add redirect of Microsoft.Extensions.Logging.Configuration
        $assemblyName = 'Microsoft.Extensions.Logging.Configuration'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-3.1.28.0' -newVersion:'3.1.28.0'

        # Add redirect of Microsoft.Extensions.Options.ConfigurationExtensions
        $assemblyName = 'Microsoft.Extensions.Options.ConfigurationExtensions'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-3.1.28.0' -newVersion:'3.1.28.0'

        # Add redirect of System.ComponentModel.Annotations
        $assemblyName = 'System.ComponentModel.Annotations'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'adb9793829ddae60' -oldVersion:'0.0.0.0-3.1.28.0' -newVersion:'3.1.28.0'

        # Add redirect of Microsoft.Powerapps.Coreframework
        $assemblyName = 'CoreFramework'
        if (Get-DependentAssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-DependentAssemblyBinding -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
        Add-DependencyAssembly -xmlDoc:$xmlDoc -assemblyName:$assemblyName -publickey:'31bf3856ad364e35' -oldVersion:'0.0.0.0-3.42.2277.41' -newVersion:'3.42.2277.41' -culture:'neutral'
        # EndReplicating
    }

    $xmlDoc.Save($batchConfig);
}

function Upgrade-WebConfig-AssemblyReferences([string] $webConfig)
{
    [System.Xml.XmlDocument] $xmlDoc = New-Object System.Xml.XmlDocument
    $xmlDoc.Load($webconfig)

    $assembliesNode = $xmlDoc.SelectSingleNode("/configuration/location/system.web/compilation/assemblies")

    $assemblyName = 'Microsoft.Dynamics.AX.Configuration.Base'
    if (!(Get-AssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc))
    {
        Add-NewAssembly -assemblyName:$assemblyName -parentNode:$assembliesNode -xmlDoc:$xmlDoc
    }
    $assemblyName = 'System.Web.Http'
    if (!(Get-AssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc))
    {
        Add-NewAssembly -assemblyName:$assemblyName -parentNode:$assembliesNode -xmlDoc:$xmlDoc
    }
    $assemblyName = 'System.Web.Http.WebHost'
    if (!(Get-AssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc))
    {
        Add-NewAssembly -assemblyName:$assemblyName -parentNode:$assembliesNode -xmlDoc:$xmlDoc
    }
    $assemblyName = 'System.Net.Http'
    if (!(Get-AssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc))
    {
        Add-NewAssembly -assemblyName:$assemblyName -parentNode:$assembliesNode -xmlDoc:$xmlDoc
    }
    if ($PlatformReleaseVersion -gt 4641)
    {
        $assemblyName = 'System.Net.Http.Formatting'
        if (!(Get-AssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc))
        {
            Add-NewAssembly -assemblyName:$assemblyName -parentNode:$assembliesNode -xmlDoc:$xmlDoc
        }
    }
    $assemblyName = 'Microsoft.Dynamics.Client.InteractionService'
    if (!(Get-AssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc))
    {
        Add-NewAssembly -assemblyName:$assemblyName -parentNode:$assembliesNode -xmlDoc:$xmlDoc
    }

    #Check if update 24 or later
    if ($PlatformReleaseVersion -ge 5179)
    {
        $assemblyName = 'Microsoft.Dynamics.ServiceFramework.Xpp'
        if (!(Get-AssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc))
        {
            Add-NewAssembly -assemblyName:$assemblyName -parentNode:$assembliesNode -xmlDoc:$xmlDoc
        }
        $assemblyName = 'System.Runtime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
        if (!(Get-AssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc))
        {
            Add-NewAssembly -assemblyName:$assemblyName -parentNode:$assembliesNode -xmlDoc:$xmlDoc
        }
        $assemblyName = 'Bond'
        if (!(Get-AssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc))
        {
            Add-NewAssembly -assemblyName:$assemblyName -parentNode:$assembliesNode -xmlDoc:$xmlDoc
        }
        $assemblyName = 'Bond.IO'
        if (!(Get-AssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc))
        {
            Add-NewAssembly -assemblyName:$assemblyName -parentNode:$assembliesNode -xmlDoc:$xmlDoc
        }
        $assemblyName = 'Bond.JSON'
        if (!(Get-AssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc))
        {
            Add-NewAssembly -assemblyName:$assemblyName -parentNode:$assembliesNode -xmlDoc:$xmlDoc
        }
        $assemblyName = 'Microsoft.Cloud.InstrumentationFramework.Events'
        if (!(Get-AssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc))
        {
            Add-NewAssembly -assemblyName:$assemblyName -parentNode:$assembliesNode -xmlDoc:$xmlDoc
        }
        $assemblyName = 'Microsoft.Cloud.InstrumentationFramework.Health'
        if (!(Get-AssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc))
        {
            Add-NewAssembly -assemblyName:$assemblyName -parentNode:$assembliesNode -xmlDoc:$xmlDoc
        }
        $assemblyName = 'Microsoft.Cloud.InstrumentationFramework.Metrics'
        if (!(Get-AssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc))
        {
            Add-NewAssembly -assemblyName:$assemblyName -parentNode:$assembliesNode -xmlDoc:$xmlDoc
        }
        $assemblyName = 'Microsoft.Extensions.DependencyInjection.Abstractions'
        if (!(Get-AssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc))
        {
            Add-NewAssembly -assemblyName:$assemblyName -parentNode:$assembliesNode -xmlDoc:$xmlDoc
        }
        $assemblyName = 'Microsoft.Extensions.Logging'
        if (!(Get-AssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc))
        {
            Add-NewAssembly -assemblyName:$assemblyName -parentNode:$assembliesNode -xmlDoc:$xmlDoc
        }
        $assemblyName = 'Microsoft.Extensions.Logging.Abstractions'
        if (!(Get-AssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc))
        {
            Add-NewAssembly -assemblyName:$assemblyName -parentNode:$assembliesNode -xmlDoc:$xmlDoc
        }
        $assemblyName = 'Newtonsoft.Json'
        if (!(Get-AssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc))
        {
            Add-NewAssembly -assemblyName:$assemblyName -parentNode:$assembliesNode -xmlDoc:$xmlDoc
        }
    }

    #Check if update 26 or later
    if ($PlatformReleaseVersion -ge 5257)
    {
        $assemblyName = 'Microsoft.Dynamics.ApplicationPlatform.Client.Instrumentation'
        if (!(Get-AssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc))
        {
            Add-NewAssembly -assemblyName:$assemblyName -parentNode:$assembliesNode -xmlDoc:$xmlDoc
        }
    }

    # Check if update 40 or later
    if ($PlatformReleaseVersion -ge 5839)
    {
        $assemblyName = 'Microsoft.Dynamics.Authentication.Client'
       
        if (!(Get-AssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc))
        {
            Add-NewAssembly -assemblyName:$assemblyName -parentNode:$assembliesNode -xmlDoc:$xmlDoc
        }
    }

    # Check if update 43 or later
    if ($PlatformReleaseVersion -ge 5990)
    {
        $assemblyName = 'Microsoft.Dynamics.InstrumentationFramework'
        
        if (!(Get-AssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc))
        {
            Add-NewAssembly -assemblyName:$assemblyName -parentNode:$assembliesNode -xmlDoc:$xmlDoc
        }

        $assemblyName = 'IfxMetricExtensionsManaged'
        
        if (!(Get-AssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc))
        {
            Add-NewAssembly -assemblyName:$assemblyName -parentNode:$assembliesNode -xmlDoc:$xmlDoc
        }        
    }

    # Check if update 52 or later
    if ($PlatformReleaseVersion -ge 6401)
    {
        # If a "System.IO.Compression" entry exists, remove it so it won't conflict with the 
        # "System.IO.Compression, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
        # entry that is being added below
        if(Get-AssemblyExists -assemblyName:"System.IO.Compression" -xmlDoc:$xmlDoc)
        {
            Remove-Assembly -assemblyName:"System.IO.Compression" -xmlDoc:$xmlDoc
        }

        $assemblies = @("Microsoft.Dynamics.AX.Metadata", "Microsoft.Dynamics.AX.Metadata.Core", "Microsoft.Dynamics.AX.Metadata.Storage", "System.IO.Compression, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")

        $assemblies | %{
            if (!(Get-AssemblyExists -assemblyName:$_ -xmlDoc:$xmlDoc))
            {
                Add-NewAssembly -assemblyName:$_ -parentNode:$assembliesNode -xmlDoc:$xmlDoc
            }
        }
    }

    # Check if update 56 or later
    if ($PlatformReleaseVersion -ge 6719)
    {
        $assemblyName = 'Microsoft.Dynamics.Platform.Integration.Services.Grpc'
       
        if (!(Get-AssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc))
        {
            Add-NewAssembly -assemblyName:$assemblyName -parentNode:$assembliesNode -xmlDoc:$xmlDoc
        }
    }

    #PU65 or greater
    if ($PlatformReleaseVersion -gt 7279) #7279 is PU64
    {
        $assemblyName = 'netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'
        if (!(Get-AssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc))
        {
            Add-NewAssembly -assemblyName:$assemblyName -parentNode:$assembliesNode -xmlDoc:$xmlDoc
        }
    }

    $xmlDoc.Save($webconfig)
}

function Add-NewAssembly([string] $assemblyName, [System.Xml.XmlNode] $parentNode, [System.Xml.XmlDocument] $xmlDoc)
{
    [System.Xml.XmlElement] $element = $xmlDoc.CreateElement("add")
    $newAttribute = $xmlDoc.CreateAttribute('assembly')
    $newAttribute.Value = $assemblyName

    $element.Attributes.Append($newAttribute)

    $parentNode.AppendChild($element)
}

function Upgrade-WebConfig-NewKeys([string]$webconfig)
{
    [System.Xml.XmlDocument] $xmlDoc = New-Object System.Xml.XmlDocument
    $xmlDoc.Load($webconfig)

    $appsettings = $xmlDoc.SelectSingleNode("/configuration/appSettings")

    $key = 'Aad.AADValidAudience'
    $value = 'microsoft.erp'
    if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
    {
        Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
    }

    $key = 'Aad.MSAIdentityProvider'
    $value = 'live.com'
    if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
    {
        Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
    }

    $key = 'Aad.MSAOutlook'
    $value = 'outlook.com'
    if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
    {
        Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
    }

    $key = 'BiReporting.IsSSRSEnabled'
    $value = 'true'
    if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
    {
        Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
    }

    $key = 'CertificateHandler.HandlerType'
    $value = 'Microsoft.Dynamics.AX.Configuration.CertificateHandler.LocalStoreCertificateHandler'
    if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
    {
        Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
    }

    $key = 'LCS.BpmAuthClient'
    $value = 'SysBpmCertClient'
    if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
    {
        Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
    }

    $key = 'LCS.ProjectId'
    $value = ''
    if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
    {
        Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
    }

    $key = 'DataAccess.FlightingEnvironment'
    $value = ''
    if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
    {
        Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
    }

    $key = 'DataAccess.FlightingCertificateThumbprint'
    $value = ''
    if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
    {
        Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
    }

    $key = 'DataAccess.FlightingServiceCatalogID'
    $value = '12719367'
    if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
    {
        Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
    }

    $key = 'DataAccess.FlightingServiceCacheFolder'
    $value = 'CarbonRuntimeBackup'
    if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
    {
        Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
    }

    $key = 'Aos.EncryptionEngineCacheExpirationInMinutes'
    $value = '720'
    if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
    {
        Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
    }

    #Check if update 7 or later
    if ($PlatformReleaseVersion -ge 4542)
    {
        $key = 'PowerBIEmbedded.AccessKey'
        $value = ''
        if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
        {
            Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
        }

        $key = 'PowerBIEmbedded.AccessKey2'
        $value = ''
        if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
        {
            Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
        }

        $key = 'PowerBIEmbedded.ApiUrl'
        $value = 'https://api.powerbi.com'
        if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
        {
            Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
        }

        $key = 'PowerBIEmbedded.IsPowerBIEmbeddedEnabled'
        $value = 'false'
        if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
        {
            Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
        }

        $key = 'PowerBIEmbedded.WorkspaceCollectionName'
        $value = ''
        if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
        {
            Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
        }
    }

    #Check if update 4
    if ($PlatformReleaseVersion -ge 4425)
    {
        $key = 'License.LicenseEnforced'
        $value = '1'
        if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
        {
            Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
        }
        $key = 'License.D365EnterprisePlanId'
        $value = '95d2cd7b-1007-484b-8595-5e97e63fe189;112847d2-abbb-4b47-8b62-37af73d536c1'
        if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
        {
            Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
        }
        $key = 'License.D365UniversalPlanId'
        $value = 'f5aa7b45-8a36-4cd1-bc37-5d06dea98645'
        if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
        {
            Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
        }
        $key = 'Infrastructure.AzureKeyVaultName'
        $value = "[Topology/Configuration/Setting[@Name='AzureKeyVaultName']/@Value]"
        if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
        {
            Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
        }
    }

    #Check if update 11 or later
    if ($PlatformReleaseVersion -ge 4647)
    {
        $key = 'Aos.DeploymentName'
        $value = "initial"
        if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
        {
            Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
        }
        $key = 'Infrastructure.SDSAzureSubscriptionId'
        $value = ""
        if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
        {
            Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
        }
        $key = 'Infrastructure.SDSAzureResourceGroup'
        $value = ""
        if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
        {
            Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
        }
        $key = 'Infrastructure.SDSAzureDirectoryId'
        $value = ""
        if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
        {
            Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
        }
        $key = 'Infrastructure.SDSApplicationID'
        $value = ""
        if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
        {
            Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
        }
        $key = 'Infrastructure.SDSApplicationKey'
        $value = ""
        if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
        {
            Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
        }
        $key = 'Aos.ForceEnumValuesOnMetadataLoad'
        $value = "True"
        if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
        {
            Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
        }
    }

    $isPPE = $false
    $isChina = $false

    #Check if update 12 or later
    if ($PlatformReleaseVersion -ge 4709)
    {
        $graphAPIkey = 'GraphApi.GraphAPIAADResource'
        if (Get-KeyExists -key:$graphAPIkey -xmlDoc:$xmlDoc)
        {
            $graphAPIValue = Get-KeyValue -key $graphAPIkey -xmlDoc $xmlDoc
            if ($graphAPIValue -eq "https://graph.ppe.windows.net")
            {
                $isPPE = $true;
            }
            elseif ($graphAPIValue -eq "https://graph.chinacloudapi.cn")
            {
                $isChina = $true;
            }
        }

        $key = 'GraphAPI.MicrosoftGraphResource'
        $value = 'https://graph.microsoft.com'

        if ($isPPE)
        {
            $value = 'https://graph.microsoft-ppe.com'
        }
        elseif ($isChina)
        {
            $value = 'https://microsoftgraph.chinacloudapi.cn'
        }

        if (Get-KeyExists -key:$key -xmlDoc:$xmlDoc)
        {
            $oldMicrosoftGraphValue = Get-KeyValue -key $key -xmlDoc $xmlDoc
            if (!($oldMicrosoftGraphValue -eq $value))
            {
                Update-KeyValue -key $key -value $value -xmlDoc $xmlDoc
            }
        }
        else
        {
            Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
        }

        $key = 'GraphApi.MaxTries'
        $value = "5"
        if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
        {
            Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
        }
        $key = 'GraphApi.BasedDelayTime'
        $value = "200"
        if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
        {
            Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
        }

        $key = 'GraphApi.MaxListTaskWaitTime'
        $value = "6000000"
        if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
        {
            Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
        }
        else
        {
            Update-KeyValue -key $key -value $value -xmlDoc $xmlDoc
        }

        $key = 'GraphApi.MaxTaskWaitTime'
        $value = "600000"
        if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
        {
            Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
        }
        else
        {
            Update-KeyValue -key $key -value $value -xmlDoc $xmlDoc
        }

        $key = 'Monitoring.ActivityMetricNamespace'
        $value = "Microsoft.Dynamics.Aos"
        if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
        {
            Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
        }

        $key = 'Monitoring.CustomMetricNamespace'
        $value = "Microsoft.Dynamics.Aos"
        if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
        {
            Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
        }

        $key = 'Monitoring.IFXSessionName'
        $value = "Dynamics.Operations.IfxSession"
        if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
        {
            Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
        }
    }

    #Check if update 22 or later
    if ($PlatformReleaseVersion -ge 5095)
    {
        $key = 'CertificateHandler.IsMSIKeyVault'
        $value = "false"
        if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
        {
            Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
        }
        $key = 'CertificateHandler.MSIEndpoint'
        $value = "MSIEndpointDefault"
        if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
        {
            Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
        }
        $key = 'CertificateHandler.MSIResource'
        $value = "MSIResourceDefault"
        if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
        {
            Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
        }
        $key = 'CertificateHandler.KeyVaultUrl'
        $value = "KeyVaultUrlDefault"
        if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
        {
            Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
        }
        $key = 'CertificateHandler.KeyVaultCacheName'
        $value = "AXKeyVaultCacheName"
        if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
        {
            Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
        }
        $key = 'CertificateHandler.KeyVaultCacheExpirationInMilliseconds'
        $value = "86400000"
        if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
        {
            Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
        }
        else
        {
            Update-KeyValue -key $key -value $value -xmlDoc $xmlDoc
		}
        $key = 'CertificateHandler.KeyVaultHandlerType'
        $value = "Microsoft.Dynamics.AX.Security.KeyVaultHelper.KeyVaultCertificateHandler, Microsoft.Dynamics.AX.Security.KeyVaultHelper, Version=7.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
        if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
        {
            Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
        }
        $key = 'CertificateHandler.LocalSecretHandlerType'
        $value = "Microsoft.Dynamics.ApplicationPlatform.Environment.SecretHandler.LocalSecretHandler"
        if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
        {
            Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
        }
        $key = 'CertificateHandler.KeyVaultSecretHandlerType'
        $value = "Microsoft.Dynamics.AX.Security.KeyVaultHelper.KeyVaultSecretHandler, Microsoft.Dynamics.AX.Security.KeyVaultHelper, Version=7.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
        if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
        {
            Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
        }

        # Commerce Configuration Update
        $key = 'Commerce.DiagnosticsFilter.MinLevel'
        $value = "Informational"
        if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
        {
            Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
        }
        $key = 'Commerce.DiagnosticsFilter.ExcludedPrivacyDataTypes'
        $value = "AccessControlData;CustomerContent;EndUserIdentifiableInformation"
        if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
        {
            Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
        }
        $key = 'Commerce.RetailSelfServiceInstallers.SideLoadingKey'
        $value = ""
        if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
        {
            Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
        }
        $key = 'Commerce.RetailSelfServiceInstallers.HardwareStationAppinsightsInstrumentationKey'
        $value = ""
        if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
        {
            Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
        }
        $key = 'Commerce.RetailSelfServiceInstallers.ClientAppinsightsInstrumentationKey'
        $value = ""
        if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
        {
            Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
        }
        $key = 'Commerce.RetailSelfServiceInstallers.CloudPosAppinsightsInstrumentationKey'
        $value = ""
        if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
        {
            Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
        }
        $key = 'Commerce.RetailSelfServiceInstallers.RetailServerAppinsightsInstrumentationKey'
        $value = ""
        if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
        {
            Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
        }
        $key = 'Commerce.RetailSelfServiceInstallers.AsyncClientAppinsightsInstrumentationKey'
        $value = ""
        if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
        {
            Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
        }
        $key = 'Commerce.RetailSelfServiceInstallers.WindowsPhoneAppinsightsInstrumentationKey'
        $value = ""
        if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
        {
            Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
        }
        $key = 'Commerce.RetailSelfServiceInstallers.AsyncServerConnectorServiceAppinsightsInstrumentationKey'
        $value = ""
        if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
        {
            Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
        }
        $key = 'Commerce.RetailSelfServiceInstallers.RealtimeServiceAx63AppinsightsInstrumentationKey'
        $value = ""
        if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
        {
            Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
        }
    }

    # AOS trusted issuers
    $issuerMicrosoftTenant = 'https://sts.windows.net/72f988bf-86f1-41af-91ab-2d7cd011db47/'
    $issuerPmeTenant = 'https://sts.windows.net/975f013f-7f24-47e8-a7d3-abc4752bf346/'
    $issuerRetailTenant = 'https://sts.windows.net/57206206-ec82-4579-9724-0a098ed1b99f/'
    $issuerRetailPpeTenant = 'https://sts.windows.net/34b54b07-9b04-4369-839c-380f28f3e0fe/'

    #Check if update 30 or later
    if ($PlatformReleaseVersion -ge 5378)
    {
        # AAD Trusted Issuers - these issuers will be trusted to make call AOS (AppIds need to be allowlisted with AOS DB first)
        $key = 'Aad.TrustedIssuers'
        $aadTrustedIssuers = @()
        $aadTrustedIssuersMetadata = ""

        # Out of the box configuration only for non-Mooncake environments
        if (-not $isChina)
        {
            if ($isPPE)
            {
                # For PPE trust Retail Test Tenant and Microsoft Tenant
                $aadTrustedIssuers = $issuerMicrosoftTenant, $issuerRetailPpeTenant
            }
            else
            {
                # For PROD, trust Retail PROD Tenant and Microsoft Tenant
                $aadTrustedIssuers = $issuerMicrosoftTenant, $issuerRetailTenant
            }

            # Trusted issuer metadata is always AAD Prod
            $aadTrustedIssuersMetadata = "https://login.windows.net/common/FederationMetadata/2007-06/FederationMetadata.xml"
        }

        # validate whether required trusted issuers already set
        $node = $xmlDoc.SelectSingleNode("//add[@key='$key']")
        if ($node) {
            $oldNodeValue = $node.value
            $issuersSplit = @($oldNodeValue -split ';' | where-object { -not [String]::IsNullOrWhiteSpace($_) } | foreach-object { $_.Trim() } )
            foreach($issuer in $aadTrustedIssuers)
            {
                if($issuersSplit -notcontains $issuer)
                {
                    $issuersSplit += $issuer
                }
            }
            $node.value = $issuersSplit -join ';'

            Write-Output "Setting $key value: Old value = '$oldNodeValue' new value = '$($node.value)' when isChina=$isChina, isPPE=$isPPE"
        }
        elseif($aadTrustedIssuers.Length -gt 0) {
            $aadTrustedIssuersValue = $aadTrustedIssuers -join ';'
            Add-NewKey -key $key -value $aadTrustedIssuersValue -parentNode $appsettings -xmlDoc $xmlDoc
            Write-Output "Adding $key with value = '$aadTrustedIssuersValue' when isChina=$isChina, isPPE=$isPPE"
        }

        # Trusted issuers authority metadata endpoint
        if($aadTrustedIssuersMetadata)
        {
            $key = 'Aad.TrustedIssuersMetadataAddress'
            $node = $xmlDoc.SelectSingleNode("//add[@key='$key']")
            if (-not $node)
            {
                Add-NewKey -key $key -value $aadTrustedIssuersMetadata -parentNode $appsettings -xmlDoc $xmlDoc
                Write-Output "Adding $key with value = '$aadTrustedIssuersMetadata' when isChina=$isChina"
            }
            else
            {
                $oldNodeValue = $node.Value
                $node.Value = $aadTrustedIssuersMetadata
                Write-Output "Setting $key value: Old value = '$oldNodeValue' new value = '$($node.value)' when isChina=$isChina"
            }
        }

        # Allow event handlers and Chain Of Command subscriptions initialize in parallel
        $key = 'EventsAndCoCHandlersInitConcurrently'
        $value = "True"
        if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
        {
            Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
        }

        $key = 'Flow.MyFlowsUrl'
        $value = 'https://go.microsoft.com/fwlink/?linkid=2122475'
        if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
        {
            Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
        }

        $key = 'Flow.CreateAFlowUrl'
        $value = 'https://go.microsoft.com/fwlink/?linkid=2122580'
        if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
        {
            Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
        }
    }
    else
    {
        Write-Output "The PlatformReleaseVersion $PlatformReleaseVersion is less than 5378 (10.0.6). So, skipping configuring configs: Aad.TrustedIssuers, Aad.TrustedIssuersMetadataAddress, EventsAndCoCHandlersInitConcurrently, Flow.MyFlowsUrl, Flow.CreateAFlowUrl"
    }

    # Add PME Tenant ID to the Aad.TrustedIssuers key. Must do this regardless of the platform + application versions
    $key = "Aad.TrustedIssuers"

    Write-Log "Ensuring that key: $key contains value: $issuerPmeTenant"

    if (Get-KeyExists -key:$key -xmlDoc:$xmlDoc)
    {
        $oldValue = ""
        $newValue = ""

        # get the current value
        [System.Xml.XmlNode] $node = $xmlDoc.SelectSingleNode("//add[@key='$key']")
        if ($null -ne $node)
        {
            $oldValue = $node.Value
        }

        if ($oldValue.Length -eq 0)
        {
            # The value is currently empty, so add both Microsoft and PME tenants to the list
            $newValue = "$issuerMicrosoftTenant;$issuerPmeTenant"
        }
        else
        {
            # add the PME issuer if necessary
            $oldValueSplit = $oldValue -split ";"
            if ($oldValueSplit -notcontains $issuerPmeTenant)
            {
                $newValue = "$oldValue;$issuerPmeTenant"
            }
        }

        if ($newValue.Length -gt 0)
        {
            Write-Log "Updading key $key, setting value to $newValue"
            Update-KeyValue -key $key -value $newValue -xmlDoc $xmlDoc
        }
    }
    else
    {
        # The value is currently empty, so add both Microsoft and PME tenants to the list
        $newValue = "$issuerMicrosoftTenant;$issuerPmeTenant"

        Write-Log "Adding key $key, setting value to $newValue"

        # Key Aad.TrustedIssuers does not exist, so create and populate it
        Add-NewKey -key $key -value $newValue -parentNode $appsettings -xmlDoc $xmlDoc
    }

    # Check if update 40 or later
    if ($PlatformReleaseVersion -ge 5839)
    {
        $key = 'Infrastructure.S2SCertSubjectName'
        $value = ""

        # Get S2S certificate by CertificateHandler
        $s2scert = Get-S2SCertificate

        if ($s2scert -eq $null)
        {
            # Fallback to load certificate from local store
            $s2sCertThumbprintKey = 'Infrastructure.S2SCertThumbprint'
            if (Get-KeyExists -key:$s2sCertThumbprintKey -xmlDoc:$xmlDoc)
            {
                try
                {
                    $s2sCertThumbprint = Get-KeyValue -key $s2sCertThumbprintKey -xmlDoc $xmlDoc
                    if ($s2sCertThumbprint)
                    {                    
                        $s2scert = Get-ChildItem -Path Cert:\LocalMachine\My\$s2sCertThumbprint
                    }
                }
                catch
                {
                    # no-op
                }
            }
        }

        if($s2scert -ne $null)
        {
            $value = $s2scert.Subject
        }

        # Add new s2s certificate subject name if it does not exist
        if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
        {
            Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
        }
        elseif ($value -ne "" -and (Get-KeyValue -key $key -xmlDoc $xmlDoc) -ne $value)
        {
            Update-KeyValue -key $key -value $value -xmlDoc $xmlDoc
        }

        $key = 'LCS.AppId'
        $value = "913c6de4-2a4a-4a61-a9ce-945d2b2ce2e0"
        if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
        {
            Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
        }
    }

    # Check if update 43 or later
    if ($PlatformReleaseVersion -ge 5990)
    {
        #  <add key="Monitoring.BucketSize" value="250" />
        #  <add key="Monitoring.BucketCount" value="50" />
        #  <add key="Monitoring.MinimumValueInMilliseconds" value="10" />

        $key = 'Monitoring.BucketSize'
        $value = "250"
        if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
        {
            Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
        }

        $key = 'Monitoring.BucketCount'
        $value = "50"
        if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
        {
            Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
        }

        $key = 'Monitoring.MinimumValueInMilliseconds'
        $value = "10"
        if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
        {
            Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
        }
    }

    # save the web.config file
    $xmlDoc.Save($webconfig);
}

function Upgrade-HttpProtocol-NewNames([string]$webconfig)
{
    [System.Xml.XmlDocument] $xmlDoc = New-Object System.Xml.XmlDocument
    $xmlDoc.Load($webconfig)

    $appsettings = $xmlDoc.SelectSingleNode("/configuration/system.webServer/httpProtocol/customHeaders")

    #Check if update 11 or later
    if ($PlatformReleaseVersion -ge 4647)
    {
        $name = 'Strict-Transport-Security'
        $value = "max-age=31536000; includeSubDomains"
        if (!(Get-NameExists -name:$name -xmlDoc:$xmlDoc))
        {
            Add-NewName -name $name -value $value -parentNode $appsettings -xmlDoc $xmlDoc
        }
    }

    $xmlDoc.Save($webconfig);
}

function Upgrade-WebConfig-Add-StaticContent([string]$webconfig)
{
	[System.Xml.XmlDocument] $xmlDoc = New-Object System.Xml.XmlDocument
    $xmlDoc.Load($webconfig)

	#Check if post update 26
    if ($PlatformReleaseVersion -gt 5257)
    {
		$staticContentNode = $xmlDoc.SelectSingleNode("/configuration/system.webServer/staticContent")
		$removeNode = $xmlDoc.SelectSingleNode("/configuration/system.webServer/staticContent/remove[@fileExtension='.properties']")
		$mimeMapNode = $xmlDoc.SelectSingleNode("/configuration/system.webServer/staticContent/mimeMap[@fileExtension='.properties']")

		if ($removeNode -eq $null)
		{
			Write-Log "Start adding system.webServer/staticContent/remove fileExtension node"

			[System.Xml.XmlElement] $removeElement = $xmlDoc.CreateElement("remove")
			$fileExtensionAttribute = $xmlDoc.CreateAttribute('fileExtension')
			$fileExtensionAttribute.Value = '.properties'
			$removeElement.Attributes.Append($fileExtensionAttribute)

			$staticContentNode.AppendChild($removeElement)
		}

		if ($mimeMapNode -eq $null)
		{
			Write-Log "Start adding system.webServer/staticContent/mimeMap fileExtension node"

			[System.Xml.XmlElement] $mimeMapElement = $xmlDoc.CreateElement("mimeMap")
			$fileExtensionAttribute = $xmlDoc.CreateAttribute('fileExtension')
			$fileExtensionAttribute.Value = '.properties'
			$mimeTypeAttribute = $xmlDoc.CreateAttribute('mimeType')
			$mimeTypeAttribute.Value = 'text/plain'
			$mimeMapElement.Attributes.Append($fileExtensionAttribute)
			$mimeMapElement.Attributes.Append($mimeTypeAttribute)

			$staticContentNode.AppendChild($mimeMapElement)
		}
	}

	$xmlDoc.Save($webconfig)
}

function Upgrade-WebConfig-Add-RequestHandlers([string]$webconfig)
{
    [System.Xml.XmlDocument] $xmlDoc = New-Object System.Xml.XmlDocument
    $xmlDoc.Load($webconfig)

    # Check if post update 36 (e.g. PU37+)
    if ($PlatformReleaseVersion -gt 5688)
    {
        $handlersNode = $xmlDoc.SelectSingleNode("/configuration/system.webServer/handlers")

        # Ensure DefaultClient handler exists
        $defaultClientNode = $xmlDoc.SelectSingleNode("/configuration/system.webServer/handlers/add[@name='DefaultClient']")
        if ($defaultClientNode -eq $null)
        {
            Write-Log "Start adding system.webServer/handlers/add DefaultClient node"

            [System.Xml.XmlElement] $defaultClientElement = $xmlDoc.CreateElement("add")

            $nameAttribute = $xmlDoc.CreateAttribute("name")
            $nameAttribute.Value = "DefaultClient"
            $defaultClientElement.Attributes.Append($nameAttribute)

            $pathAttribute = $xmlDoc.CreateAttribute("path")
            $pathAttribute.Value = "/"
            $defaultClientElement.Attributes.Append($pathAttribute)

            $verbAttribute = $xmlDoc.CreateAttribute("verb")
            $verbAttribute.Value = "*"
            $defaultClientElement.Attributes.Append($verbAttribute)

            $typeAttribute = $xmlDoc.CreateAttribute("type")
            $typeAttribute.Value = "System.Web.Handlers.TransferRequestHandler"
            $defaultClientElement.Attributes.Append($typeAttribute)

            $preConditionAttribute = $xmlDoc.CreateAttribute("preCondition")
            $preConditionAttribute.Value = "integratedMode,runtimeVersionv4.0"
            $defaultClientElement.Attributes.Append($preConditionAttribute)

            $handlersNode.AppendChild($defaultClientElement)
        }

        # Ensure DefaultClient-HTM handler exists
        $defaultClientHtmNode = $xmlDoc.SelectSingleNode("/configuration/system.webServer/handlers/add[@name='DefaultClient-HTM']")
        if ($defaultClientHtmNode -eq $null)
        {
            Write-Log "Start adding system.webServer/handlers/add DefaultClient-HTM node"

            [System.Xml.XmlElement] $defaultClientHtmElement = $xmlDoc.CreateElement("add")

            $nameAttribute = $xmlDoc.CreateAttribute("name")
            $nameAttribute.Value = "DefaultClient-HTM"
            $defaultClientHtmElement.Attributes.Append($nameAttribute)

            $pathAttribute = $xmlDoc.CreateAttribute("path")
            $pathAttribute.Value = "default.htm"
            $defaultClientHtmElement.Attributes.Append($pathAttribute)

            $verbAttribute = $xmlDoc.CreateAttribute("verb")
            $verbAttribute.Value = "*"
            $defaultClientHtmElement.Attributes.Append($verbAttribute)

            $typeAttribute = $xmlDoc.CreateAttribute("type")
            $typeAttribute.Value = "System.Web.Handlers.TransferRequestHandler"
            $defaultClientHtmElement.Attributes.Append($typeAttribute)

            $preConditionAttribute = $xmlDoc.CreateAttribute("preCondition")
            $preConditionAttribute.Value = "integratedMode,runtimeVersionv4.0"
            $defaultClientHtmElement.Attributes.Append($preConditionAttribute)

            $handlersNode.AppendChild($defaultClientHtmElement)
        }

        # Ensure DefaultDebugClient-HTM handler exists
        $defaultDebugClientHtmNode = $xmlDoc.SelectSingleNode("/configuration/system.webServer/handlers/add[@name='DefaultDebugClient-HTM']")
        if ($defaultDebugClientHtmNode -eq $null)
        {
            Write-Log "Start adding system.webServer/handlers/add DefaultDebugClient-HTM node"
            $defaultDebugClientHtmElement = $xmlDoc.CreateElement("add")

            $nameAttribute = $xmlDoc.CreateAttribute("name")
            $nameAttribute.Value = "DefaultDebugClient-HTM"
            $defaultDebugClientHtmElement.Attributes.Append($nameAttribute)

            $pathAttribute = $xmlDoc.CreateAttribute("path")
            $pathAttribute.Value = "defaultdebug.htm"
            $defaultDebugClientHtmElement.Attributes.Append($pathAttribute)

            $verbAttribute = $xmlDoc.CreateAttribute("verb")
            $verbAttribute.Value = "*"
            $defaultDebugClientHtmElement.Attributes.Append($verbAttribute)

            $typeAttribute = $xmlDoc.CreateAttribute("type")
            $typeAttribute.Value = "System.Web.Handlers.TransferRequestHandler"
            $defaultDebugClientHtmElement.Attributes.Append($typeAttribute)

            $preConditionAttribute = $xmlDoc.CreateAttribute("preCondition")
            $preConditionAttribute.Value = "integratedMode,runtimeVersionv4.0"
            $defaultDebugClientHtmElement.Attributes.Append($preConditionAttribute)

            $handlersNode.AppendChild($defaultDebugClientHtmElement)
        }

        # Check if post update 37 (e.g. PU38+)
        if ($PlatformReleaseVersion -gt 5746)
        {
            # Ensure ClientComputedScripts handler exists
            $clientComputedScriptsNode = $xmlDoc.SelectSingleNode("/configuration/system.webServer/handlers/add[@name='ClientComputedScripts']")
            if ($clientComputedScriptsNode -eq $null)
            {
                Write-Log "Start adding system.webServer/handlers/add ClientComputedScripts node"
                $clientComputedScriptsElement = $xmlDoc.CreateElement("add")

                $nameAttribute = $xmlDoc.CreateAttribute("name")
                $nameAttribute.Value = "ClientComputedScripts"
                $clientComputedScriptsElement.Attributes.Append($nameAttribute)

                $pathAttribute = $xmlDoc.CreateAttribute("path")
                $pathAttribute.Value = "scripts/computed"
                $clientComputedScriptsElement.Attributes.Append($pathAttribute)

                $verbAttribute = $xmlDoc.CreateAttribute("verb")
                $verbAttribute.Value = "*"
                $clientComputedScriptsElement.Attributes.Append($verbAttribute)

                $typeAttribute = $xmlDoc.CreateAttribute("type")
                $typeAttribute.Value = "System.Web.Handlers.TransferRequestHandler"
                $clientComputedScriptsElement.Attributes.Append($typeAttribute)

                $preConditionAttribute = $xmlDoc.CreateAttribute("preCondition")
                $preConditionAttribute.Value = "integratedMode,runtimeVersionv4.0"
                $clientComputedScriptsElement.Attributes.Append($preConditionAttribute)

                $handlersNode.AppendChild($clientComputedScriptsElement)
            }
        }
    }

    $xmlDoc.Save($webconfig)
}

function Upgrade-WebConfig-DeleteKeys([string]$webconfig)
{
    [System.Xml.XmlDocument] $xmlDoc = New-Object System.Xml.XmlDocument
    $xmlDoc.Load($webconfig)

    $key = 'HelpWiki.AuthorizationKey'
    if (Get-KeyExists -key:$key -xmlDoc:$xmlDoc)
    {
        Remove-Key -key $key -xmlDoc $xmlDoc
    }

    $key = 'HelpWiki.AuthorizationKeyValue'

    if (Get-KeyExists -key:$key -xmlDoc:$xmlDoc)
    {
        Remove-Key -key $key -xmlDoc $xmlDoc
    }

    $xmlDoc.Save($webconfig);
}

function Upgrade-WebConfig-updateKeys([string]$webconfig)
{
    [System.Xml.XmlDocument] $xmlDoc = New-Object System.Xml.XmlDocument
    $xmlDoc.Load($webconfig)

    # Update the Infrastructure.InternalServiceCertificateThumbprints key to include FRServiceUser certificate thumbprint
    $allowedUserIds = "FRServiceUser"
    if (Get-AllowedUserIdsExists -allowedUserIds:$allowedUserIds -xmlDoc:$xmlDoc)
    {
        $fRServiceUserThumbPrint = Get-AllowedUserIdsName -allowedUserIds:$allowedUserIds -xmlDoc:$xmlDoc

        $key = "Infrastructure.InternalServiceCertificateThumbprints"
        if (($fRServiceUserThumbPrint.GetValue(1)) -and (Get-KeyExists -key:$key -xmlDoc:$xmlDoc))
        {
            $oldValue = Get-KeyValue -key $key -xmlDoc $xmlDoc

            if (($oldValue.GetValue(1)))
            {
                $oldValue = $oldValue.GetValue(1)
                $fRServiceUserThumbPrint = $fRServiceUserThumbPrint.GetValue(1)
                if ((!$oldValue.Contains($fRServiceUserThumbPrint)))
                {
                    $newValue = $oldValue + ";$fRServiceUserThumbPrint"
                    Update-KeyValue -key:$key -value:$newValue -xmlDoc:$xmlDoc
                }
            }
            else
            {
                Update-KeyValue -key:$key -value:$fRServiceUserThumbPrint -xmlDoc:$xmlDoc
            }
        }
    }

    # Update the AppInsightsKey if it was the old production key to the new production key. Test keys are unchanged.
    $key = "OfficeApps.AppInsightsKey"
    if (Get-KeyExists -key:$key -xmlDoc:$xmlDoc)
    {
        $oldValue = Get-KeyValue -key $key -xmlDoc $xmlDoc
        if ($oldValue -eq "a8640c62-56a5-49c5-8d37-adcc48ac1523")
        {
            Write-Log "Updating OfficeApps.AppInsightsKey"
            Update-KeyValue -key $key -value "0e9ff251-74c0-4b3f-8466-c5345e5d4933" -xmlDoc $xmlDoc
        }
        else
        {
            Write-Log "Not updating OfficeApps.AppInsightsKey"
        }
    }

    # Update the HelpWiki.APIEndPoint key to the new production or test endpoint
    $key = "HelpWiki.APIEndPoint"
    if (Get-KeyExists -key:$key -xmlDoc:$xmlDoc)
    {
        $oldValue = Get-KeyValue -key $key -xmlDoc $xmlDoc
        if ($oldValue -eq "http://ax.help.dynamics.com")
        {
            Write-Log "Updating HelpWiki.APIEndPoint to production endpoint"
            Update-KeyValue -key $key -value "https://lcsapi.lcs.dynamics.com" -xmlDoc $xmlDoc
        }
        elseif ($oldValue -eq "http://ax.help.int.dynamics.com")
        {
            Write-Log "Updating HelpWiki.APIEndPoint to test endpoint"
            Update-KeyValue -key $key -value "https://lcsapi.lcs.tie.dynamics.com" -xmlDoc $xmlDoc
        }
        else
        {
            Write-Log "Not updating HelpWiki.APIEndPoint endpoint"
        }
    }

    # Check for PU22+
    if ($PlatformReleaseVersion -ge 5095)
    {
        # Update the Monitoring.ETWManifests key, adding Microsoft.Dynamics.ApplicationPlatform.DatabaseSynchronize.man if it does not exist in the list
        $key = "Monitoring.ETWManifests"
        if (Get-KeyExists -key:$key -xmlDoc:$xmlDoc)
        {
            $oldValue = Get-KeyValue -key $key -xmlDoc $xmlDoc
            $oldValueSplit = $oldValue -split ";"
            if ($oldValueSplit -notcontains "Microsoft.Dynamics.ApplicationPlatform.DatabaseSynchronize.man")
            {
                Write-Log "Updating Monitoring.ETWManifests, adding Microsoft.Dynamics.ApplicationPlatform.DatabaseSynchronize.man"
                $newValue = "$oldValue;Microsoft.Dynamics.ApplicationPlatform.DatabaseSynchronize.man"
                Update-KeyValue -key $key -value $newValue -xmlDoc $xmlDoc
            }
            else
            {
                Write-Log "Not updating Monitoring.ETWManifests, Microsoft.Dynamics.ApplicationPlatform.DatabaseSynchronize.man already exists"
            }
        }      
    }

    $xmlDoc.Save($webconfig);
}

function Upgrade-WebConfig-debugCompilation([string]$webconfig)
{
    [System.Xml.XmlDocument] $xmlDoc = New-Object System.Xml.XmlDocument
    $xmlDoc.Load($webconfig)

    $node = $xmlDoc.SelectSingleNode("//system.web/compilation")
    if ($node -ne $null)
    {
        Write-Log "Disabling debug compilation for assemblies"
        $node.debug = "false"
        $xmlDoc.Save($webconfig)
    }
    else
    {
        Write-Error "Cannot disable debug compilation for assemblies. No such property in the config file"
    }
}

function Upgrade-WebConfig-targetFrameworkCompilation([string]$webconfig)
{
    # perform this for PU29+
    if ($PlatformReleaseVersion -ge 5372)
    {
        [System.Xml.XmlDocument] $xmlDoc = New-Object System.Xml.XmlDocument
        $xmlDoc.Load($webconfig)

        $node = $xmlDoc.SelectSingleNode("/configuration/location[@inheritInChildApplications='false']/system.web/compilation")
        if ($node -ne $null)
        {
            if ($node.targetFramework -ne $null)
            {
                Write-Log "Update target framework version"
                $node.targetFramework = "4.5"
                $xmlDoc.Save($webconfig)
            }
        }
    }
}

function Get-AssemblyExists([string] $assemblyName, [System.Xml.XmlDocument] $xmlDoc)
{
    [System.Xml.XmlNode] $nodeToRead = $xmlDoc.SelectSingleNode("//add[@assembly='$assemblyName']")
    $keyExists = $false

    if ($nodeToRead -eq $null)
    {
        $keyExists = $false
    }
    else
    {
        $keyExists = $true
    }
    return $keyExists
}

function Get-KeyExists([string] $key, [System.Xml.XmlDocument] $xmlDoc)
{
    [System.Xml.XmlNode] $nodeToRead = $xmlDoc.SelectSingleNode("//add[@key='$key']")
    $keyExists = $false

    if ($nodeToRead -ne $null)
    {
        $keyExists = $true
    }

    return $keyExists
}

function Get-NameExists([string] $name, [System.Xml.XmlDocument] $xmlDoc)
{
    [System.Xml.XmlNode] $nodeToRead = $xmlDoc.SelectSingleNode("//add[@name='$name']")
    $nameExists = $false

    if ($nodeToRead -ne $null)
    {
        $nameExists = $true
    }

    return $nameExists
}

function Get-AllowedUserIdsExists([string] $allowedUserIds, [System.Xml.XmlDocument] $xmlDoc)
{
    [System.Xml.XmlNode] $nodeToRead = $xmlDoc.SelectSingleNode("//add[@allowedUserIds='$allowedUserIds']")
    $allowedUserIdsExists = $false

    if ($nodeToRead -ne $null)
    {
        $allowedUserIdsExists = $true
    }

    return $allowedUserIdsExists
}

function Get-AllowedUserIdsName([string] $allowedUserIds, [System.Xml.XmlDocument] $xmlDoc)
{
    [System.Xml.XmlNode] $nodeToRead = $xmlDoc.SelectSingleNode("//add[@allowedUserIds='$allowedUserIds']")

    if ($nodeToRead -eq $null)
    {
        Log-Error  "Failed to find allowedUserIds node '$allowedUserIds' for read"
    }

    Write-log "selected node '$allowedUserIds' for read"

    return $nodeToRead.name
}

function Remove-Key([string] $key, [System.Xml.XmlDocument] $xmlDoc)
{
    [System.Xml.XmlNode] $nodeForDeletion = $xmlDoc.SelectSingleNode("//add[@key='$key']")

    if ($nodeForDeletion -eq $null)
    {
        Log-Error  "Failed to find key node '$key' for deletion"
    }

    Write-log "selected node '$key' for deletion"

    $nodeForDeletion.ParentNode.RemoveChild($nodeForDeletion);
}

function Remove-Assembly([string] $assemblyName, [System.Xml.XmlDocument] $xmlDoc)
{
    [System.Xml.XmlNode] $nodeForDeletion = $xmlDoc.SelectSingleNode("//add[@assembly='$assemblyName']")

    if ($nodeForDeletion -eq $null)
    {
        Log-Error  "Failed to find assembly node '$assemblyName' for deletion"
    }

    Write-log "selected node ''$assemblyName' for deletion"

    $nodeForDeletion.ParentNode.RemoveChild($nodeForDeletion);
}

function Get-KeyValue([string] $key, [System.Xml.XmlDocument] $xmlDoc)
{
    [System.Xml.XmlNode] $nodeToRead = $xmlDoc.SelectSingleNode("//add[@key='$key']")

    if ($nodeToRead -eq $null)
    {
        Log-Error  "Failed to find key node '$key' for read"
    }

    Write-log "selected node '$key' for read"

    return $nodeToRead.Value
}

function Update-KeyValue([string] $key, [string] $value, [System.Xml.XmlDocument] $xmlDoc)
{
    [System.Xml.XmlNode] $nodeForDeletion = $xmlDoc.SelectSingleNode("//add[@key='$key']")

    if ($nodeForDeletion -eq $null)
    {
        Log-Error  "Failed to find key node '$key' for update"
    }

    Write-log "selected node '$key' for update"

    $nodeForDeletion.Value = $value
}

function Add-NewKey([string] $key, [string] $value, [System.Xml.XmlNode] $parentNode, [System.Xml.XmlDocument] $xmlDoc)
{
    [System.Xml.XmlElement] $element = $xmlDoc.CreateElement("add")
    $newAttribute = $xmlDoc.CreateAttribute('key')
    $newAttribute.Value = $key

    $element.Attributes.Append($newAttribute)

    $newAttribute = $xmlDoc.CreateAttribute('value')
    $newAttribute.Value = $value
    $element.Attributes.Append($newAttribute)

    $parentNode.AppendChild($element)
}

function Add-NewName([string] $name, [string] $value, [System.Xml.XmlNode] $parentNode, [System.Xml.XmlDocument] $xmlDoc)
{
    [System.Xml.XmlElement] $element = $xmlDoc.CreateElement("add")
    $newAttribute = $xmlDoc.CreateAttribute('name')
    $newAttribute.Value = $name

    $element.Attributes.Append($newAttribute)

    $newAttribute = $xmlDoc.CreateAttribute('value')
    $newAttribute.Value = $value
    $element.Attributes.Append($newAttribute)

    $parentNode.AppendChild($element)
}

function Rename-File([string]$from, [string]$to)
{
    Move-Item -Path $from -Destination $to -Force | Out-Null
    Write-Log "Renamed file '$from' to '$to'."
}

function Decrypt-Config([string]$webroot)
{
    $command = Join-Path -Path "$webroot\bin" -ChildPath $configEncryptor
    if (!(Test-Path -Path $command))
    {
        Log-Error "Cannot find the Microsoft.Dynamics.AX.Framework.ConfigEncryptor.exe at '$webroot\bin\'." -throw
    }

    $webconfig = Join-Path -Path $webroot -ChildPath "Web.config"
    $commandParameter = " -decrypt `"$webconfig`""
    $logdir = [System.IO.Path]::GetDirectoryName($global:logfile)
    $stdOut = Join-Path -Path $logdir -ChildPath "config_decrypt.log"
    $stdErr = Join-Path -Path $logdir -ChildPath "config_decrypt.error.log"
    Start-Process $command $commandParameter -PassThru -Wait -RedirectStandardOutput $stdOut -RedirectStandardError $stdErr

    $decryptError = Get-Content $stdErr
    if ($decryptError -ne $null)
    {
        Log-Error $decryptError -throw
    }

    Write-Log "Finished decrypting the web.config."
}

function Encrypt-Config([string]$webroot)
{
    $command = Join-Path -Path "$webroot\bin" -ChildPath $configEncryptor
    if (!(Test-Path -Path $command))
    {
        Log-Error "Cannot find the Microsoft.Dynamics.AX.Framework.ConfigEncryptor.exe at '$webroot\bin\'." -throw
    }

    $webconfig = Join-Path -Path $webroot -ChildPath "Web.config"
    $commandParameter = " -encrypt `"$webconfig`""
    $logdir = [System.IO.Path]::GetDirectoryName($global:logfile)
    $stdOut = Join-Path -Path $logdir -ChildPath "config_encrypt.log"
    $stdErr = Join-Path -Path $logdir -ChildPath "config_encrypt.error.log"
    Start-Process $command $commandParameter -PassThru -Wait -RedirectStandardOutput $stdOut -RedirectStandardError $stdErr

    $encryptError = Get-Content $stdErr
    if ($encryptError -ne $null)
    {
        Log-Error $encryptError -throw
    }

    Write-Log "Finished encrypting the web.config."
}

function Upgrade-WebConfig-rootLocations-PCFControls([string]$webconfig)
{
    # Check if update 52 or later
    if ($PlatformReleaseVersion -ge 6401)
    {
        [System.Xml.XmlDocument] $xmlDoc = New-Object System.Xml.XmlDocument
        $xmlDoc.Load($webconfig)

        $locationNode = $xmlDoc.SelectSingleNode("/configuration/location[@path='Resources']")
        if ($locationNode -eq $null)
        {
            <#
            <!-- Enble the serving of PCF controls (see PcfControlMetadataResourceController) -->
            <location path="Resources">
                <system.webServer>
                    <security>
                        <requestFiltering>
                            <fileExtensions>
                                <remove fileExtension=".resx" />
                                <add fileExtension=".resx" allowed="true" />
                            </fileExtensions>
                        </requestFiltering>
                    </security>
                </system.webServer>
            </location>
            #>

            Write-Log "Start adding Resources location node"
            $configurationNode = $xmlDoc.SelectSingleNode("/configuration")

            [System.Xml.XmlComment] $fileExtensionsComment = $xmlDoc.CreateComment("Enable the serving of PCF controls (see PcfControlMetadataResourceController)")
            $configurationNode.AppendChild($fileExtensionsComment)

            [System.Xml.XmlElement] $locationElement = $xmlDoc.CreateElement("location")
            $pathAttribute = $xmlDoc.CreateAttribute('path')
            $pathAttribute.Value = 'Resources'
            $locationElement.Attributes.Append($pathAttribute)
            $configurationNode.AppendChild($locationElement)

            [System.Xml.XmlElement] $systemWebServerElement = $xmlDoc.CreateElement("system.webServer")
            $locationElement.AppendChild($systemWebServerElement)

            [System.Xml.XmlElement] $securityElement = $xmlDoc.CreateElement("security")
            $systemWebServerElement.AppendChild($securityElement)

            [System.Xml.XmlElement] $requestFilteringElement = $xmlDoc.CreateElement("requestFiltering")
            $securityElement.AppendChild($requestFilteringElement)

            [System.Xml.XmlElement] $fileExtensionsElement = $xmlDoc.CreateElement("fileExtensions")
            $requestFilteringElement.AppendChild($fileExtensionsElement)

            [System.Xml.XmlElement] $removeElement = $xmlDoc.CreateElement("remove")
            $pathAttribute = $xmlDoc.CreateAttribute('fileExtension')
            $pathAttribute.Value = '.resx'
            $removeElement.Attributes.Append($pathAttribute)
            $fileExtensionsElement.AppendChild($removeElement)

            [System.Xml.XmlElement] $addElement = $xmlDoc.CreateElement("add")
            $pathAttribute = $xmlDoc.CreateAttribute('fileExtension')
            $pathAttribute.Value = '.resx'
            $addElement.Attributes.Append($pathAttribute)
            $pathAttribute = $xmlDoc.CreateAttribute('allowed')
            $pathAttribute.Value = 'true'
            $addElement.Attributes.Append($pathAttribute)
            $fileExtensionsElement.AppendChild($addElement)

            $xmlDoc.Save($webconfig)
        }
    }
}

function Upgrade-WebConfig-rootLocations-ReliableCommunicationManager([string]$webconfig)
{
    [System.Xml.XmlDocument] $xmlDoc = New-Object System.Xml.XmlDocument
    $xmlDoc.Load($webconfig)

    $rcmLocationNode = $xmlDoc.SelectSingleNode("/configuration/location[@path='Services/ReliableCommunicationManager.svc']")
    if ($rcmLocationNode -eq $null)
    {
        Write-Log "Start adding Services/ReliableCommunicationManager.svc location node"
        $configurationNode = $xmlDoc.SelectSingleNode("/configuration")

        [System.Xml.XmlElement] $locationElement = $xmlDoc.CreateElement("location")
        $pathAttribute = $xmlDoc.CreateAttribute('path')
        $pathAttribute.Value = 'Services/ReliableCommunicationManager.svc'
        $locationElement.Attributes.Append($pathAttribute)

        $configurationNode.AppendChild($locationElement)

        $xmlDoc.Save($webconfig)
    }

    #Check if platform update 25 or later
    if ($PlatformReleaseVersion -ge 5215)
    {
        # <system.web />
        $webNode = $xmlDoc.SelectSingleNode("/configuration/location[@path='Services/ReliableCommunicationManager.svc']/system.web")
        if ($webNode -eq $null)
        {
            Write-Log "Start adding system.web node to Services/ReliableCommunicationManager.svc location"
            $locationNode = $xmlDoc.SelectSingleNode("/configuration/location[@path='Services/ReliableCommunicationManager.svc']")

            [System.Xml.XmlElement] $webElement = $xmlDoc.CreateElement("system.web")

            $locationNode.AppendChild($webElement)

            $xmlDoc.Save($webconfig)
        }

        # <system.web>
        #   <compilation debug="false" />
        #   <httpRuntime enableVersionHeader="false" />
        # </system.web>

        $compilationNode = $xmlDoc.SelectSingleNode("/configuration/location[@path='Services/ReliableCommunicationManager.svc']/system.web/compilation")
        if ($compilationNode -eq $null)
        {
            Write-Log "Start adding system.web/compilation node to Services/ReliableCommunicationManager.svc location"
            $webNode = $xmlDoc.SelectSingleNode("/configuration/location[@path='Services/ReliableCommunicationManager.svc']/system.web")

            [System.Xml.XmlElement] $compilationElement = $xmlDoc.CreateElement("compilation")
            $debugAttribute = $xmlDoc.CreateAttribute('debug')
            $debugAttribute.Value = 'false'
            $compilationElement.Attributes.Append($debugAttribute)

            $webNode.AppendChild($compilationElement)

            $xmlDoc.Save($webconfig)
        }

        $httpRuntimeNode = $xmlDoc.SelectSingleNode("/configuration/location[@path='Services/ReliableCommunicationManager.svc']/system.web/httpRuntime")
        if ($httpRuntimeNode -eq $null)
        {
            Write-Log "Start adding system.web/httpRuntime node to Services/ReliableCommunicationManager.svc location"
            $webNode = $xmlDoc.SelectSingleNode("/configuration/location[@path='Services/ReliableCommunicationManager.svc']/system.web")

            [System.Xml.XmlElement] $httpRuntimeElement = $xmlDoc.CreateElement("httpRuntime")
            $enableVersionHeaderAttribute = $xmlDoc.CreateAttribute('enableVersionHeader')
            $enableVersionHeaderAttribute.Value = 'false'
            $httpRuntimeElement.Attributes.Append($enableVersionHeaderAttribute)

            $webNode.AppendChild($httpRuntimeElement)

            $xmlDoc.Save($webconfig)
        }
    }

    $webServerNode = $xmlDoc.SelectSingleNode("/configuration/location[@path='Services/ReliableCommunicationManager.svc']/system.webServer")
    if ($webServerNode -eq $null)
    {
        Write-Log "Start adding system.webServer node to Services/ReliableCommunicationManager.svc location"
        $locationNode = $xmlDoc.SelectSingleNode("/configuration/location[@path='Services/ReliableCommunicationManager.svc']")

        [System.Xml.XmlElement] $webServerElement = $xmlDoc.CreateElement("system.webServer")

        [System.Xml.XmlElement] $httpErrorsElement = $xmlDoc.CreateElement("httpErrors")
        $errorModeAttribute = $xmlDoc.CreateAttribute('errorMode')
        $errorModeAttribute.Value = 'Custom'
        $existingResponseAttribute = $xmlDoc.CreateAttribute('existingResponse')
        $existingResponseAttribute.Value = 'PassThrough'
        $httpErrorsElement.Attributes.Append($errorModeAttribute)
        $httpErrorsElement.Attributes.Append($existingResponseAttribute)

        $webServerElement.AppendChild($httpErrorsElement)

        $locationNode.AppendChild($webServerElement)

        $xmlDoc.Save($webconfig)
    }

    #Check if platform update 25 or later
    if ($PlatformReleaseVersion -ge 5215)
    {
        # IIS version 10 or above is supported
        $iisVersion = Get-IISVersion-Major
        if ($iisVersion -ge 10)
        {
            # <security>
            #   <requestFiltering removeServerHeader="true" />
            # </security>
            $securityNode = $xmlDoc.SelectSingleNode("/configuration/location[@path='Services/ReliableCommunicationManager.svc']/system.webServer/security")
            if ($securityNode -eq $null)
            {
                Write-Log "Start adding system.webServer/security node to Services/ReliableCommunicationManager.svc location"
                $webServerNode = $xmlDoc.SelectSingleNode("/configuration/location[@path='Services/ReliableCommunicationManager.svc']/system.webServer")

                [System.Xml.XmlElement] $securityElement = $xmlDoc.CreateElement("security")
                [System.Xml.XmlElement] $requestFilteringElement = $xmlDoc.CreateElement("requestFiltering")
                $removeServerHeaderAttribute = $xmlDoc.CreateAttribute('removeServerHeader')
                $removeServerHeaderAttribute.Value = 'true'
                $requestFilteringElement.Attributes.Append($removeServerHeaderAttribute)

                $securityElement.AppendChild($requestFilteringElement)
                $webServerNode.AppendChild($securityElement)

                $xmlDoc.Save($webconfig)
            }
        }
    }

    $httpProtocolNode = $xmlDoc.SelectSingleNode("/configuration/location[@path='Services/ReliableCommunicationManager.svc']/system.webServer/httpProtocol")
    if ($httpProtocolNode -eq $null)
    {
        Write-Log "Start adding system.webServer/httpProtocol node to Services/ReliableCommunicationManager.svc location"
        $webServerNode = $xmlDoc.SelectSingleNode("/configuration/location[@path='Services/ReliableCommunicationManager.svc']/system.webServer")

        [System.Xml.XmlElement] $httpProtocolElement = $xmlDoc.CreateElement("httpProtocol")

        $webServerNode.AppendChild($httpProtocolElement)

        $xmlDoc.Save($webconfig)
    }

    $customHeadersNode = $xmlDoc.SelectSingleNode("/configuration/location[@path='Services/ReliableCommunicationManager.svc']/system.webServer/httpProtocol/customHeaders")
    if ($customHeadersNode -eq $null)
    {
        Write-Log "Start adding system.webServer/httpProtocol/customHeaders node to Services/ReliableCommunicationManager.svc location"
        $httpProtocolNode = $xmlDoc.SelectSingleNode("/configuration/location[@path='Services/ReliableCommunicationManager.svc']/system.webServer/httpProtocol")

        [System.Xml.XmlElement] $customHeadersElement = $xmlDoc.CreateElement("customHeaders")

        $httpProtocolNode.AppendChild($customHeadersElement)

        $xmlDoc.Save($webconfig)
    }

    $removeNode = $xmlDoc.SelectSingleNode("/configuration/location[@path='Services/ReliableCommunicationManager.svc']/system.webServer/httpProtocol/customHeaders/remove[@name='Cache-Control']")
    if ($removeNode -eq $null)
    {
        Write-Log "Start adding system.webServer/httpProtocol/customHeaders/remove node to Services/ReliableCommunicationManager.svc location"
        $customHeadersNode = $xmlDoc.SelectSingleNode("/configuration/location[@path='Services/ReliableCommunicationManager.svc']/system.webServer/httpProtocol/customHeaders")

        $addNode = $xmlDoc.SelectSingleNode("/configuration/location[@path='Services/ReliableCommunicationManager.svc']/system.webServer/httpProtocol/customHeaders/add[@name='Cache-Control']")
        if ($addNode -ne $null)
        {
            $customHeadersNode.RemoveChild($addNode)
        }

        [System.Xml.XmlElement] $removeElement = $xmlDoc.CreateElement("remove")
        $removeNameAttribute = $xmlDoc.CreateAttribute('name')
        $removeNameAttribute.Value = 'Cache-Control'
        $removeElement.Attributes.Append($removeNameAttribute)

        $customHeadersNode.AppendChild($removeElement)

        $xmlDoc.Save($webconfig)
    }

    $addNode = $xmlDoc.SelectSingleNode("/configuration/location[@path='Services/ReliableCommunicationManager.svc']/system.webServer/httpProtocol/customHeaders/add[@name='Cache-Control']")
    if ($addNode -eq $null)
    {
        Write-Log "Start adding system.webServer/httpProtocol/customHeaders/add node to Services/ReliableCommunicationManager.svc location"
        $customHeadersNode = $xmlDoc.SelectSingleNode("/configuration/location[@path='Services/ReliableCommunicationManager.svc']/system.webServer/httpProtocol/customHeaders")

        [System.Xml.XmlElement] $addElement = $xmlDoc.CreateElement("add")
        $addNameAttribute = $xmlDoc.CreateAttribute('name')
        $addNameAttribute.Value = 'Cache-Control'
        $addValueAttribute = $xmlDoc.CreateAttribute('value')
        $addValueAttribute.Value = 'no-cache,no-store'
        $addElement.Attributes.Append($addNameAttribute)
        $addElement.Attributes.Append($addValueAttribute)

        $customHeadersNode.AppendChild($addElement)

        $xmlDoc.Save($webconfig)
    }
}

function Upgrade-WebConfig-rootLocations-TelemetryManager([string]$webconfig)
{
    #Check if platform update 25 or later
    if ($PlatformReleaseVersion -ge 5215)
    {
        [System.Xml.XmlDocument] $xmlDoc = New-Object System.Xml.XmlDocument
        $xmlDoc.Load($webconfig)

        $tmLocationNode = $xmlDoc.SelectSingleNode("/configuration/location[@path='Services/TelemetryManager.svc']")
        if ($tmLocationNode -eq $null)
        {
            Write-Log "Start adding Services/TelemetryManager.svc location node"
            $configurationNode = $xmlDoc.SelectSingleNode("/configuration")

            [System.Xml.XmlElement] $locationElement = $xmlDoc.CreateElement("location")
            $pathAttribute = $xmlDoc.CreateAttribute('path')
            $pathAttribute.Value = 'Services/TelemetryManager.svc'
            $locationElement.Attributes.Append($pathAttribute)

            $configurationNode.AppendChild($locationElement)

            $xmlDoc.Save($webconfig)
        }

        # <system.web />
        $webNode = $xmlDoc.SelectSingleNode("/configuration/location[@path='Services/TelemetryManager.svc']/system.web")
        if ($webNode -eq $null)
        {
            Write-Log "Start adding system.web node to Services/TelemetryManager.svc location"
            $locationNode = $xmlDoc.SelectSingleNode("/configuration/location[@path='Services/TelemetryManager.svc']")

            [System.Xml.XmlElement] $webElement = $xmlDoc.CreateElement("system.web")

            $locationNode.AppendChild($webElement)

            $xmlDoc.Save($webconfig)
        }

        # <system.web>
        #   <compilation debug="false" />
        #   <httpRuntime enableVersionHeader="false" />
        # </system.web>

        $compilationNode = $xmlDoc.SelectSingleNode("/configuration/location[@path='Services/TelemetryManager.svc']/system.web/compilation")
        if ($compilationNode -eq $null)
        {
            Write-Log "Start adding system.web/compilation node to Services/TelemetryManager.svc location"
            $webNode = $xmlDoc.SelectSingleNode("/configuration/location[@path='Services/TelemetryManager.svc']/system.web")

            [System.Xml.XmlElement] $compilationElement = $xmlDoc.CreateElement("compilation")
            $debugAttribute = $xmlDoc.CreateAttribute('debug')
            $debugAttribute.Value = 'false'
            $compilationElement.Attributes.Append($debugAttribute)

            $webNode.AppendChild($compilationElement)

            $xmlDoc.Save($webconfig)
        }

        $httpRuntimeNode = $xmlDoc.SelectSingleNode("/configuration/location[@path='Services/TelemetryManager.svc']/system.web/httpRuntime")
        if ($httpRuntimeNode -eq $null)
        {
            Write-Log "Start adding system.web/httpRuntime node to Services/TelemetryManager.svc location"
            $webNode = $xmlDoc.SelectSingleNode("/configuration/location[@path='Services/TelemetryManager.svc']/system.web")

            [System.Xml.XmlElement] $httpRuntimeElement = $xmlDoc.CreateElement("httpRuntime")
            $enableVersionHeaderAttribute = $xmlDoc.CreateAttribute('enableVersionHeader')
            $enableVersionHeaderAttribute.Value = 'false'
            $httpRuntimeElement.Attributes.Append($enableVersionHeaderAttribute)

            $webNode.AppendChild($httpRuntimeElement)

            $xmlDoc.Save($webconfig)
        }

        $webServerNode = $xmlDoc.SelectSingleNode("/configuration/location[@path='Services/TelemetryManager.svc']/system.webServer")
        if ($webServerNode -eq $null)
        {
            Write-Log "Start adding system.webServer node to Services/TelemetryManager.svc location"
            $locationNode = $xmlDoc.SelectSingleNode("/configuration/location[@path='Services/TelemetryManager.svc']")

            [System.Xml.XmlElement] $webServerElement = $xmlDoc.CreateElement("system.webServer")

            [System.Xml.XmlElement] $httpErrorsElement = $xmlDoc.CreateElement("httpErrors")
            $errorModeAttribute = $xmlDoc.CreateAttribute('errorMode')
            $errorModeAttribute.Value = 'Custom'
            $existingResponseAttribute = $xmlDoc.CreateAttribute('existingResponse')
            $existingResponseAttribute.Value = 'PassThrough'
            $httpErrorsElement.Attributes.Append($errorModeAttribute)
            $httpErrorsElement.Attributes.Append($existingResponseAttribute)

            $webServerElement.AppendChild($httpErrorsElement)

            $locationNode.AppendChild($webServerElement)

            $xmlDoc.Save($webconfig)
        }

        # IIS version 10 or above is supported
        $iisVersion = Get-IISVersion-Major
        if ($iisVersion -ge 10)
        {
            # <security>
            #   <requestFiltering removeServerHeader="true" />
            # </security>
            $securityNode = $xmlDoc.SelectSingleNode("/configuration/location[@path='Services/TelemetryManager.svc']/system.webServer/security")
            if ($securityNode -eq $null)
            {
                Write-Log "Start adding system.webServer/security node to Services/TelemetryManager.svc location"
                $webServerNode = $xmlDoc.SelectSingleNode("/configuration/location[@path='Services/TelemetryManager.svc']/system.webServer")

                [System.Xml.XmlElement] $securityElement = $xmlDoc.CreateElement("security")
                [System.Xml.XmlElement] $requestFilteringElement = $xmlDoc.CreateElement("requestFiltering")
                $removeServerHeaderAttribute = $xmlDoc.CreateAttribute('removeServerHeader')
                $removeServerHeaderAttribute.Value = 'true'
                $requestFilteringElement.Attributes.Append($removeServerHeaderAttribute)

                $securityElement.AppendChild($requestFilteringElement)
                $webServerNode.AppendChild($securityElement)

                $xmlDoc.Save($webconfig)
            }
        }
    }
}

function Upgrade-WebConfig-rootLocations([string]$webconfig)
{
    [System.Xml.XmlDocument] $xmlDoc = New-Object System.Xml.XmlDocument
    $xmlDoc.Load($webconfig)

    if ($PlatformReleaseVersion -ge 4425)
    {
        $newNodeAttribute = 'punchout'
        $nodetoAdd = $xmlDoc.SelectSingleNode("/configuration/location[@path='$newNodeAttribute']")
        if ($nodetoAdd -eq $null)
        {
            Write-Log "Start adding punchout node"
            $configurationNode = $xmlDoc.SelectSingleNode("/configuration")

            [System.Xml.XmlElement] $locationElement = $xmlDoc.CreateElement("location")
            $pathAttribute = $xmlDoc.CreateAttribute('path')
            $pathAttribute.Value = $newNodeAttribute
            $locationElement.Attributes.Append($pathAttribute)

            [System.Xml.XmlElement] $webElement = $xmlDoc.CreateElement("system.web")
            [System.Xml.XmlElement] $httpRuntimeElement = $xmlDoc.CreateElement("httpRuntime")
            $requestValidationModeAttribute = $xmlDoc.CreateAttribute('requestValidationMode')
            $requestValidationModeAttribute.Value = '2.0'
            $httpRuntimeElement.Attributes.Append($requestValidationModeAttribute)

            $webElement.AppendChild($httpRuntimeElement)
            $locationElement.AppendChild($webElement)
            $configurationNode.AppendChild($locationElement)

            $xmlDoc.Save($webconfig)
        }
    }

    # Check if update 41 or later
    if ($PlatformReleaseVersion -ge 5934)
    {      
        $sameSiteNone ='None'
        $sameSiteLax ='Lax'
        $httpCookiesConfigNode = $xmlDoc.SelectSingleNode("/configuration/location/system.web/httpCookies")
        $httpCookiesConfigNodeValue = $httpCookiesConfigNode.GetAttribute("sameSite")

        # Update existing Lax value to None to support punchout scenario
         if($httpCookiesConfigNodeValue -eq $sameSiteLax)
        {
           $httpCookiesConfigNode.SetAttribute("sameSite", $sameSiteNone)
           Write-Log "Web.config http Cookie sameSite updated to '$sameSiteNone' value."
        }
        elseif($httpCookiesConfigNodeValue -eq $sameSiteNone)
        {
           Write-Log "Web.config http Cookie sameSite already has '$sameSiteNone' value."
        }
        else
        {
           $httpCookiesConfigNode.SetAttribute("sameSite", $sameSiteNone)
            Write-Log "Web.config http Cookie sameSite updated to '$sameSiteNone' value."
        }
        $xmlDoc.Save($webconfig)
    }
}

function Modify-WebConfig-removeServerHeaderSetting([System.Xml.XmlDocument]$xmlDoc, [string]$xmlNodePathHead)
{
    # <system.webServer>
    #   <security>
    #       <requestFiltering removeServerHeader="true">
    #       </requestFiltering>
    #   </security>
    # </system.webServer>
    
    # <system.webServer />
    $webServerNode = $xmlDoc.SelectSingleNode("$xmlNodePathHead/system.webServer")
    if ($webServerNode -eq $null)
    {
        Write-Log "Start adding system.webServer node to $xmlNodePathHead"
        $configurationNode = $xmlDoc.SelectSingleNode($xmlNodePathHead)

        [System.Xml.XmlElement] $webServerElement = $xmlDoc.CreateElement("system.webServer")
        $configurationNode.AppendChild($webServerElement)

        $xmlDoc.Save($webconfig)
    }

    # <security>
    $securityNode = $xmlDoc.SelectSingleNode("$xmlNodePathHead/system.webServer/security")
    if ($securityNode -eq $null)
    {
        Write-Log "Start adding security node to $xmlNodePathHead/system.webServer"
        $webServerNode = $xmlDoc.SelectSingleNode("$xmlNodePathHead/system.webServer")
        [System.Xml.XmlElement] $securityElement = $xmlDoc.CreateElement("security")               
        $webServerNode.AppendChild($securityElement)
        $xmlDoc.Save($webconfig)
    }

    # <requestFiltering removeServerHeader="true">
    $requestFilteringNode = $xmlDoc.SelectSingleNode("$xmlNodePathHead/system.webServer/security/requestFiltering")
    if ($requestFilteringNode -eq $null)
    {
        Write-Log "Start adding requestFiltering node to $xmlNodePathHead/system.webServer/security"
        $securityNode = $xmlDoc.SelectSingleNode("$xmlNodePathHead/system.webServer/security")
        [System.Xml.XmlElement] $requestFilteringElement = $xmlDoc.CreateElement("requestFiltering")
        $removeServerHeaderAttribute = $xmlDoc.CreateAttribute('removeServerHeader')
        $removeServerHeaderAttribute.Value = 'true'
        $requestFilteringElement.Attributes.Append($removeServerHeaderAttribute)

        $securityNode.AppendChild($requestFilteringElement)
        $xmlDoc.Save($webconfig)
    }
    else
    {
        Write-Log "start modifying removeServerHeader attribute of requestFiltering node under $xmlNodePathHead/system.webServer/security"
        [System.Xml.XmlElement] $requestFilteringElement = $xmlDoc.SelectSingleNode("$xmlNodePathHead/system.webServer/security/requestFiltering")
        $requestFilteringElement.SetAttribute('removeServerHeader', 'true')
        $xmlDoc.Save($webconfig)
    }
}

function Upgrade-WebConfig-rootLocationsWithSecurity([string]$webconfig)
{
    # PU44 and above.
    if ($PlatformReleaseVersion -ge 6060)
    {
        # IIS version 10 or above is supported
        $iisVersion = Get-IISVersion-Major
        if ($iisVersion -ge 10)
        {
            [System.Xml.XmlDocument] $xmlDoc = New-Object System.Xml.XmlDocument
            $xmlDoc.Load($webconfig)
        
            Modify-WebConfig-removeServerHeaderSetting -xmlDoc:$xmlDoc -xmlNodePath "/configuration"
        }
    }
}


function Upgrade-WebConfig-rootLocationsWithSecurity-byName([string]$webconfig, [string]$locationname)
{
    # PU44 and above.
    if ($PlatformReleaseVersion -ge 6060)
    {
        [System.Xml.XmlDocument] $xmlDoc = New-Object System.Xml.XmlDocument
        $xmlDoc.Load($webconfig)

        $tmLocationNode = $xmlDoc.SelectSingleNode("/configuration/location[@path='$locationname']")
        if ($tmLocationNode -eq $null)
        {
            Write-Log "$locationname location node does not exist. Return and do nothing."
            return
        }

        # <system.web />
        $webNode = $xmlDoc.SelectSingleNode("/configuration/location[@path='$locationname']/system.web")
        if ($webNode -eq $null)
        {
            Write-Log "Start adding system.web node to $locationname location"
            $locationNode = $xmlDoc.SelectSingleNode("/configuration/location[@path='$locationname']")

            [System.Xml.XmlElement] $webElement = $xmlDoc.CreateElement("system.web")

            $locationNode.AppendChild($webElement)

            $xmlDoc.Save($webconfig)
        }

        # <system.web>
        #   <compilation debug="false" />
        #   <httpRuntime enableVersionHeader="false" />
        # </system.web>

        $compilationNode = $xmlDoc.SelectSingleNode("/configuration/location[@path='$locationname']/system.web/compilation")
        if ($compilationNode -eq $null)
        {
            Write-Log "Start adding system.web/compilation node to $locationname location"
            $webNode = $xmlDoc.SelectSingleNode("/configuration/location[@path='$locationname']/system.web")

            [System.Xml.XmlElement] $compilationElement = $xmlDoc.CreateElement("compilation")
            $debugAttribute = $xmlDoc.CreateAttribute('debug')
            $debugAttribute.Value = 'false'
            $compilationElement.Attributes.Append($debugAttribute)

            $webNode.AppendChild($compilationElement)

            $xmlDoc.Save($webconfig)
        }
        else
        {
            Write-Log "Start modifying debug attribute of system.web/compilation node under $locationname location"
            [System.Xml.XmlElement] $compilationNode = $xmlDoc.SelectSingleNode("/configuration/location[@path='$locationname']/system.web/compilation")
            $compilationNode.SetAttribute('debug', 'false')
            $xmlDoc.Save($webconfig)
        }

        $httpRuntimeNode = $xmlDoc.SelectSingleNode("/configuration/location[@path='$locationname']/system.web/httpRuntime")
        if ($httpRuntimeNode -eq $null)
        {
            Write-Log "Start adding system.web/httpRuntime node to $locationname location"
            $webNode = $xmlDoc.SelectSingleNode("/configuration/location[@path='$locationname']/system.web")

            [System.Xml.XmlElement] $httpRuntimeElement = $xmlDoc.CreateElement("httpRuntime")
            $enableVersionHeaderAttribute = $xmlDoc.CreateAttribute('enableVersionHeader')
            $enableVersionHeaderAttribute.Value = 'false'
            $httpRuntimeElement.Attributes.Append($enableVersionHeaderAttribute)

            $webNode.AppendChild($httpRuntimeElement)

            $xmlDoc.Save($webconfig)
        }
        else
        {
            Write-Log "Start modifying enableVersionHeader attribute of system.web/httpRuntime node under $locationname location"
            [System.Xml.XmlElement] $compilationNode = $xmlDoc.SelectSingleNode("/configuration/location[@path='$locationname']/system.web/httpRuntime")
            $compilationNode.SetAttribute('enableVersionHeader', 'false')
            $xmlDoc.Save($webconfig)
        }


        # <system.webServer>
        #   <security>
        #       <requestFiltering removeServerHeader="true">
        #       </requestFiltering>
        #   </security>
        # </system.webServer>
        # IIS version 10 or above is supported
        $iisVersion = Get-IISVersion-Major
        if ($iisVersion -ge 10)
        {
            Modify-WebConfig-removeServerHeaderSetting -xmlDoc:$xmlDoc -xmlNodePath "/configuration/location[@path='$locationname']"           
        }
    }
}

function Upgrade-WebConfig-RemoveAssemblies([string]$webConfig)
{
    if ($PlatformReleaseVersion -ge 4425)
    {
        [System.Xml.XmlDocument] $xmlDoc = New-Object System.Xml.XmlDocument
        $xmlDoc.Load($webconfig)
        $assemblyName = 'Microsoft.Dynamics.IntegrationFramework.WebService.Process'
        if (Get-AssemblyExists -assemblyName:$assemblyName -xmlDoc:$xmlDoc)
        {
            Remove-Assembly -assemblyName:$assemblyName -xmlDoc:$xmlDoc
        }
    }
}

function Upgrade-WebConfig-RemoveWcfActivityLog([string]$webConfig)
{
    if ($PlatformReleaseVersion -ge 4425)
    {
        Write-Log "Start removing wcf activityLog."
        [System.Xml.XmlDocument] $xmlDoc = New-Object System.Xml.XmlDocument
        $xmlDoc.Load($webconfig)

        $Web = $xmlDoc.SelectNodes("//*[@name='WcfActivityLog']")
        foreach ($webitem in $Web)
        {
            $webItemParent = $webitem.ParentNode
            $webItemParent.RemoveChild($webitem)
        }

        $xmlDoc.Save($webconfig)
    }
}

function Upgrade-WebConfig-Add-LcsEnvironmentId([string]$webconfig)
{
    [System.Xml.XmlDocument] $xmlDoc = New-Object System.Xml.XmlDocument
    $xmlDoc.Load($webconfig)
    $appsettings = $xmlDoc.SelectSingleNode("/configuration/appSettings")

    $key = 'LCS.EnvironmentId'
    Try
    {
        $value = Get-ItemProperty -Path hklm:SOFTWARE\Microsoft\Dynamics\AX\Diagnostics\MonitoringInstall -Name "LCSEnvironmentID"
        $value = $value.LCSEnvironmentId
    }
    Catch
    {
        $value = ''
    }
    if (!(Get-KeyExists -key:$key -xmlDoc:$xmlDoc) -and $value -ne '')
    {
        Add-NewKey -key $key -value $value -parentNode $appsettings -xmlDoc $xmlDoc
    }

    $xmlDoc.Save($webconfig);
}

function Upgrade-WifConfig-Add-CustomTokenHandler([string]$wifconfig)
{
    if ($PlatformReleaseVersion -ge 4977)
    {
        [System.Xml.XmlDocument] $wifXml = New-Object System.Xml.XmlDocument
        $wifXml.Load($wifconfig)

        Write-Log "Checking if the custom token handler should be added to wif.config"
        $shouldAddCustomTokenHandler = $false

        $foundNode = $wifXml.SelectSingleNode("//add[@type='MS.Dynamics.TestTools.CloudCommonTestUtilities.Authentication.PerfSdkSaml2TokenHandler, MS.Dynamics.TestTools.CloudCommonTestUtilities']")
        if ($foundNode -eq $null)
        {
            $key = 'HKLM:/SOFTWARE/Microsoft/Dynamics/AX/Diagnostics/MonitoringInstall'

            if (Test-Path -Path $key)
            {
                $lcsEnvironmentTag = (Get-ItemProperty -Path $key).LcsEnvironmentTag
                if ($lcsEnvironmentTag -eq "sandbox")
                {
                    Write-Log "Sandbox VM on PU18 or above should have the custom token handler"
                    $shouldAddCustomTokenHandler = $true
                }
            }
            elseif (Get-DevToolsInstalled)
            {
                Write-Log "Dev VM on PU18 or above should have the custom token handler"
                $shouldAddCustomTokenHandler = $true
            }
        }

        if ($shouldAddCustomTokenHandler)
        {
            Write-Log "Adding PerfSDK custom token handler"

            $securityTokenHandlerConfiguration = $wifXml.SelectSingleNode("system.identityModel/identityConfiguration/securityTokenHandlers")

            $removeNode = $wifXml.CreateElement("remove")
            $removeNode.SetAttribute("type", "System.IdentityModel.Tokens.Saml2SecurityTokenHandler, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")

            if ($PlatformReleaseVersion -lt 7595)
            {
            $addNode = $wifXml.CreateElement("add")
            $addNode.SetAttribute("type", "MS.Dynamics.TestTools.CloudCommonTestUtilities.Authentication.PerfSdkSaml2TokenHandler, MS.Dynamics.TestTools.CloudCommonTestUtilities")

            $securityTokenHandlerConfiguration.AppendChild($addNode)
            }

            $securityTokenHandlerConfiguration.AppendChild($removeNode)
        }

        if ($PlatformReleaseVersion -ge 7595) 
        {
            Write-Log "PlatformReleaseVersion is greater than or equal to 7595"

            $nodeToRemove = $wifXml.SelectSingleNode("//add[@type='MS.Dynamics.TestTools.CloudCommonTestUtilities.Authentication.PerfSdkSaml2TokenHandler, MS.Dynamics.TestTools.CloudCommonTestUtilities']")

            if ($nodeToRemove -ne $null) 
            {
             $parentNode = $nodeToRemove.ParentNode
             $parentNode.RemoveChild($nodeToRemove)
             
             Write-Log "Found and removed PerfSdkSaml2TokenHandler node."
            } 
            else 
            {
             Write-Log "Node not found"
            }
        } 
        else 
        {
            Write-Log "PlatformReleaseVersion is less than 7595"
        }

        $wifXml.Save($wifconfig)
    }
}

function Upgrade-WebConfig-ExcludeIdentityModelFromInheritance([string]$webconfig)
{
    [System.Xml.XmlDocument] $xmlDoc = New-Object System.Xml.XmlDocument
    $xmlDoc.Load($webconfig)

    $identityModel = $xmlDoc.SelectSingleNode("//system.identityModel")
    if ($identityModel.ParentNode.Name -ne "location")
    {
        Write-Log "Excluding identity model from inheritance"

        $inheritanceNode = $xmlDoc.CreateElement("location")
        $inheritanceNode.SetAttribute("path", ".")
        $inheritanceNode.SetAttribute("inheritInChildApplications", "false")

        $configuration = $xmlDoc.SelectSingleNode("/configuration")
        $configuration.InsertBefore($inheritanceNode, $identityModel)
        $inheritanceNode.AppendChild($identityModel)
    }
    $xmlDoc.Save($webconfig)
}

function Upgrade-WebConfig-Add-SecurityrequestFilteringVerbsElements([string] $webConfig)
{
    if (Get-DevToolsInstalled)
    {
        # Must allow DEBUG verb for development environments
        Write-Log "Development Tools are installed. Skipping Upgrade-WebConfig-Add-SecurityrequestFilteringVerbsElements"
    }
    else
    {
        # Not a development environment, so disallow DEBUG verb

        Write-Log "Upgrade-WebConfig-Add-SecurityrequestFilteringVerbsElements start"

        [System.Xml.XmlDocument] $xmlDoc = New-Object System.Xml.XmlDocument
        $xmlDoc.Load($webconfig)

        # /configuration/system.webServer
        [System.Xml.XmlNode] $node = $xmlDoc.SelectSingleNode("/configuration/system.webServer")
        if ($null -ne $node)
        {
            Add-SecurityrequestFilteringVerbsElement -xmlDoc $xmlDoc -webServerNode $node
        }

        $xmlDoc.Save($webconfig)

        Write-Log "Upgrade-WebConfig-Add-SecurityrequestFilteringVerbsElements end"
    }
}

function Add-SecurityrequestFilteringVerbsElement([System.Xml.XmlDocument] $xmlDoc, [System.Xml.XmlNode] $webServerNode)
{
    #  <security>
    #    <requestFiltering>
    #      <verbs>
    #        <add verb="DEBUG" allowed="false" />
    #      </verbs>
    #    </requestFiltering>
    #  </security>

    # Ensure security node exists
    [System.Xml.XmlNode] $securityNode = $webServerNode.SelectSingleNode("security")
    if ($null -eq $securityNode)
    {
        Write-Log "Add-SecurityrequestFilteringVerbsElement: Creating element 'security'"

        $securityNode = $xmlDoc.CreateNode("element", "security", $null)
        $webServerNode.AppendChild($securityNode)
    }

    # Ensure requestFiltering node exists
    [System.Xml.XmlNode] $requestFilteringNode = $securityNode.SelectSingleNode("requestFiltering")
    if ($null -eq $requestFilteringNode)
    {
        Write-Log "Add-SecurityrequestFilteringVerbsElement: Creating element 'requestFiltering'"

        $requestFilteringNode = $xmlDoc.CreateNode("element", "requestFiltering", $null)
        $securityNode.AppendChild($requestFilteringNode)
    }

    # Ensure verbs node exists
    [System.Xml.XmlNode] $verbsNode = $requestFilteringNode.SelectSingleNode("verbs")
    if ($null -eq $verbsNode)
    {
        Write-Log "Add-SecurityrequestFilteringVerbsElement: Creating element 'verbs'"

        $verbsNode = $xmlDoc.CreateNode("element", "verbs", $null)
        $requestFilteringNode.AppendChild($verbsNode)
    }

    # Add exclusion of verb DEBUG
    [System.Xml.XmlNode] $verbNode = $verbsNode.SelectSingleNode("add[@verb='DEBUG']")
    if ($null -eq $verbNode)
    {
        Write-Log "Add-SecurityrequestFilteringVerbsElement: Creating element 'add' with attribute 'verb' with value 'DEBUG'"

        Add-VerbAllowedElement -xmlDoc $xmlDoc -parentNode $verbsNode -verb "DEBUG" -allowed "false"
    }
}

function Add-VerbAllowedElement([System.Xml.XmlDocument] $xmlDoc, [System.Xml.XmlNode] $parentNode, [string] $verb, [string] $allowed)
{
    [System.Xml.XmlElement] $element = $xmlDoc.CreateElement("add");

    [System.Xml.XmlAttribute] $verbAttribute = $xmlDoc.CreateAttribute("verb")
    $verbAttribute.Value = $verb

    [System.Xml.XmlAttribute] $allowedAttribute = $xmlDoc.CreateAttribute("allowed")
    $allowedAttribute.Value = $allowed

    $element.Attributes.Append($verbAttribute)
    $element.Attributes.Append($allowedAttribute)

    $parentNode.AppendChild($element)
}

function Upgrade-WebConfig-Update-LogoutModule([string] $webConfig)
{
    # Microsoft.Dynamics.AX.HttpModule.LogoutHttpModule.netmodule is merged with AOSKernel.dll, since .NET does
    # not support netmodules it needs to be changed to be an assembly. Since it is only relevant to the IIS hosted AOS
    # the assembly will only be registered with IIS (and no longer be merged with AOSKernel.dll)

    if ($PlatformReleaseVersion -gt 7400) # Main build post PU66
    {
        Write-Log "Upgrade-WebConfig-Update-LogoutModule start"

        # Before: <add name="LogoutModule" type="Microsoft.Dynamics.AX.HttpModule.LogoutHttpModule" preCondition="managedHandler" />
        # After:  <add name="LogoutModule" type="Microsoft.Dynamics.AX.HttpModule.LogoutHttpModule, Microsoft.Dynamics.AX.HttpModule.LogoutHttpModule" preCondition="managedHandler" />

        [System.Xml.XmlDocument] $xmlDoc = New-Object System.Xml.XmlDocument
        $xmlDoc.Load($webconfig)

        [System.Xml.XmlNode] $modulesNode = $xmlDoc.SelectSingleNode("/configuration/system.webServer/modules")
        if ($null -ne $modulesNode)
        {
            $addNode = $modulesNode.SelectSingleNode("add[@type='Microsoft.Dynamics.AX.HttpModule.LogoutHttpModule']")
            if($null -ne $addNode)
            {
                Write-Log "Updating LogoutHttpModule node"
                $addNode.type = "Microsoft.Dynamics.AX.HttpModule.LogoutHttpModule, Microsoft.Dynamics.AX.HttpModule.LogoutHttpModule"
            }
        }

        $xmlDoc.Save($webconfig)

        Write-Log "Upgrade-WebConfig-Update-LogoutModule end"
    }
}

function Upgrade-WebConfig-Update-SecureCookieHttpModule([string] $webConfig)
{
    # Microsoft.Dynamics.AX.HttpModule.LogoutHttpModule.netmodule is merged with AOSKernel.dll, since .NET does
    # not support netmodules it needs to be changed to be an assembly. Since it is only relevant to the IIS hosted AOS
    # the assembly will only be registered with IIS (and no longer be merged with AOSKernel.dll)

    if ($PlatformReleaseVersion -gt 7400) # Main build post PU66
    {
        Write-Log "SecureCookieHttpModule start"

        # Before: <add name="LogoutModule" type="Microsoft.Dynamics.AX.HttpModule.SecureCookieHttpModule" preCondition="managedHandler" />
        # After:  <add name="LogoutModule" type="Microsoft.Dynamics.AX.HttpModule.SecureCookieHttpModule, Microsoft.Dynamics.AX.HttpModule.SecureCookieHttpModule" preCondition="managedHandler" />

        [System.Xml.XmlDocument] $xmlDoc = New-Object System.Xml.XmlDocument
        $xmlDoc.Load($webconfig)

        [System.Xml.XmlNode] $modulesNode = $xmlDoc.SelectSingleNode("/configuration/system.webServer/modules")
        if ($null -ne $modulesNode)
        {
            $addNode = $modulesNode.SelectSingleNode("add[@type='Microsoft.Dynamics.AX.HttpModule.SecureCookieHttpModule']")
            if($null -ne $addNode)
            {
                Write-Log "Updating SecureCookieHttpModule node"
                $addNode.type = "Microsoft.Dynamics.AX.HttpModule.SecureCookieHttpModule, Microsoft.Dynamics.AX.HttpModule.SecureCookieHttpModule"
            }
        }

        $xmlDoc.Save($webconfig)

        Write-Log "SecureCookieHttpModule end"
    }
}

# <summary>
# Adds the fileExtensions element to requestFiltering element such that explicit
# file types are excluded from URI access
# </summary>
function Upgrade-WebConfig-Add-RequestFilteringFileExtensions([string] $webConfig)
{
    # Only run this on Platform Update 34 and later
    if ($PlatformReleaseVersion -lt 5585)
    {
        # no-op
        return
    }

    # <fileExtensions allowUnlisted="true">
    #   <add fileExtension=".dll" allowed="false" />
    #   <add fileExtension=".man" allowed="false" />
    # </fileExtensions>

    Write-Log "Upgrade-WebConfig-Add-RequestFilteringFileExtensions start"

    # Load web.config
    [System.Xml.XmlDocument] $xmlDoc = New-Object System.Xml.XmlDocument
    $xmlDoc.Load($webconfig)

    # /configuration/system.webServer/security/requestFiltering
    [System.Xml.XmlNode] $requestFilteringNode = $xmlDoc.SelectSingleNode("/configuration/system.webServer/security/requestFiltering")
    if ($null -ne $requestFilteringNode)
    {
        # Does the fileExtensions element exist?
        [System.Xml.XmlNode] $fileExtensionsNode = $requestFilteringNode.SelectSingleNode("fileExtensions")

        # Create it if necessary
        if ($null -eq $fileExtensionsNode)
        {
            Write-Log "Creating element: fileExtensions"

            $fileExtensionsNode = $xmlDoc.CreateNode("element", "fileExtensions", $null)
            $requestFilteringNode.AppendChild($fileExtensionsNode)
        }

        # Does the allowUnlisted attribute exist and have the correct value?
        [System.Xml.XmlAttribute] $attribute = $fileExtensionsNode.Attributes.GetNamedItem("allowUnlisted")
        if ($null -eq $attribute -or "true" -ne $attribute.Value)
        {
            # Set allowUnlisted attribute to True
            [System.Xml.XmlNode] $allowUnlistedAttribute = $xmlDoc.CreateNode("attribute", "allowUnlisted", $null)
            $allowUnlistedAttribute.Value = "true"

            # set the element attribute
            $fileExtensionsNode.Attributes.SetNamedItem($allowUnlistedAttribute)
        }

        # Exclude file extensions in this list
        $fileExtensions = ".dll", ".man"

        # Loop through the exclusion list
        foreach ($fileExtension in $fileExtensions)
        {
            Add-FileExtensionsElement -xmlDoc $xmlDoc -parentNode $fileExtensionsNode -fileExtensionValue $fileExtension -allowedValue "false"
        }
    }

    # Save web.config
    $xmlDoc.Save($webconfig)

    Write-Log "Upgrade-WebConfig-Add-RequestFilteringFileExtensions end"
}

# <summary>
# Adds the fileExtensions element to the parent node
# </summary>
function Add-FileExtensionsElement([System.Xml.XmlDocument] $xmlDoc, [System.Xml.XmlNode] $parentNode, [string] $fileExtensionValue, [string] $allowedValue)
{
    # Do nothing if the element exists as desired
    if ($null -ne $parentNode.SelectSingleNode("/add[@fileExtension='$fileExtensionValue' and @allowed='$allowedValue']"))
    {
        # no-op
        return
    }

    Write-Log "Add-FileExtensionsElement start"

    # Does the element exist?
    [System.Xml.XmlNode] $addElement = $parentNode.SelectSingleNode("add[@fileExtension='$fileExtensionValue']")
    if ($null -eq $addElement)
    {
        Write-Log "Creating element add with attribute fileExtension having value $fileExtensionValue"

        # create the element
        $addElement = $xmlDoc.CreateNode("element", "add", $null)

        [System.Xml.XmlNode] $fileExtensionAttribute = $xmlDoc.CreateNode("attribute", "fileExtension", $null)
        $fileExtensionAttribute.Value = $fileExtensionValue

        # set the element attribute
        $addElement.Attributes.SetNamedItem($fileExtensionAttribute)

        # add the element to the parent node
        $parentNode.AppendChild($addElement)
    }

    # Does the allowed attribute exist and have the correct value?
    [System.Xml.XmlAttribute] $attribute = $addElement.Attributes.GetNamedItem("allowed")
    if ($null -eq $attribute -or $allowedValue -ne $attribute.Value)
    {
        # Set allowed attribute to the correct value
        [System.Xml.XmlNode] $allowedAttribute = $xmlDoc.CreateNode("attribute", "allowed", $null)
        $allowedAttribute.Value = $allowedValue

        # set the element attribute
        $addElement.Attributes.SetNamedItem($allowedAttribute)
    }

    Write-Log "Add-FileExtensionsElement end"
}

<#
.SYNOPSIS
    Gets the major version of IIS from registry.

.NOTES
    Used only from within this module.
#>
function Get-IISVersion-Major()
{
    $majorVersion = 0

    try
    {
        $obj = Get-ItemProperty -Path registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\InetStp\ -Name "MajorVersion"
        if ($null -ne $obj)
        {
            $majorVersion = $obj.MajorVersion
        }
    }
    catch
    {
        # no-op
    }

    return $majorVersion
}

Export-ModuleMember -Function Initialize-Log, Write-Log, Write-Error, Create-Backup, Upgrade-Web-Config, Encrypt-Config, Decrypt-Config -Variable $logfile
# SIG # Begin signature block
# MIIsAAYJKoZIhvcNAQcCoIIr8TCCK+0CAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCCUp8rr57HjZq4B
# U8VQsEKm6VCEAn/f9+EInbtUb3d5haCCEW4wggh+MIIHZqADAgECAhM2AAACAO38
# jbec3qFIAAIAAAIAMA0GCSqGSIb3DQEBCwUAMEExEzARBgoJkiaJk/IsZAEZFgNH
# QkwxEzARBgoJkiaJk/IsZAEZFgNBTUUxFTATBgNVBAMTDEFNRSBDUyBDQSAwMTAe
# Fw0yNDExMDgxMjQzMjhaFw0yNTExMDgxMjQzMjhaMCQxIjAgBgNVBAMTGU1pY3Jv
# c29mdCBBenVyZSBDb2RlIFNpZ24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
# AoIBAQC5L/UPrOpwYjxcoZC0TqqvMF1WUELvwXN+k27SrA5rohJknn7Cgbxg4hGT
# XKqpcdbtsVTN3ZY896SJ20uQ+INL5OVLzpW408nCNTPYg2LtGJbqHUjpNm0hLCJ+
# gO5Jn2T8DDzIJoUijGXj1m+hRLKb2nOIicCED2GuYBmuWXnaY7INmVEaU3peryty
# ZjDuxdyGDuiPURz8lW1SUiDzoszNp1oswVr+WjDvLDUx4HlxPsG8zUjIst0NnJ6o
# z4tNFKaUBDCetcMjQxpCETn29a1CuRddxZLjPHZHfcotr5sh1S6bNQdzVaMNsxV8
# L3wjHb7XJ6ZVm662mHEiPgpyNcLhAgMBAAGjggWKMIIFhjApBgkrBgEEAYI3FQoE
# HDAaMAwGCisGAQQBgjdbAQEwCgYIKwYBBQUHAwMwPQYJKwYBBAGCNxUHBDAwLgYm
# KwYBBAGCNxUIhpDjDYTVtHiE8Ys+hZvdFs6dEoFgg93NZoaUjDICAWQCAQ4wggJ2
# BggrBgEFBQcBAQSCAmgwggJkMGIGCCsGAQUFBzAChlZodHRwOi8vY3JsLm1pY3Jv
# c29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJQ1NDQTAxLkFNRS5HQkxfQU1F
# JTIwQ1MlMjBDQSUyMDAxKDIpLmNydDBSBggrBgEFBQcwAoZGaHR0cDovL2NybDEu
# YW1lLmdibC9haWEvQlkyUEtJQ1NDQTAxLkFNRS5HQkxfQU1FJTIwQ1MlMjBDQSUy
# MDAxKDIpLmNydDBSBggrBgEFBQcwAoZGaHR0cDovL2NybDIuYW1lLmdibC9haWEv
# QlkyUEtJQ1NDQTAxLkFNRS5HQkxfQU1FJTIwQ1MlMjBDQSUyMDAxKDIpLmNydDBS
# BggrBgEFBQcwAoZGaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJQ1NDQTAx
# LkFNRS5HQkxfQU1FJTIwQ1MlMjBDQSUyMDAxKDIpLmNydDBSBggrBgEFBQcwAoZG
# aHR0cDovL2NybDQuYW1lLmdibC9haWEvQlkyUEtJQ1NDQTAxLkFNRS5HQkxfQU1F
# JTIwQ1MlMjBDQSUyMDAxKDIpLmNydDCBrQYIKwYBBQUHMAKGgaBsZGFwOi8vL0NO
# PUFNRSUyMENTJTIwQ0ElMjAwMSxDTj1BSUEsQ049UHVibGljJTIwS2V5JTIwU2Vy
# dmljZXMsQ049U2VydmljZXMsQ049Q29uZmlndXJhdGlvbixEQz1BTUUsREM9R0JM
# P2NBQ2VydGlmaWNhdGU/YmFzZT9vYmplY3RDbGFzcz1jZXJ0aWZpY2F0aW9uQXV0
# aG9yaXR5MB0GA1UdDgQWBBST/HE52ZUlmsYqZcZBdrXZ5u4ZnzAOBgNVHQ8BAf8E
# BAMCB4AwRQYDVR0RBD4wPKQ6MDgxHjAcBgNVBAsTFU1pY3Jvc29mdCBDb3Jwb3Jh
# dGlvbjEWMBQGA1UEBRMNMjM2MTY3KzUwMzE1NTCCAeYGA1UdHwSCAd0wggHZMIIB
# 1aCCAdGgggHNhj9odHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ1JM
# L0FNRSUyMENTJTIwQ0ElMjAwMSgyKS5jcmyGMWh0dHA6Ly9jcmwxLmFtZS5nYmwv
# Y3JsL0FNRSUyMENTJTIwQ0ElMjAwMSgyKS5jcmyGMWh0dHA6Ly9jcmwyLmFtZS5n
# YmwvY3JsL0FNRSUyMENTJTIwQ0ElMjAwMSgyKS5jcmyGMWh0dHA6Ly9jcmwzLmFt
# ZS5nYmwvY3JsL0FNRSUyMENTJTIwQ0ElMjAwMSgyKS5jcmyGMWh0dHA6Ly9jcmw0
# LmFtZS5nYmwvY3JsL0FNRSUyMENTJTIwQ0ElMjAwMSgyKS5jcmyGgb1sZGFwOi8v
# L0NOPUFNRSUyMENTJTIwQ0ElMjAwMSgyKSxDTj1CWTJQS0lDU0NBMDEsQ049Q0RQ
# LENOPVB1YmxpYyUyMEtleSUyMFNlcnZpY2VzLENOPVNlcnZpY2VzLENOPUNvbmZp
# Z3VyYXRpb24sREM9QU1FLERDPUdCTD9jZXJ0aWZpY2F0ZVJldm9jYXRpb25MaXN0
# P2Jhc2U/b2JqZWN0Q2xhc3M9Y1JMRGlzdHJpYnV0aW9uUG9pbnQwHwYDVR0jBBgw
# FoAUllGE4Gtve/7YBqvD8oXmKa5q+dQwHwYDVR0lBBgwFgYKKwYBBAGCN1sBAQYI
# KwYBBQUHAwMwDQYJKoZIhvcNAQELBQADggEBAEDd8Wf5RkHsB64vgn2slxDtHzSo
# It9xN/Dm3RdFjNZ0diTUPMgSPYQlSk8nIAfudnB9FLavGlvZLlyUpfrPSuikepj3
# i3pqNEFn6fNdNFv/wHMxv7hQTIDCmuoR1v1rX+w3oeleBPMnN3QmH4ff1NsynyV4
# dZdYgN9Cw9sC/S3pWZpJrbOs7YOM3vqyU6DciHhC4D9i2zByHCF2pu9nYfiQf5A2
# iUZenRvyo1E5rC+UP2VZXa4k7g66W20+zAajIKKIqEmRtWahekMkCcOIHFBY4RDA
# ybgPRSGur4VDAiZPjTXS90wQXrX9CwU20cfiCC6e76F4H95KtQjKYpzuNVAwggjo
# MIIG0KADAgECAhMfAAAAUeqP9pxzDKg7AAAAAABRMA0GCSqGSIb3DQEBCwUAMDwx
# EzARBgoJkiaJk/IsZAEZFgNHQkwxEzARBgoJkiaJk/IsZAEZFgNBTUUxEDAOBgNV
# BAMTB2FtZXJvb3QwHhcNMjEwNTIxMTg0NDE0WhcNMjYwNTIxMTg1NDE0WjBBMRMw
# EQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRUwEwYDVQQD
# EwxBTUUgQ1MgQ0EgMDEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDJ
# mlIJfQGejVbXKpcyFPoFSUllalrinfEV6JMc7i+bZDoL9rNHnHDGfJgeuRIYO1LY
# /1f4oMTrhXbSaYRCS5vGc8145WcTZG908bGDCWr4GFLc411WxA+Pv2rteAcz0eHM
# H36qTQ8L0o3XOb2n+x7KJFLokXV1s6pF/WlSXsUBXGaCIIWBXyEchv+sM9eKDsUO
# LdLTITHYJQNWkiryMSEbxqdQUTVZjEz6eLRLkofDAo8pXirIYOgM770CYOiZrcKH
# K7lYOVblx22pdNawY8Te6a2dfoCaWV1QUuazg5VHiC4p/6fksgEILptOKhx9c+ia
# piNhMrHsAYx9pUtppeaFAgMBAAGjggTcMIIE2DASBgkrBgEEAYI3FQEEBQIDAgAC
# MCMGCSsGAQQBgjcVAgQWBBQSaCRCIUfL1Gu+Mc8gpMALI38/RzAdBgNVHQ4EFgQU
# llGE4Gtve/7YBqvD8oXmKa5q+dQwggEEBgNVHSUEgfwwgfkGBysGAQUCAwUGCCsG
# AQUFBwMBBggrBgEFBQcDAgYKKwYBBAGCNxQCAQYJKwYBBAGCNxUGBgorBgEEAYI3
# CgMMBgkrBgEEAYI3FQYGCCsGAQUFBwMJBggrBgEFBQgCAgYKKwYBBAGCN0ABAQYL
# KwYBBAGCNwoDBAEGCisGAQQBgjcKAwQGCSsGAQQBgjcVBQYKKwYBBAGCNxQCAgYK
# KwYBBAGCNxQCAwYIKwYBBQUHAwMGCisGAQQBgjdbAQEGCisGAQQBgjdbAgEGCisG
# AQQBgjdbAwEGCisGAQQBgjdbBQEGCisGAQQBgjdbBAEGCisGAQQBgjdbBAIwGQYJ
# KwYBBAGCNxQCBAweCgBTAHUAYgBDAEEwCwYDVR0PBAQDAgGGMBIGA1UdEwEB/wQI
# MAYBAf8CAQAwHwYDVR0jBBgwFoAUKV5RXmSuNLnrrJwNp4x1AdEJCygwggFoBgNV
# HR8EggFfMIIBWzCCAVegggFToIIBT4YxaHR0cDovL2NybC5taWNyb3NvZnQuY29t
# L3BraWluZnJhL2NybC9hbWVyb290LmNybIYjaHR0cDovL2NybDIuYW1lLmdibC9j
# cmwvYW1lcm9vdC5jcmyGI2h0dHA6Ly9jcmwzLmFtZS5nYmwvY3JsL2FtZXJvb3Qu
# Y3JshiNodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9hbWVyb290LmNybIaBqmxkYXA6
# Ly8vQ049YW1lcm9vdCxDTj1BTUVSb290LENOPUNEUCxDTj1QdWJsaWMlMjBLZXkl
# MjBTZXJ2aWNlcyxDTj1TZXJ2aWNlcyxDTj1Db25maWd1cmF0aW9uLERDPUFNRSxE
# Qz1HQkw/Y2VydGlmaWNhdGVSZXZvY2F0aW9uTGlzdD9iYXNlP29iamVjdENsYXNz
# PWNSTERpc3RyaWJ1dGlvblBvaW50MIIBqwYIKwYBBQUHAQEEggGdMIIBmTBHBggr
# BgEFBQcwAoY7aHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL2NlcnRz
# L0FNRVJvb3RfYW1lcm9vdC5jcnQwNwYIKwYBBQUHMAKGK2h0dHA6Ly9jcmwyLmFt
# ZS5nYmwvYWlhL0FNRVJvb3RfYW1lcm9vdC5jcnQwNwYIKwYBBQUHMAKGK2h0dHA6
# Ly9jcmwzLmFtZS5nYmwvYWlhL0FNRVJvb3RfYW1lcm9vdC5jcnQwNwYIKwYBBQUH
# MAKGK2h0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0FNRVJvb3RfYW1lcm9vdC5jcnQw
# gaIGCCsGAQUFBzAChoGVbGRhcDovLy9DTj1hbWVyb290LENOPUFJQSxDTj1QdWJs
# aWMlMjBLZXklMjBTZXJ2aWNlcyxDTj1TZXJ2aWNlcyxDTj1Db25maWd1cmF0aW9u
# LERDPUFNRSxEQz1HQkw/Y0FDZXJ0aWZpY2F0ZT9iYXNlP29iamVjdENsYXNzPWNl
# cnRpZmljYXRpb25BdXRob3JpdHkwDQYJKoZIhvcNAQELBQADggIBAFAQI7dPD+jf
# XtGt3vJp2pyzA/HUu8hjKaRpM3opya5G3ocprRd7vdTHb8BDfRN+AD0YEmeDB5HK
# QoG6xHPI5TXuIi5sm/LeADbV3C2q0HQOygS/VT+m1W7a/752hMIn+L4ZuyxVeSBp
# fwf7oQ4YSZPh6+ngZvBHgfBaVz4O9/wcfw91QDZnTgK9zAh9yRKKls2bziPEnxeO
# ZMVNaxyV0v152PY2xjqIafIkUjK6vY9LtVFjJXenVUAmn3WCPWNFC1YTIIHw/mD2
# cTfPy7QA1pT+GPARAKt0bKtq9aCd/Ym0b5tPbpgCiRtzyb7fbNS1dE740re0COE6
# 7YV2wbeo2sXixzvLftH8L7s9xv9wV+G22qyKt6lmKLjFK1yMw4Ni5fMabcgmzRvS
# jAcbqgp3tk4a8emaaH0rz8MuuIP+yrxtREPXSqL/C5bzMzsikuDW9xH10graZzSm
# PjilzpRfRdu20/9UQmC7eVPZ4j1WNa1oqPHfzET3ChIzJ6Q9G3NPCB+7KwX0OQmK
# yv7IDimj8U/GlsHD1z+EF/fYMf8YXG15LamaOAohsw/ywO6SYSreVW+5Y0mzJutn
# BC9Cm9ozj1+/4kqksrlhZgR/CSxhFH3BTweH8gP2FEISRtShDZbuYymynY1un+Ry
# fiK9+iVTLdD1h/SxyxDpZMtimb4CgJQlMYIZ6DCCGeQCAQEwWDBBMRMwEQYKCZIm
# iZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRUwEwYDVQQDEwxBTUUg
# Q1MgQ0EgMDECEzYAAAIA7fyNt5zeoUgAAgAAAgAwDQYJYIZIAWUDBAIBBQCgga4w
# GQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEOMAwGCisG
# AQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIEpWMusKna63m3F91sXxqtmyMsx02Zqp
# tlAYCfraqoluMEIGCisGAQQBgjcCAQwxNDAyoBSAEgBNAGkAYwByAG8AcwBvAGYA
# dKEagBhodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20wDQYJKoZIhvcNAQEBBQAEggEA
# DB9BAAOmM3UQt31NhUauoeHFYA6/BQKogG+WcLuIRISk3QRUYCs5ffH8hAbqLvrL
# ar50PfbAI6z8tFdz2bQKa44sNHixnDE8BS38T4alBX7/kKNwg6maHCr9FSr/XJ1A
# ENs1bA0HUifI8sy45TPyVfKSL38BaRN5sPSgcsKDwjhWEdzHDJslfneGL9qGm2aV
# V46DHSmSQfwguUDj0zsPOqjdL5AAiKpNqM/iuchnZpIF0a9T5K5kycuZdLXnpccS
# /h9NqVcaSA1Q/tQLmpSmuw4CL46FEBKIfLW9LZp9Py5/Ger3bVvaQFpBPf/yJyth
# w6n/Xi7jwHvKAuZ6WK9MC6GCF7AwghesBgorBgEEAYI3AwMBMYIXnDCCF5gGCSqG
# SIb3DQEHAqCCF4kwgheFAgEDMQ8wDQYJYIZIAWUDBAIBBQAwggFaBgsqhkiG9w0B
# CRABBKCCAUkEggFFMIIBQQIBAQYKKwYBBAGEWQoDATAxMA0GCWCGSAFlAwQCAQUA
# BCBGMkVg/8EpRmiuwdLrU86uuLx+1vJSmdNizfZjT0huYwIGaBLCZwa8GBMyMDI1
# MDUwOTExMjExNS41ODhaMASAAgH0oIHZpIHWMIHTMQswCQYDVQQGEwJVUzETMBEG
# A1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWlj
# cm9zb2Z0IENvcnBvcmF0aW9uMS0wKwYDVQQLEyRNaWNyb3NvZnQgSXJlbGFuZCBP
# cGVyYXRpb25zIExpbWl0ZWQxJzAlBgNVBAsTHm5TaGllbGQgVFNTIEVTTjoyRDFB
# LTA1RTAtRDk0NzElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2Vydmlj
# ZaCCEf4wggcoMIIFEKADAgECAhMzAAAB/XP5aFrNDGHtAAEAAAH9MA0GCSqGSIb3
# DQEBCwUAMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYD
# VQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAk
# BgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwMB4XDTI0MDcyNTE4
# MzExNloXDTI1MTAyMjE4MzExNlowgdMxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpX
# YXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQg
# Q29ycG9yYXRpb24xLTArBgNVBAsTJE1pY3Jvc29mdCBJcmVsYW5kIE9wZXJhdGlv
# bnMgTGltaXRlZDEnMCUGA1UECxMeblNoaWVsZCBUU1MgRVNOOjJEMUEtMDVFMC1E
# OTQ3MSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFtcCBTZXJ2aWNlMIICIjAN
# BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAoWWs+D+Ou4JjYnRHRedu0MTFYzNJ
# EVPnILzc02R3qbnujvhZgkhp+p/lymYLzkQyG2zpxYceTjIF7HiQWbt6FW3ARkBr
# thJUz05ZnKpcF31lpUEb8gUXiD2xIpo8YM+SD0S+hTP1TCA/we38yZ3BEtmZtcVn
# aLRp/Avsqg+5KI0Kw6TDJpKwTLl0VW0/23sKikeWDSnHQeTprO0zIm/btagSYm3V
# /8zXlfxy7s/EVFdSglHGsUq8EZupUO8XbHzz7tURyiD3kOxNnw5ox1eZX/c/XmW4
# H6b4yNmZF0wTZuw37yA1PJKOySSrXrWEh+H6++Wb6+1ltMCPoMJHUtPP3Cn0CNcN
# vrPyJtDacqjnITrLzrsHdOLqjsH229Zkvndk0IqxBDZgMoY+Ef7ffFRP2pPkrF1F
# 9IcBkYz8hL+QjX+u4y4Uqq4UtT7VRnsqvR/x/+QLE0pcSEh/XE1w1fcp6Jmq8RnH
# EXikycMLN/a/KYxpSP3FfFbLZuf+qIryFL0gEDytapGn1ONjVkiKpVP2uqVIYj4V
# iCjy5pLUceMeqiKgYqhpmUHCE2WssLLhdQBHdpl28+k+ZY6m4dPFnEoGcJHuMcIZ
# nw4cOwixojROr+Nq71cJj7Q4L0XwPvuTHQt0oH7RKMQgmsy7CVD7v55dOhdHXdYs
# yO69dAdK+nWlyYcCAwEAAaOCAUkwggFFMB0GA1UdDgQWBBTpDMXA4ZW8+yL2+3vA
# 6RmU7oEKpDAfBgNVHSMEGDAWgBSfpxVdAF5iXYP05dJlpxtTNRnpcjBfBgNVHR8E
# WDBWMFSgUqBQhk5odHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NybC9N
# aWNyb3NvZnQlMjBUaW1lLVN0YW1wJTIwUENBJTIwMjAxMCgxKS5jcmwwbAYIKwYB
# BQUHAQEEYDBeMFwGCCsGAQUFBzAChlBodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20v
# cGtpb3BzL2NlcnRzL01pY3Jvc29mdCUyMFRpbWUtU3RhbXAlMjBQQ0ElMjAyMDEw
# KDEpLmNydDAMBgNVHRMBAf8EAjAAMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMIMA4G
# A1UdDwEB/wQEAwIHgDANBgkqhkiG9w0BAQsFAAOCAgEAY9hYX+T5AmCrYGaH96Td
# R5T52/PNOG7ySYeopv4flnDWQLhBlravAg+pjlNv5XSXZrKGv8e4s5dJ5WdhfC9y
# wFQq4TmXnUevPXtlubZk+02BXK6/23hM0TSKs2KlhYiqzbRe8QbMfKXEDtvMoHSZ
# T7r+wI2IgjYQwka+3P9VXgERwu46/czz8IR/Zq+vO5523Jld6ssVuzs9uwIrJhfc
# YBj50mXWRBcMhzajLjWDgcih0DuykPcBpoTLlOL8LpXooqnr+QLYE4BpUep3JySM
# YfPz2hfOL3g02WEfsOxp8ANbcdiqM31dm3vSheEkmjHA2zuM+Tgn4j5n+Any7IOD
# YQkIrNVhLdML09eu1dIPhp24lFtnWTYNaFTOfMqFa3Ab8KDKicmp0AthRNZVg0BP
# AL58+B0UcoBGKzS9jscwOTu1JmNlisOKkVUVkSJ5Fo/ctfDSPdCTVaIXXF7l40k1
# cM/X2O0JdAS97T78lYjtw/PybuzX5shxBh/RqTPvCyAhIxBVKfN/hfs4CIoFaqWJ
# 0r/8SB1CGsyyIcPfEgMo8ceq1w5Zo0JfnyFi6Guo+z3LPFl/exQaRubErsAUTfyB
# Y5/5liyvjAgyDYnEB8vHO7c7Fg2tGd5hGgYs+AOoWx24+XcyxpUkAajDhky9Dl+8
# JZTjts6BcT9sYTmOodk/SgIwggdxMIIFWaADAgECAhMzAAAAFcXna54Cm0mZAAAA
# AAAVMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2Fz
# aGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENv
# cnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3NvZnQgUm9vdCBDZXJ0aWZpY2F0ZSBB
# dXRob3JpdHkgMjAxMDAeFw0yMTA5MzAxODIyMjVaFw0zMDA5MzAxODMyMjVaMHwx
# CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRt
# b25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1p
# Y3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwMIICIjANBgkqhkiG9w0BAQEFAAOC
# Ag8AMIICCgKCAgEA5OGmTOe0ciELeaLL1yR5vQ7VgtP97pwHB9KpbE51yMo1V/YB
# f2xK4OK9uT4XYDP/XE/HZveVU3Fa4n5KWv64NmeFRiMMtY0Tz3cywBAY6GB9alKD
# RLemjkZrBxTzxXb1hlDcwUTIcVxRMTegCjhuje3XD9gmU3w5YQJ6xKr9cmmvHaus
# 9ja+NSZk2pg7uhp7M62AW36MEBydUv626GIl3GoPz130/o5Tz9bshVZN7928jaTj
# kY+yOSxRnOlwaQ3KNi1wjjHINSi947SHJMPgyY9+tVSP3PoFVZhtaDuaRr3tpK56
# KTesy+uDRedGbsoy1cCGMFxPLOJiss254o2I5JasAUq7vnGpF1tnYN74kpEeHT39
# IM9zfUGaRnXNxF803RKJ1v2lIH1+/NmeRd+2ci/bfV+AutuqfjbsNkz2K26oElHo
# vwUDo9Fzpk03dJQcNIIP8BDyt0cY7afomXw/TNuvXsLz1dhzPUNOwTM5TI4CvEJo
# LhDqhFFG4tG9ahhaYQFzymeiXtcodgLiMxhy16cg8ML6EgrXY28MyTZki1ugpoMh
# XV8wdJGUlNi5UPkLiWHzNgY1GIRH29wb0f2y1BzFa/ZcUlFdEtsluq9QBXpsxREd
# cu+N+VLEhReTwDwV2xo3xwgVGD94q0W29R6HXtqPnhZyacaue7e3PmriLq0CAwEA
# AaOCAd0wggHZMBIGCSsGAQQBgjcVAQQFAgMBAAEwIwYJKwYBBAGCNxUCBBYEFCqn
# Uv5kxJq+gpE8RjUpzxD/LwTuMB0GA1UdDgQWBBSfpxVdAF5iXYP05dJlpxtTNRnp
# cjBcBgNVHSAEVTBTMFEGDCsGAQQBgjdMg30BATBBMD8GCCsGAQUFBwIBFjNodHRw
# Oi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL0RvY3MvUmVwb3NpdG9yeS5odG0w
# EwYDVR0lBAwwCgYIKwYBBQUHAwgwGQYJKwYBBAGCNxQCBAweCgBTAHUAYgBDAEEw
# CwYDVR0PBAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAU1fZWy4/o
# olxiaNE9lJBb186aGMQwVgYDVR0fBE8wTTBLoEmgR4ZFaHR0cDovL2NybC5taWNy
# b3NvZnQuY29tL3BraS9jcmwvcHJvZHVjdHMvTWljUm9vQ2VyQXV0XzIwMTAtMDYt
# MjMuY3JsMFoGCCsGAQUFBwEBBE4wTDBKBggrBgEFBQcwAoY+aHR0cDovL3d3dy5t
# aWNyb3NvZnQuY29tL3BraS9jZXJ0cy9NaWNSb29DZXJBdXRfMjAxMC0wNi0yMy5j
# cnQwDQYJKoZIhvcNAQELBQADggIBAJ1VffwqreEsH2cBMSRb4Z5yS/ypb+pcFLY+
# TkdkeLEGk5c9MTO1OdfCcTY/2mRsfNB1OW27DzHkwo/7bNGhlBgi7ulmZzpTTd2Y
# urYeeNg2LpypglYAA7AFvonoaeC6Ce5732pvvinLbtg/SHUB2RjebYIM9W0jVOR4
# U3UkV7ndn/OOPcbzaN9l9qRWqveVtihVJ9AkvUCgvxm2EhIRXT0n4ECWOKz3+SmJ
# w7wXsFSFQrP8DJ6LGYnn8AtqgcKBGUIZUnWKNsIdw2FzLixre24/LAl4FOmRsqlb
# 30mjdAy87JGA0j3mSj5mO0+7hvoyGtmW9I/2kQH2zsZ0/fZMcm8Qq3UwxTSwethQ
# /gpY3UA8x1RtnWN0SCyxTkctwRQEcb9k+SS+c23Kjgm9swFXSVRk2XPXfx5bRAGO
# WhmRaw2fpCjcZxkoJLo4S5pu+yFUa2pFEUep8beuyOiJXk+d0tBMdrVXVAmxaQFE
# fnyhYWxz/gq77EFmPWn9y8FBSX5+k77L+DvktxW/tM4+pTFRhLy/AsGConsXHRWJ
# jXD+57XQKBqJC4822rpM+Zv/Cuk0+CQ1ZyvgDbjmjJnW4SLq8CdCPSWU5nR0W2rR
# nj7tfqAxM328y+l7vzhwRNGQ8cirOoo6CGJ/2XBjU02N7oJtpQUQwXEGahC0HVUz
# WLOhcGbyoYIDWTCCAkECAQEwggEBoYHZpIHWMIHTMQswCQYDVQQGEwJVUzETMBEG
# A1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWlj
# cm9zb2Z0IENvcnBvcmF0aW9uMS0wKwYDVQQLEyRNaWNyb3NvZnQgSXJlbGFuZCBP
# cGVyYXRpb25zIExpbWl0ZWQxJzAlBgNVBAsTHm5TaGllbGQgVFNTIEVTTjoyRDFB
# LTA1RTAtRDk0NzElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2Vydmlj
# ZaIjCgEBMAcGBSsOAwIaAxUAoj0WtVVQUNSKoqtrjinRAsBUdoOggYMwgYCkfjB8
# MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVk
# bW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1N
# aWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDANBgkqhkiG9w0BAQsFAAIFAOvH
# zGEwIhgPMjAyNTA1MDkwMDM1NDVaGA8yMDI1MDUxMDAwMzU0NVowdzA9BgorBgEE
# AYRZCgQBMS8wLTAKAgUA68fMYQIBADAKAgEAAgIouwIB/zAHAgEAAgIS0TAKAgUA
# 68kd4QIBADA2BgorBgEEAYRZCgQCMSgwJjAMBgorBgEEAYRZCgMCoAowCAIBAAID
# B6EgoQowCAIBAAIDAYagMA0GCSqGSIb3DQEBCwUAA4IBAQCrGgQOuM675gC6D4xr
# TqAww8EFl9Wr34WBLnset0yQrJxQ4MnK1OiQvVqPdpawtSJc5e9l4XXeh0vmfcH6
# AZUBHDDYWxonhCQUAcTagQ/R3mqdaNQNCueC0oJxmEp30T1KTFrH5k+CQjnWkz5w
# HmTfysjFXOEC4X8t2I4yADbQaz0iULhfGesdchsgazOWAtTSpMjr/S5oYFBWj4JZ
# usskaLjgmNppiC8GGecJA5f+t+o5+EcTEySkCPjk8WGq1SSYlJHUrfIdNa02Dvrj
# eFs+GyfQBja/5PwqIttZZ71D4xRigiKQLu3zp2ucHRIuCm0l5BRuyzuWZhKX5Rte
# ayktMYIEDTCCBAkCAQEwgZMwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hp
# bmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jw
# b3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAC
# EzMAAAH9c/loWs0MYe0AAQAAAf0wDQYJYIZIAWUDBAIBBQCgggFKMBoGCSqGSIb3
# DQEJAzENBgsqhkiG9w0BCRABBDAvBgkqhkiG9w0BCQQxIgQgLHqxl+08l3imdF8s
# Jls28+5stcCLUAQzDzELv9A1hu0wgfoGCyqGSIb3DQEJEAIvMYHqMIHnMIHkMIG9
# BCCAKEgNyUowvIfx/eDfYSupHkeF1p6GFwjKBs8lRB4NRzCBmDCBgKR+MHwxCzAJ
# BgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25k
# MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jv
# c29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMzAAAB/XP5aFrNDGHtAAEAAAH9MCIE
# IKpHDsQqi6DpZi5QtG3yk3l8DcKYlrkb0iIyhuhLAKbAMA0GCSqGSIb3DQEBCwUA
# BIICAHnKQR2iF4VqDsEm9ERP1CjDwjuFxgfcZQkVt2XW/5tR+M75IALm9nz6NvCe
# tqWdPn0ZnJGs44+Oq28KGEX5BSjTLTQ1NBnjiyTJgFIidmGe/JBrypsH/EAkZukm
# hCz2lx5r+wQPaAv3JNQKFJcibk80ZsUaxSkcfq6926xP5kj9LOVXyuYwUKXeIV++
# 2pinjNNU+JUoPQlc9+PUeGxdXGZWjxiL7+BEhnKX22QrCa6WEYy8V5KCNLspLa83
# H2+P1odJI+1Dr30Lj1urtO7J0RYUVbtFw66AeUG5RVumZ7WGNJMrBVZNetYH3o+I
# 3rmL2h6rkBFZKk9uBPX2mszoD/vWG4NOfwnHmzbeYV8L0TjA10YUuSrLDSIawJjz
# 71ytNCRuKmAnD3LkZPZ4ymIe9sdoypYWt92c9rz59+zaGuawhITNn1VPvgtPshif
# XYxt1Fl6ugwHE79IIEgOtvtUHO5EagJxtIzetEPaQfqt6eqRe2CKetQub+6qP0QS
# wXez+M+NOAJDmxkJyRFevfURzYi3cpNc0o0FJTeSHzQxm+015Z8EFceyC/y5DhIz
# GeXrzg+RCVvMGMRzijiR5VLe+8rmLeqeUrKcoyt+g0cvslLGFsQVRIFEOCCYQf4S
# 6LQle83drLTzunY7/WhBKxcf0Ck9u9XY7UErQSpKDQ6bKR4l
# SIG # End signature block
