public/New-AppVentiXShortcutUserSetting.ps1
|
<#
.SYNOPSIS Creates an AppVentiX UserSetting XML file for a Shortcuts configuration. .DESCRIPTION Builds and saves an AppVentiX UserSetting XML file that defines one or more shortcuts, including executable path, arguments, working directory, desktop placement, and icon data. Supports two input modes: - ShortcutEntries mode: accepts an array of hashtables describing individual shortcut entries. - InputObject mode: accepts a pre-structured PSCustomObject (e.g. from Get-IvantiWCShortcut), which includes shortcut metadata and icon data (base64) ready for direct use. Icon data handling: - If the InputObject or ShortcutEntry already contains base64 icon data, it is used as-is. - If icon data is absent and an IconFile path is provided, the function generates all icon sizes (16, 32, 48, 256 and default 32) from that file. - If neither is available, a warning is issued and icon fields are left empty. .PARAMETER FriendlyName Display name for the AppVentiX UserSetting. .PARAMETER Description Optional description for the UserSetting. .PARAMETER ExecutionOrder Execution order for the UserSetting. Defaults to 0. .PARAMETER ProcessAtLogin Whether the setting is applied at login. Defaults to $true. .PARAMETER ProcessAtRefresh Whether the setting is applied at refresh. Defaults to $true. .PARAMETER ProcessAtReconnectAndUnlock Whether the setting is applied at reconnect and unlock. Defaults to $false. .PARAMETER MachineGroupFriendlyName One or more machine group friendly names to apply the setting to. Defaults to 'All Machine Groups'. .PARAMETER ShortcutEntries Array of hashtables describing shortcut entries. Each entry must contain: ShortcutName, ExecutablePath. Optional keys: Arguments, WorkingDirectory, PlaceOnDesktop, IconData, IconData16, IconData32, IconData48, IconData256, IconFile, EntryId (generated when omitted), FileTypeAssociations. FileTypeAssociations is an array of hashtables or objects with Extension and optional TypeDescription, linked to the EntryId of the entry they are defined in. FileAssociations with Extension and Description (Get-IvantiWCApplication output) is accepted as well. .PARAMETER InputObject Pre-structured PSCustomObject containing shortcut metadata and entries. Optional properties CaptureRules and EnforceFileTypeAssociations are used when the matching parameter is not specified. .PARAMETER IconFile Path to a PNG, ICO, or EXE file used as icon source when icon data is absent in the entries. The function will generate all required icon sizes from this file. .PARAMETER CaptureRules Array of hashtables describing User State Roaming capture rules. UserStateRoaming is enabled when at least one rule is provided. Each rule must contain: Kind (Folder, File or Registry), Path. Optional keys: Exclude, IncludeSubfolders (default True), Enabled (default True), Description, RuleId (generated when omitted). .PARAMETER EnforceFileTypeAssociations Whether the file type associations are enforced. Defaults to $true. Written as False when no file type associations are defined. .PARAMETER ConfigShare Path to the AppVentiX config share. Defaults to the module variable. .EXAMPLE New-AppVentiXShortcutUserSetting -FriendlyName "Notepad++" -ShortcutEntries @( @{ ShortcutName = "Notepad++" ExecutablePath = "C:\Program Files\Notepad++\notepad++.exe" FileTypeAssociations = @(@{ Extension = ".txt" }) } ) -CaptureRules @( @{ Kind = "Folder"; Path = "%APPDATA%\Notepad++" } @{ Kind = "Registry"; Path = "HKCU\Software\Notepad++" } ) .LINK Get-AppVentiXUserSettings .LINK New-AppVentiXDriveMappingUserSetting .LINK New-AppVentiXEnvironmentVariableUserSetting .LINK New-AppVentiXGroupPolicyUserSetting .LINK New-AppVentiXPrinterMappingUserSetting .LINK New-AppVentiXRegistryUserSetting .LINK Set-AppVentiXUserSettingFolder .LINK Set-AppVentiXUserSettingsAssignment .NOTES Function : New-AppVentiXShortcutUserSetting Author : John Billekens Copyright : (c) John Billekens Consultancy & AppVentiX Version : 2026.321.1000 #> function New-AppVentiXShortcutUserSetting { [CmdletBinding()] [Alias("New-AppVentiXShortcut")] param ( [Parameter(Mandatory = $true, ParameterSetName = "ShortcutEntries")] [Parameter(Mandatory = $false, ParameterSetName = "InputObject")] [string]$FriendlyName, [Parameter(Mandatory = $false, ParameterSetName = "ShortcutEntries")] [Parameter(Mandatory = $false, ParameterSetName = "InputObject")] [string]$Description, [Parameter(Mandatory = $false, ParameterSetName = "ShortcutEntries")] [Parameter(Mandatory = $false, ParameterSetName = "InputObject")] [int]$ExecutionOrder = 0, [Parameter(Mandatory = $false, ParameterSetName = "ShortcutEntries")] [Parameter(Mandatory = $false, ParameterSetName = "InputObject")] [bool]$ProcessAtLogin = $true, [Parameter(Mandatory = $false, ParameterSetName = "ShortcutEntries")] [Parameter(Mandatory = $false, ParameterSetName = "InputObject")] [bool]$ProcessAtRefresh = $true, [Parameter(Mandatory = $false, ParameterSetName = "ShortcutEntries")] [Parameter(Mandatory = $false, ParameterSetName = "InputObject")] [bool]$ProcessAtReconnectAndUnlock = $false, [Parameter(Mandatory = $false, ParameterSetName = "ShortcutEntries")] [Parameter(Mandatory = $false, ParameterSetName = "InputObject")] [string[]]$MachineGroupFriendlyName = @("All Machine Groups"), [Parameter(Mandatory = $true, ParameterSetName = "ShortcutEntries")] [hashtable[]]$ShortcutEntries = @(), [Parameter(Mandatory = $true, ParameterSetName = "InputObject")] [PSCustomObject]$InputObject, [Parameter(Mandatory = $false, ParameterSetName = "ShortcutEntries")] [Parameter(Mandatory = $false, ParameterSetName = "InputObject")] [ValidateScript({ Test-Path $_ -PathType Leaf })] [string]$IconFile, [Parameter(Mandatory = $false, ParameterSetName = "ShortcutEntries")] [Parameter(Mandatory = $false, ParameterSetName = "InputObject")] [hashtable[]]$CaptureRules = @(), [Parameter(Mandatory = $false, ParameterSetName = "ShortcutEntries")] [Parameter(Mandatory = $false, ParameterSetName = "InputObject")] [bool]$EnforceFileTypeAssociations = $true, [Parameter(DontShow)] [ValidateNotNullOrEmpty()] [string]$ConfigShare = $Script:AppVentix.ConfigShare ) #region functions function ConvertFrom-IconFilePath { <# .SYNOPSIS Converts an image file to a base64 PNG string, optionally resized. #> [CmdletBinding()] [OutputType([string])] param( [Parameter(Mandatory = $true)] [string]$Path, [Parameter(Mandatory = $false)] [ValidateRange(16, 256)] [int]$Size = 32 ) try { Add-Type -AssemblyName System.Drawing -ErrorAction Stop $originalImage = [System.Drawing.Image]::FromFile($Path) if ($originalImage.Width -eq $Size -and $originalImage.Height -eq $Size) { $ms = New-Object System.IO.MemoryStream $originalImage.Save($ms, [System.Drawing.Imaging.ImageFormat]::Png) $result = [Convert]::ToBase64String($ms.ToArray()) $ms.Dispose() } else { $resized = New-Object System.Drawing.Bitmap $Size, $Size $g = [System.Drawing.Graphics]::FromImage($resized) $g.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::HighQualityBicubic $g.SmoothingMode = [System.Drawing.Drawing2D.SmoothingMode]::HighQuality $g.PixelOffsetMode = [System.Drawing.Drawing2D.PixelOffsetMode]::HighQuality $g.DrawImage($originalImage, 0, 0, $Size, $Size) $g.Dispose() $ms = New-Object System.IO.MemoryStream $resized.Save($ms, [System.Drawing.Imaging.ImageFormat]::Png) $result = [Convert]::ToBase64String($ms.ToArray()) $ms.Dispose() $resized.Dispose() } $originalImage.Dispose() return $result } catch { Write-Error "Failed to convert icon file '$Path' to Base64: $_" return "" } } function ConvertTo-EntryHashtable { <# .SYNOPSIS Converts a hashtable, dictionary or PSCustomObject to a hashtable. #> [CmdletBinding()] [OutputType([hashtable])] param( [Parameter(Mandatory = $true)] [object]$InputObject ) if ($InputObject -is [System.Collections.IDictionary]) { return [hashtable]$InputObject } $result = @{} foreach ($property in $InputObject.PSObject.Properties) { $result[$property.Name] = $property.Value } return $result } function New-ShortcutUserSettingXml { [CmdletBinding()] param () $XmlDoc = New-Object System.Xml.XmlDocument $Root = $XmlDoc.CreateElement("UserSetting") [void]$XmlDoc.AppendChild($Root) function Add-TextElement { param ( [System.Xml.XmlElement]$Parent, [string]$Name, [string]$Text ) $el = $XmlDoc.CreateElement($Name) $el.InnerText = $Text [void]$Parent.AppendChild($el) return $el } [void](Add-TextElement -Parent $Root -Name "Id" -Text $SettingId) [void](Add-TextElement -Parent $Root -Name "FriendlyName" -Text $FriendlyName) [void](Add-TextElement -Parent $Root -Name "Description" -Text $Description) [void](Add-TextElement -Parent $Root -Name "Type" -Text $Type) [void](Add-TextElement -Parent $Root -Name "ExecutionOrder" -Text $ExecutionOrder) [void](Add-TextElement -Parent $Root -Name "CreatedDate" -Text $CreatedDate) [void](Add-TextElement -Parent $Root -Name "LastModifiedDate" -Text $LastModifiedDate) [void](Add-TextElement -Parent $Root -Name "ProcessAtLogin" -Text (ConvertTo-BooleanString -Value $ProcessAtLogin)) [void](Add-TextElement -Parent $Root -Name "ProcessAtRefresh" -Text (ConvertTo-BooleanString -Value $ProcessAtRefresh)) [void](Add-TextElement -Parent $Root -Name "ProcessAtReconnectAndUnlock" -Text (ConvertTo-BooleanString -Value $ProcessAtReconnectAndUnlock)) $MachineGroupsElement = $XmlDoc.CreateElement("MachineGroups") foreach ($Group in $MachineGroups) { [void](Add-TextElement -Parent $MachineGroupsElement -Name "MachineGroup" -Text $Group) } [void]$Root.AppendChild($MachineGroupsElement) $MachineGroupFriendlyNamesElement = $XmlDoc.CreateElement("MachineGroupFriendlyNames") foreach ($GroupFriendlyName in $MachineGroupFriendlyNames) { [void](Add-TextElement -Parent $MachineGroupFriendlyNamesElement -Name "FriendlyName" -Text $GroupFriendlyName) } [void]$Root.AppendChild($MachineGroupFriendlyNamesElement) $UserStateRoamingElement = $XmlDoc.CreateElement("UserStateRoaming") $UserStateRoamingElement.SetAttribute("Enabled", (ConvertTo-BooleanString -Value ($NewCaptureRules.Count -gt 0))) # Write a full end tag like the console, not a self-closing element $UserStateRoamingElement.IsEmpty = $false foreach ($RuleData in $NewCaptureRules) { $CaptureRuleElement = $XmlDoc.CreateElement("CaptureRule") [void](Add-TextElement -Parent $CaptureRuleElement -Name "RuleId" -Text $RuleData.RuleId) [void](Add-TextElement -Parent $CaptureRuleElement -Name "Kind" -Text $RuleData.Kind) [void](Add-TextElement -Parent $CaptureRuleElement -Name "Path" -Text $RuleData.Path) [void](Add-TextElement -Parent $CaptureRuleElement -Name "Exclude" -Text $RuleData.Exclude) [void](Add-TextElement -Parent $CaptureRuleElement -Name "IncludeSubfolders" -Text (ConvertTo-BooleanString -Value $RuleData.IncludeSubfolders)) [void](Add-TextElement -Parent $CaptureRuleElement -Name "Enabled" -Text (ConvertTo-BooleanString -Value $RuleData.Enabled)) [void](Add-TextElement -Parent $CaptureRuleElement -Name "Description" -Text $RuleData.Description) [void]$UserStateRoamingElement.AppendChild($CaptureRuleElement) } [void]$Root.AppendChild($UserStateRoamingElement) $ShortcutEntriesElement = $XmlDoc.CreateElement("ShortcutEntries") foreach ($EntryData in $NewShortcutEntries) { $ShortcutEntryElement = $XmlDoc.CreateElement("ShortcutEntry") [void](Add-TextElement -Parent $ShortcutEntryElement -Name "ShortcutName" -Text $EntryData.ShortcutName) [void](Add-TextElement -Parent $ShortcutEntryElement -Name "ExecutablePath" -Text $EntryData.ExecutablePath) [void](Add-TextElement -Parent $ShortcutEntryElement -Name "Arguments" -Text $EntryData.Arguments) [void](Add-TextElement -Parent $ShortcutEntryElement -Name "WorkingDirectory" -Text $EntryData.WorkingDirectory) [void](Add-TextElement -Parent $ShortcutEntryElement -Name "PlaceOnDesktop" -Text (ConvertTo-BooleanString -Value ([bool]$EntryData.PlaceOnDesktop))) [void](Add-TextElement -Parent $ShortcutEntryElement -Name "IconData" -Text $EntryData.IconData) [void](Add-TextElement -Parent $ShortcutEntryElement -Name "IconData16" -Text $EntryData.IconData16) [void](Add-TextElement -Parent $ShortcutEntryElement -Name "IconData32" -Text $EntryData.IconData32) [void](Add-TextElement -Parent $ShortcutEntryElement -Name "IconData48" -Text $EntryData.IconData48) [void](Add-TextElement -Parent $ShortcutEntryElement -Name "IconData256" -Text $EntryData.IconData256) [void](Add-TextElement -Parent $ShortcutEntryElement -Name "EntryId" -Text $EntryData.EntryId) [void]$ShortcutEntriesElement.AppendChild($ShortcutEntryElement) } [void]$Root.AppendChild($ShortcutEntriesElement) $FileTypeAssociationsElement = $XmlDoc.CreateElement("FileTypeAssociations") $FileTypeAssociationsElement.SetAttribute("Enforce", (ConvertTo-BooleanString -Value ($EnforceFileTypeAssociations -and $NewFileTypeAssociations.Count -gt 0))) $FileTypeAssociationsElement.IsEmpty = $false foreach ($AssociationData in $NewFileTypeAssociations) { $FileTypeAssociationElement = $XmlDoc.CreateElement("FileTypeAssociation") [void](Add-TextElement -Parent $FileTypeAssociationElement -Name "Extension" -Text $AssociationData.Extension) [void](Add-TextElement -Parent $FileTypeAssociationElement -Name "ShortcutEntryId" -Text $AssociationData.ShortcutEntryId) [void](Add-TextElement -Parent $FileTypeAssociationElement -Name "TypeDescription" -Text $AssociationData.TypeDescription) [void]$FileTypeAssociationsElement.AppendChild($FileTypeAssociationElement) } [void]$Root.AppendChild($FileTypeAssociationsElement) return $XmlDoc } #endregion functions if (Test-AppVentiXIsLicensed -ConfigShare $ConfigShare) { $SettingId = [guid]::NewGuid().ToString() $Type = "Shortcuts" # Process InputObject if ($PSBoundParameters.ContainsKey("InputObject")) { Write-Verbose "Processing InputObject parameter..." if (-not [string]::IsNullOrEmpty($InputObject.FriendlyName)) { $FriendlyName = $InputObject.FriendlyName } if (-not [string]::IsNullOrEmpty($InputObject.Description)) { $Description = $InputObject.Description } if ($PSBoundParameters.ContainsKey("ProcessAtLogin") -eq $false -and $null -ne $InputObject.ProcessAtLogin) { $ProcessAtLogin = [bool]$InputObject.ProcessAtLogin } if ($PSBoundParameters.ContainsKey("ProcessAtRefresh") -eq $false -and $null -ne $InputObject.ProcessAtRefresh) { $ProcessAtRefresh = [bool]$InputObject.ProcessAtRefresh } if ($PSBoundParameters.ContainsKey("ProcessAtReconnectAndUnlock") -eq $false -and $null -ne $InputObject.ProcessAtReconnectAndUnlock) { $ProcessAtReconnectAndUnlock = [bool]$InputObject.ProcessAtReconnectAndUnlock } $ShortcutEntries = @( $InputObject.ShortcutEntries | ForEach-Object { @{ ShortcutName = "$($_.ShortcutName)" ExecutablePath = "$($_.ExecutablePath)" Arguments = "$($_.Arguments)" WorkingDirectory = "$($_.WorkingDirectory)" PlaceOnDesktop = $_.PlaceOnDesktop IconData = "$($_.IconData)" IconData16 = "$($_.IconData16)" IconData32 = "$($_.IconData32)" IconData48 = "$($_.IconData48)" IconData256 = "$($_.IconData256)" EntryId = "$($_.EntryId)" FileTypeAssociations = @($_.FileTypeAssociations) + @($_.FileAssociations) } } ) if ($PSBoundParameters.ContainsKey("CaptureRules") -eq $false -and $null -ne $InputObject.CaptureRules) { $CaptureRules = @($InputObject.CaptureRules | ForEach-Object { ConvertTo-EntryHashtable -InputObject $_ }) } if ($PSBoundParameters.ContainsKey("EnforceFileTypeAssociations") -eq $false -and $null -ne $InputObject.EnforceFileTypeAssociations) { $EnforceFileTypeAssociations = [bool]$InputObject.EnforceFileTypeAssociations } } # Resolve MachineGroups if ($MachineGroupFriendlyName.Count -gt 0) { if ($MachineGroupFriendlyName -notcontains "All Machine Groups" -and $MachineGroupFriendlyName -notcontains "All" -and $MachineGroupFriendlyName.Count -gt 0) { $AvailableGroups = Get-AppVentiXMachineGroup $MachineGroups = @() $MachineGroupFriendlyNames = @() foreach ($Group in $MachineGroupFriendlyName) { $selectedGroup = $AvailableGroups | Where-Object { $_.FriendlyName -ieq $Group } if ($selectedGroup) { $MachineGroups += $selectedGroup.GroupName.ToString() $MachineGroupFriendlyNames += $selectedGroup.FriendlyName.ToString() } } } else { $MachineGroups = @("All") $MachineGroupFriendlyNames = @("All Machine Groups") } } else { $MachineGroups = @("All") $MachineGroupFriendlyNames = @("All Machine Groups") } #region --- Build $NewShortcutEntries --- $NewShortcutEntries = @() $NewFileTypeAssociations = @() foreach ($entry in $ShortcutEntries) { if (-not ($entry.ContainsKey("ShortcutName") -and $entry.ContainsKey("ExecutablePath"))) { Write-Error "Each shortcut entry must be a hashtable containing at least the keys: ShortcutName, ExecutablePath" return } $NewEntry = [ordered]@{ ShortcutName = "$($entry.ShortcutName)" ExecutablePath = "$($entry.ExecutablePath)" Arguments = "$($entry.Arguments)" WorkingDirectory = "$($entry.WorkingDirectory)" PlaceOnDesktop = $false IconData = "$($entry.IconData)" IconData16 = "$($entry.IconData16)" IconData32 = "$($entry.IconData32)" IconData48 = "$($entry.IconData48)" IconData256 = "$($entry.IconData256)" EntryId = if ([string]::IsNullOrEmpty($entry.EntryId)) { [guid]::NewGuid().ToString() } else { "$($entry.EntryId)" } } # Normalize PlaceOnDesktop switch ($entry.PlaceOnDesktop) { "True" { $NewEntry.PlaceOnDesktop = $true } "False" { $NewEntry.PlaceOnDesktop = $false } "1" { $NewEntry.PlaceOnDesktop = $true } "0" { $NewEntry.PlaceOnDesktop = $false } $true { $NewEntry.PlaceOnDesktop = $true } $false { $NewEntry.PlaceOnDesktop = $false } default { $NewEntry.PlaceOnDesktop = $false } } # Icon resolution: use base64 from entry if present, otherwise fall back to IconFile $iconSizes = @{ IconData = 32; IconData16 = 16; IconData32 = 32; IconData48 = 48; IconData256 = 256 } $hasAnyIconData = $iconSizes.Keys | Where-Object { -not [string]::IsNullOrEmpty($NewEntry[$_]) } if (-not $hasAnyIconData) { if ($PSBoundParameters.ContainsKey("IconFile")) { Write-Verbose "No icon data in entry '$($NewEntry.ShortcutName)'. Generating from IconFile '$IconFile'." foreach ($iconField in $iconSizes.GetEnumerator()) { $NewEntry[$iconField.Key] = ConvertFrom-IconFilePath -Path $IconFile -Size $iconField.Value } } else { Write-Warning "No icon data found for shortcut '$($NewEntry.ShortcutName)' and no -IconFile specified. Icon fields will be empty." } } elseif ($PSBoundParameters.ContainsKey("IconFile")) { Write-Verbose "Entry '$($NewEntry.ShortcutName)' already contains icon data. -IconFile parameter will be ignored for this entry." } $NewShortcutEntries += $NewEntry $associations = @($entry.FileTypeAssociations) + @($entry.FileAssociations) | Where-Object { $null -ne $_ } foreach ($association in $associations) { $association = ConvertTo-EntryHashtable -InputObject $association if ([string]::IsNullOrEmpty($association.Extension)) { Write-Error "Each file type association must contain an Extension (shortcut '$($NewEntry.ShortcutName)')." return } $NewFileTypeAssociations += [ordered]@{ Extension = "." + "$($association.Extension)".Trim().TrimStart(".") ShortcutEntryId = $NewEntry.EntryId TypeDescription = if ($association.ContainsKey("TypeDescription")) { "$($association.TypeDescription)" } else { "$($association.Description)" } } } } #endregion --- Build $NewShortcutEntries --- #region --- Build $NewCaptureRules (UserStateRoaming) --- $NewCaptureRules = @() foreach ($rule in $CaptureRules) { if (-not ($rule.ContainsKey("Kind") -and $rule.ContainsKey("Path"))) { Write-Error "Each capture rule must be a hashtable containing at least the keys: Kind, Path" return } $kind = @("Folder", "File", "Registry") | Where-Object { $_ -ieq $rule.Kind } if (-not $kind) { Write-Error "Invalid capture rule Kind '$($rule.Kind)' for path '$($rule.Path)'. Valid values: Folder, File, Registry" return } $NewCaptureRules += [ordered]@{ RuleId = if ([string]::IsNullOrEmpty($rule.RuleId)) { [guid]::NewGuid().ToString() } else { "$($rule.RuleId)" } Kind = $kind Path = "$($rule.Path)" Exclude = "$($rule.Exclude)" IncludeSubfolders = -not $rule.ContainsKey("IncludeSubfolders") -or "$($rule.IncludeSubfolders)" -notin @("False", "0") Enabled = -not $rule.ContainsKey("Enabled") -or "$($rule.Enabled)" -notin @("False", "0") Description = "$($rule.Description)" } } #endregion --- Build $NewCaptureRules (UserStateRoaming) --- $policyFilename = "$($Type)-$($SettingId).xml" $CreatedDate = (Get-Date).ToString("yyyy-MM-dd HH:mm:ss") $LastModifiedDate = (Get-Date).ToString("yyyy-MM-dd HH:mm:ss") if ([string]::IsNullOrEmpty($FriendlyName)) { Write-Error "FriendlyName is required. Please provide a value for the FriendlyName parameter or include it in the InputObject." return } try { Write-Verbose "Building UserSetting XML..." $XmlDocument = New-ShortcutUserSettingXml $XmlWriterSettings = New-Object System.Xml.XmlWriterSettings $XmlWriterSettings.Indent = $true $XmlWriterSettings.IndentChars = " " $XmlWriterSettings.Encoding = [System.Text.Encoding]::UTF8 $XmlWriterSettings.OmitXmlDeclaration = $true Write-Verbose "Saving UserSetting XML to $policyFilename" $ms = New-Object System.IO.MemoryStream $XmlWriter = [System.Xml.XmlWriter]::Create($ms, $XmlWriterSettings) $XmlDocument.Save($XmlWriter) $XmlWriter.Close() Set-AppVentiXConfigStoreItem -Item $Script:AppVentix.UserSettingsPath -ChildName $policyFilename -Content $ms.ToArray() -ConfigShare $ConfigShare Write-AppVentiXLogEntry -Feature UserSettings -Action $($MyInvocation.MyCommand.Name) -Details "New Shortcut User Setting '$FriendlyName' [$SettingId] added with $($NewShortcutEntries.Count) shortcut(s)." Write-Output ( [PSCustomObject]@{ Id = $SettingId FriendlyName = $FriendlyName FileName = $policyFilename } ) } catch { Write-Error "Failed to generate XML: $($_.Exception.Message)" } } else { Write-Warning 'AppVentiX is not licensed!' } } # SIG # Begin signature block # MII5zAYJKoZIhvcNAQcCoII5vTCCObkCAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCB5NbwB+TgJSLtE # sRuU2qlt9bUAflv6NnsATdzh4dWgiaCCIfAwggXMMIIDtKADAgECAhBUmNLR1FsZ # lUgTecgRwIeZMA0GCSqGSIb3DQEBDAUAMHcxCzAJBgNVBAYTAlVTMR4wHAYDVQQK # ExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xSDBGBgNVBAMTP01pY3Jvc29mdCBJZGVu # dGl0eSBWZXJpZmljYXRpb24gUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgMjAy # MDAeFw0yMDA0MTYxODM2MTZaFw00NTA0MTYxODQ0NDBaMHcxCzAJBgNVBAYTAlVT # MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xSDBGBgNVBAMTP01pY3Jv # c29mdCBJZGVudGl0eSBWZXJpZmljYXRpb24gUm9vdCBDZXJ0aWZpY2F0ZSBBdXRo # b3JpdHkgMjAyMDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALORKgeD # Bmf9np3gx8C3pOZCBH8Ppttf+9Va10Wg+3cL8IDzpm1aTXlT2KCGhFdFIMeiVPvH # or+Kx24186IVxC9O40qFlkkN/76Z2BT2vCcH7kKbK/ULkgbk/WkTZaiRcvKYhOuD # PQ7k13ESSCHLDe32R0m3m/nJxxe2hE//uKya13NnSYXjhr03QNAlhtTetcJtYmrV # qXi8LW9J+eVsFBT9FMfTZRY33stuvF4pjf1imxUs1gXmuYkyM6Nix9fWUmcIxC70 # ViueC4fM7Ke0pqrrBc0ZV6U6CwQnHJFnni1iLS8evtrAIMsEGcoz+4m+mOJyoHI1 # vnnhnINv5G0Xb5DzPQCGdTiO0OBJmrvb0/gwytVXiGhNctO/bX9x2P29Da6SZEi3 # W295JrXNm5UhhNHvDzI9e1eM80UHTHzgXhgONXaLbZ7LNnSrBfjgc10yVpRnlyUK # xjU9lJfnwUSLgP3B+PR0GeUw9gb7IVc+BhyLaxWGJ0l7gpPKWeh1R+g/OPTHU3mg # trTiXFHvvV84wRPmeAyVWi7FQFkozA8kwOy6CXcjmTimthzax7ogttc32H83rwjj # O3HbbnMbfZlysOSGM1l0tRYAe1BtxoYT2v3EOYI9JACaYNq6lMAFUSw0rFCZE4e7 # swWAsk0wAly4JoNdtGNz764jlU9gKL431VulAgMBAAGjVDBSMA4GA1UdDwEB/wQE # AwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTIftJqhSobyhmYBAcnz1AQ # T2ioojAQBgkrBgEEAYI3FQEEAwIBADANBgkqhkiG9w0BAQwFAAOCAgEAr2rd5hnn # LZRDGU7L6VCVZKUDkQKL4jaAOxWiUsIWGbZqWl10QzD0m/9gdAmxIR6QFm3FJI9c # Zohj9E/MffISTEAQiwGf2qnIrvKVG8+dBetJPnSgaFvlVixlHIJ+U9pW2UYXeZJF # xBA2CFIpF8svpvJ+1Gkkih6PsHMNzBxKq7Kq7aeRYwFkIqgyuH4yKLNncy2RtNwx # AQv3Rwqm8ddK7VZgxCwIo3tAsLx0J1KH1r6I3TeKiW5niB31yV2g/rarOoDXGpc8 # FzYiQR6sTdWD5jw4vU8w6VSp07YEwzJ2YbuwGMUrGLPAgNW3lbBeUU0i/OxYqujY # lLSlLu2S3ucYfCFX3VVj979tzR/SpncocMfiWzpbCNJbTsgAlrPhgzavhgplXHT2 # 6ux6anSg8Evu75SjrFDyh+3XOjCDyft9V77l4/hByuVkrrOj7FjshZrM77nq81YY # uVxzmq/FdxeDWds3GhhyVKVB0rYjdaNDmuV3fJZ5t0GNv+zcgKCf0Xd1WF81E+Al # GmcLfc4l+gcK5GEh2NQc5QfGNpn0ltDGFf5Ozdeui53bFv0ExpK91IjmqaOqu/dk # ODtfzAzQNb50GQOmxapMomE2gj4d8yu8l13bS3g7LfU772Aj6PXsCyM2la+YZr9T # 03u4aUoqlmZpxJTG9F9urJh4iIAGXKKy7aIwggalMIIEjaADAgECAhMzAAYWnItq # 2rzK2H0+AAAABhacMA0GCSqGSIb3DQEBDAUAMFoxCzAJBgNVBAYTAlVTMR4wHAYD # VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKzApBgNVBAMTIk1pY3Jvc29mdCBJ # RCBWZXJpZmllZCBDUyBFT0MgQ0EgMDMwHhcNMjYwOTEzMTYwNjIyWhcNMjYwOTE2 # MTYwNjIyWjBoMQswCQYDVQQGEwJOTDEWMBQGA1UECBMNTm9vcmQtSG9sbGFuZDEP # MA0GA1UEBxMGSGVpbG9vMRcwFQYDVQQKEw5BcHBWZW50aVggQi5WLjEXMBUGA1UE # AxMOQXBwVmVudGlYIEIuVi4wggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIB # gQCJ8RAejS/ySdKh4AYMzB7lDhSpY0sEWhyrSC2FFLV/CZ6tmKo3CDBkc+CZcagY # E+wQyP2mUo62Ftwg426HCOcrQFvqN/9KB9isXnIt2eVscoY0mFO5dTXQRlBZi+In # 4WZVwiraEwgsSOexXhV8cy8XHb6XFAhbkFF9yCDtm+ht9wLWKcLrR+GaX0PTwSyD # 6OmHqgz5ktBmrx1dOIg6U5lK6GKWnJdhdyKmCia6GZMGILib7fhG9X9mFo0avT78 # g+zHVOZs3xjXgxgJC3hEXY29bVyzY8J/bBFt7eEfxXoQ5SAKsRd9nQKGpSQsSxn+ # gqBN4jUAlnTE9xgPiIfLoGxiHu3StQK/Zj74x01zjTkf0xZzie0cbCZiljBJwVKB # x0Mxd1Mhl/gPGlWEoIwpXpmou1aIj+xwGm2HgPYstv3BXXpSWN/wkloyrtBluKl+ # i89Y7994lVPHZfAS71hEGnvSUN9PokEZ2/lOccGqY20pIwS93U/vhJ1gBW3YiGnh # oW8CAwEAAaOCAdQwggHQMAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgeAMDsG # A1UdJQQ0MDIGCisGAQQBgjdhAQAGCCsGAQUFBwMDBhorBgEEAYI3YaL8yC6uh9F6 # gZ2lyVCBwcKCJzAdBgNVHQ4EFgQU5eqUD0Rjq+0fZ7GOJBIsgqiVpiUwHwYDVR0j # BBgwFoAUa16lNMMFxWJKIVqOq3NgYtSsY4UwZwYDVR0fBGAwXjBcoFqgWIZWaHR0 # cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jcmwvTWljcm9zb2Z0JTIwSUQl # MjBWZXJpZmllZCUyMENTJTIwRU9DJTIwQ0ElMjAwMy5jcmwwdAYIKwYBBQUHAQEE # aDBmMGQGCCsGAQUFBzAChlhodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3Bz # L2NlcnRzL01pY3Jvc29mdCUyMElEJTIwVmVyaWZpZWQlMjBDUyUyMEVPQyUyMENB # JTIwMDMuY3J0MFQGA1UdIARNMEswSQYEVR0gADBBMD8GCCsGAQUFBwIBFjNodHRw # Oi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL0RvY3MvUmVwb3NpdG9yeS5odG0w # DQYJKoZIhvcNAQEMBQADggIBAK0MeKtzOlQmTEz6035FrN7FV6WFbJKwxNCaCOnx # U7GvTjFyTLdEaRD5f8Okn7ETAfytQZ48MaK8Io4jjfhT2lx7SYrdWFdhNjiv1pCm # v/5LApBsRGrL8oixP70qPhGAE3yyw/D/ZQCqYBFHZjNqz7jZhWD5jL81stBa+5OX # hnHQKlOTAdfLgIRsnigcm3OKiPPcGQRWxZvIRfFTO2t2dg7PQ/oBqwqNc94p8cQ0 # Z4BC/jNGZJYmtPhgC74MMJPhI2zzZgq+ILbr/HuZ7+P+yQzPnc/kdvD9AI5pmiO3 # KEsfDR13ixQ+INCjDG1dOsRODE3spjzhnu7fQUpNA9i6o7tnAbfhVmy1DxyxEjwo # VtbiasWKbaVABy6TEYqt7mIkhnElUcW3cUuApBrP6NsZ/P/NuPLUNjmBV/LL2rLU # nkE5Xj5LZJksm6eRlMhv5kPR6815/QZVAN1/x8/1pjBnuycHeQGKEmR+8bdzwwuN # K9aLGVoZFODQ9PVlofey5+dqpPDvtKQPRnxJQkAFmInB2LtbU+qeoblliZQolgfo # 069cEuBiDv74gFi+nX1INBt+CrH0XmQe9yQK5sVtoQbYkj7Ig2jJZn5ru2kYiCRc # uTN9yDeLpoOJWCgDY0ZqoE3ma8Cye8wpqhYSKd+snyQlrIaXDA4xtLQky0LWc3Ty # zAcXMIIGpTCCBI2gAwIBAgITMwAGFpyLatq8yth9PgAAAAYWnDANBgkqhkiG9w0B # AQwFADBaMQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0 # aW9uMSswKQYDVQQDEyJNaWNyb3NvZnQgSUQgVmVyaWZpZWQgQ1MgRU9DIENBIDAz # MB4XDTI2MDkxMzE2MDYyMloXDTI2MDkxNjE2MDYyMlowaDELMAkGA1UEBhMCTkwx # FjAUBgNVBAgTDU5vb3JkLUhvbGxhbmQxDzANBgNVBAcTBkhlaWxvbzEXMBUGA1UE # ChMOQXBwVmVudGlYIEIuVi4xFzAVBgNVBAMTDkFwcFZlbnRpWCBCLlYuMIIBojAN # BgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAifEQHo0v8knSoeAGDMwe5Q4UqWNL # BFocq0gthRS1fwmerZiqNwgwZHPgmXGoGBPsEMj9plKOthbcIONuhwjnK0Bb6jf/ # SgfYrF5yLdnlbHKGNJhTuXU10EZQWYviJ+FmVcIq2hMILEjnsV4VfHMvFx2+lxQI # W5BRfcgg7ZvobfcC1inC60fhml9D08Esg+jph6oM+ZLQZq8dXTiIOlOZSuhilpyX # YXcipgomuhmTBiC4m+34RvV/ZhaNGr0+/IPsx1TmbN8Y14MYCQt4RF2NvW1cs2PC # f2wRbe3hH8V6EOUgCrEXfZ0ChqUkLEsZ/oKgTeI1AJZ0xPcYD4iHy6BsYh7t0rUC # v2Y++MdNc405H9MWc4ntHGwmYpYwScFSgcdDMXdTIZf4DxpVhKCMKV6ZqLtWiI/s # cBpth4D2LLb9wV16Uljf8JJaMq7QZbipfovPWO/feJVTx2XwEu9YRBp70lDfT6JB # Gdv5TnHBqmNtKSMEvd1P74SdYAVt2Ihp4aFvAgMBAAGjggHUMIIB0DAMBgNVHRMB # Af8EAjAAMA4GA1UdDwEB/wQEAwIHgDA7BgNVHSUENDAyBgorBgEEAYI3YQEABggr # BgEFBQcDAwYaKwYBBAGCN2Gi/MgurofReoGdpclQgcHCgicwHQYDVR0OBBYEFOXq # lA9EY6vtH2exjiQSLIKolaYlMB8GA1UdIwQYMBaAFGtepTTDBcViSiFajqtzYGLU # rGOFMGcGA1UdHwRgMF4wXKBaoFiGVmh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9w # a2lvcHMvY3JsL01pY3Jvc29mdCUyMElEJTIwVmVyaWZpZWQlMjBDUyUyMEVPQyUy # MENBJTIwMDMuY3JsMHQGCCsGAQUFBwEBBGgwZjBkBggrBgEFBQcwAoZYaHR0cDov # L3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jZXJ0cy9NaWNyb3NvZnQlMjBJRCUy # MFZlcmlmaWVkJTIwQ1MlMjBFT0MlMjBDQSUyMDAzLmNydDBUBgNVHSAETTBLMEkG # BFUdIAAwQTA/BggrBgEFBQcCARYzaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3Br # aW9wcy9Eb2NzL1JlcG9zaXRvcnkuaHRtMA0GCSqGSIb3DQEBDAUAA4ICAQCtDHir # czpUJkxM+tN+RazexVelhWySsMTQmgjp8VOxr04xcky3RGkQ+X/DpJ+xEwH8rUGe # PDGivCKOI434U9pce0mK3VhXYTY4r9aQpr/+SwKQbERqy/KIsT+9Kj4RgBN8ssPw # /2UAqmARR2Yzas+42YVg+Yy/NbLQWvuTl4Zx0CpTkwHXy4CEbJ4oHJtziojz3BkE # VsWbyEXxUztrdnYOz0P6AasKjXPeKfHENGeAQv4zRmSWJrT4YAu+DDCT4SNs82YK # viC26/x7me/j/skMz53P5Hbw/QCOaZojtyhLHw0dd4sUPiDQowxtXTrETgxN7KY8 # 4Z7u30FKTQPYuqO7ZwG34VZstQ8csRI8KFbW4mrFim2lQAcukxGKre5iJIZxJVHF # t3FLgKQaz+jbGfz/zbjy1DY5gVfyy9qy1J5BOV4+S2SZLJunkZTIb+ZD0evNef0G # VQDdf8fP9aYwZ7snB3kBihJkfvG3c8MLjSvWixlaGRTg0PT1ZaH3sufnaqTw77Sk # D0Z8SUJABZiJwdi7W1PqnqG5ZYmUKJYH6NOvXBLgYg7++IBYvp19SDQbfgqx9F5k # HvckCubFbaEG2JI+yINoyWZ+a7tpGIgkXLkzfcg3i6aDiVgoA2NGaqBN5mvAsnvM # KaoWEinfrJ8kJayGlwwOMbS0JMtC1nN08swHFzCCBygwggUQoAMCAQICEzMAAAAV # BT5uGY6TKdkAAAAAABUwDQYJKoZIhvcNAQEMBQAwYzELMAkGA1UEBhMCVVMxHjAc # BgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjE0MDIGA1UEAxMrTWljcm9zb2Z0 # IElEIFZlcmlmaWVkIENvZGUgU2lnbmluZyBQQ0EgMjAyMTAeFw0yNjAzMjYxODEx # MjhaFw0zMTAzMjYxODExMjhaMFoxCzAJBgNVBAYTAlVTMR4wHAYDVQQKExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24xKzApBgNVBAMTIk1pY3Jvc29mdCBJRCBWZXJpZmll # ZCBDUyBFT0MgQ0EgMDMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDg # 9Ms9AqovDnMePvMOe+KybhCd8+lokzYORlS3kBVXseecbyGwBcsenlm5bLtMGPji # IFLzBQF+ghlVV/U29q5GcdeEEBCHTTGhL2koIrLc4UrliMRcbv9mOMtR/l7/xAmv # 0Fx4BJHn1dHt37fvrBqXmKjKfGf5DpyO/+hnV7TEreMtS19iO+bjZ/9Hnpg3PCk0 # e7YSbRTFkx97FZwRWpC4s3NepRfRXQh/WMAj7JmsYeVZohi4TF5yW2JMrJZqwHcy # zJZYtD2Hlno5ZEJkdiZcEaxHOobmwO06Z1J9c23ps9PGIhGaq1sKLEAz9Doc5rLk # YWGteDrscKhAp2kIc/oYlH9Ij6BkOqqgWINEkEtC8ZNG1Mak+h3o65aj0iQKmdxW # 7IZaHO5cuyoMi+KtYfXeIIg3sVIbS2EL8kUtsDGdEqNqAq/isqTi1jXqLe6iKp1n # i1SPdvPW9G03CTsYF68b/yuIQRwbdoBCXemMNJCS0dorCRY4b2WAAy4ng7SANcEg # rBgZf535+QfLU5hGzrKjIpbMabauWb5FKWUKkMsPcXFkXRWO4noKPm4KWlFypqOp # bJ/KONVReIlxHQRegAOBzIhRB7gr9IDQ1sc2MgOgQ+xVGW4oq4HD0mfAiwiyLskZ # rkaQ7JoanYjBNcR9RS26YxAVbcBtLitFTzCIEg5ZdQIDAQABo4IB3DCCAdgwDgYD # VR0PAQH/BAQDAgGGMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBRrXqU0wwXF # YkohWo6rc2Bi1KxjhTBUBgNVHSAETTBLMEkGBFUdIAAwQTA/BggrBgEFBQcCARYz # aHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9Eb2NzL1JlcG9zaXRvcnku # aHRtMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMBIGA1UdEwEB/wQIMAYBAf8C # AQAwHwYDVR0jBBgwFoAU2UEpsA8PY2zvadf1zSmepEhqMOYwcAYDVR0fBGkwZzBl # oGOgYYZfaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jcmwvTWljcm9z # b2Z0JTIwSUQlMjBWZXJpZmllZCUyMENvZGUlMjBTaWduaW5nJTIwUENBJTIwMjAy # MS5jcmwwfQYIKwYBBQUHAQEEcTBvMG0GCCsGAQUFBzAChmFodHRwOi8vd3d3Lm1p # Y3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY3Jvc29mdCUyMElEJTIwVmVyaWZp # ZWQlMjBDb2RlJTIwU2lnbmluZyUyMFBDQSUyMDIwMjEuY3J0MA0GCSqGSIb3DQEB # DAUAA4ICAQBdbiI8zwXLX8glJEh/8Q22UMCUhWBO46Z9FPhwOR3mdlqRVLkYOon/ # MczUwrjDhx3X99SPH5PSflkGoTvnO9ZWHM5YFVYpO7NYuB+mfVSGAGZwiGOASWk0 # i2B7vn9nElJJmoiXxugfH5YdBsrUgTt0AFNXkzmqTgk+S1Hxb1u/0HCqEHVZPk2A # /6eJXYbtpRM5Fcz00jisUl9BRZgSebODV85bBzOveqyC3f0PnHCxRJNhMb8xP/sB # /VI7pf2rheSV7zqUSv8vn/fIMblXeaVIlpqoq8SP9BJMjE/CoVXJxnkZQRM1Fa7k # N9yztvReOhxSgPgpZx/Xl/jkwyEFVJTBfBp3sTgfIc/pmqv2ehtakL2AEj78EmOP # QohxJT3wyX+P78GA25tLpAvzj3RMMHd8z18ZuuVi+60MAzGpOASH1L8Nlr3fZRZn # QO+pyye2DCvYmHaIfdUgYJqn7noxxGVv89+RaETh1tgCDvwNpFCSG7vl5A4ako+2 # fx409r9TWjXC7Oif1IQ5ZJzB4Rf8GvBiHYjvMmHpledp1FGRLdSRFVpC3/OKpZY6 # avIqZp7+8pP/WQP903DdgrvAT6W4xPOBxXPa4tGksN3SuqJaiFYHSNyeBufn8ise # ujW4IbBSbHD4BPqbF3qZ+7nG9d/d/G2/Lx4kH9cCmBfmsZdSkHmukDCCB54wggWG # oAMCAQICEzMAAAAHh6M0o3uljhwAAAAAAAcwDQYJKoZIhvcNAQEMBQAwdzELMAkG # A1UEBhMCVVMxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjFIMEYGA1UE # AxM/TWljcm9zb2Z0IElkZW50aXR5IFZlcmlmaWNhdGlvbiBSb290IENlcnRpZmlj # YXRlIEF1dGhvcml0eSAyMDIwMB4XDTIxMDQwMTIwMDUyMFoXDTM2MDQwMTIwMTUy # MFowYzELMAkGA1UEBhMCVVMxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv # bjE0MDIGA1UEAxMrTWljcm9zb2Z0IElEIFZlcmlmaWVkIENvZGUgU2lnbmluZyBQ # Q0EgMjAyMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALLwwK8ZiCji # 3VR6TElsaQhVCbRS/3pK+MHrJSj3Zxd3KU3rlfL3qrZilYKJNqztA9OQacr1AwoN # cHbKBLbsQAhBnIB34zxf52bDpIO3NJlfIaTE/xrweLoQ71lzCHkD7A4As1Bs076I # u+mA6cQzsYYH/Cbl1icwQ6C65rU4V9NQhNUwgrx9rGQ//h890Q8JdjLLw0nV+ayQ # 2Fbkd242o9kH82RZsH3HEyqjAB5a8+Ae2nPIPc8sZU6ZE7iRrRZywRmrKDp5+Tcm # JX9MRff241UaOBs4NmHOyke8oU1TYrkxh+YeHgfWo5tTgkoSMoayqoDpHOLJs+qG # 8Tvh8SnifW2Jj3+ii11TS8/FGngEaNAWrbyfNrC69oKpRQXY9bGH6jn9NEJv9weF # xhTwyvx9OJLXmRGbAUXN1U9nf4lXezky6Uh/cgjkVd6CGUAf0K+Jw+GE/5VpIVbc # Nr9rNE50Sbmy/4RTCEGvOq3GhjITbCa4crCzTTHgYYjHs1NbOc6brH+eKpWLtr+b # Gecy9CrwQyx7S/BfYJ+ozst7+yZtG2wR461uckFu0t+gCwLdN0A6cFtSRtR8bvxV # FyWwTtgMMFRuBa3vmUOTnfKLsLefRaQcVTgRnzeLzdpt32cdYKp+dhr2ogc+qM6K # 4CBI5/j4VFyC4QFeUP2YAidLtvpXRRo3AgMBAAGjggI1MIICMTAOBgNVHQ8BAf8E # BAMCAYYwEAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0OBBYEFNlBKbAPD2Ns72nX9c0p # nqRIajDmMFQGA1UdIARNMEswSQYEVR0gADBBMD8GCCsGAQUFBwIBFjNodHRwOi8v # d3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL0RvY3MvUmVwb3NpdG9yeS5odG0wGQYJ # KwYBBAGCNxQCBAweCgBTAHUAYgBDAEEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSME # GDAWgBTIftJqhSobyhmYBAcnz1AQT2ioojCBhAYDVR0fBH0wezB5oHegdYZzaHR0 # cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jcmwvTWljcm9zb2Z0JTIwSWRl # bnRpdHklMjBWZXJpZmljYXRpb24lMjBSb290JTIwQ2VydGlmaWNhdGUlMjBBdXRo # b3JpdHklMjAyMDIwLmNybDCBwwYIKwYBBQUHAQEEgbYwgbMwgYEGCCsGAQUFBzAC # hnVodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY3Jvc29m # dCUyMElkZW50aXR5JTIwVmVyaWZpY2F0aW9uJTIwUm9vdCUyMENlcnRpZmljYXRl # JTIwQXV0aG9yaXR5JTIwMjAyMC5jcnQwLQYIKwYBBQUHMAGGIWh0dHA6Ly9vbmVv # Y3NwLm1pY3Jvc29mdC5jb20vb2NzcDANBgkqhkiG9w0BAQwFAAOCAgEAfyUqnv7U # q+rdZgrbVyNMul5skONbhls5fccPlmIbzi+OwVdPQ4H55v7VOInnmezQEeW4LqK0 # wja+fBznANbXLB0KrdMCbHQpbLvG6UA/Xv2pfpVIE1CRFfNF4XKO8XYEa3oW8oVH # +KZHgIQRIwAbyFKQ9iyj4aOWeAzwk+f9E5StNp5T8FG7/VEURIVWArbAzPt9ThVN # 3w1fAZkF7+YU9kbq1bCR2YD+MtunSQ1Rft6XG7b4e0ejRA7mB2IoX5hNh3UEauY0 # byxNRG+fT2MCEhQl9g2i2fs6VOG19CNep7SquKaBjhWmirYyANb0RJSLWjinMLXN # OAga10n8i9jqeprzSMU5ODmrMCJE12xS/NWShg/tuLjAsKP6SzYZ+1Ry358ZTFcx # 0FS/mx2vSoU8s8HRvy+rnXqyUJ9HBqS0DErVLjQwK8VtsBdekBmdTbQVoCgPCqr+ # PDPB3xajYnzevs7eidBsM71PINK2BoE2UfMwxCCX3mccFgx6UsQeRSdVVVNSyALQ # e6PT12418xon2iDGE81OGCreLzDcMAZnrUAx4XQLUz6ZTl65yPUiOh3k7Yww94lD # f+8oG2oZmDh5O1Qe38E+M3vhKwmzIeoB1dVLlz4i3IpaDcR+iuGjH2TdaC1ZOmBX # iCRKJLj4DT2uhJ04ji+tHD6n58vhavFIrmcxghcyMIIXLgIBATBxMFoxCzAJBgNV # BAYTAlVTMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKzApBgNVBAMT # Ik1pY3Jvc29mdCBJRCBWZXJpZmllZCBDUyBFT0MgQ0EgMDMCEzMABhaci2ravMrY # fT4AAAAGFpwwDQYJYIZIAWUDBAIBBQCgXjAQBgorBgEEAYI3AgEMMQIwADAZBgkq # hkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAvBgkqhkiG9w0BCQQxIgQgbaYl/MNVauz0 # 2j2PbBcNL55SULgO5FEPzBEbd9tvhmUwDQYJKoZIhvcNAQEBBQAEggGACmS3ZiM/ # 50bSoRJn5kJQ2q+FGVn5WiNPLtl67nDT0I16sdWzwkphdmmtwy6j6zrLHSe1RuZI # l1ousN22kVHoRVVbhVn2TDHeZ6OB7Lsxi9Aj0YnO6TjTS+AyccKAdcs/VOceEFBu # SLpGy63/qIM10BflQGfXKzBs2uyPoyD2SqpheN9NmqBH+Q7rGJZWuv7+K2ugHQDf # z5bSNHifSPKiBMG3R6jDc66g7u7QCX+sLOuORZygP/5t2Fi21h8sfB+DF/nuDlMC # LIP3zSxdH5oAT7ixQVX8gz7qGQLq9fXvyHZJOoHHY9dvMIDRoNxwK6Vf8cycBHfQ # LwZztMW23CE6tzAvYXPNRZa97q6o/Z62t4SZl+V4qAeaBKWBSxrAonEYpOZ6N9Py # 4yoL7Z+0SvEAZsgpMVtvF+zjcUWn6s6oa1GBPcVsa0cJQhAFM4B6PJ3w49+1s9cg # SWGFXgGmu4KtwvgziXt6aX8OQCIlbyZIbvoJcZrshY/FD0j5Ba2ryygLoYIUsjCC # FK4GCisGAQQBgjcDAwExghSeMIIUmgYJKoZIhvcNAQcCoIIUizCCFIcCAQMxDzAN # BglghkgBZQMEAgEFADCCAWoGCyqGSIb3DQEJEAEEoIIBWQSCAVUwggFRAgEBBgor # BgEEAYRZCgMBMDEwDQYJYIZIAWUDBAIBBQAEIA+2h4/RFJGKr1+A5yz5GjX0PYpg # gbJT6/QuK3IdJ0uWAgZqmsvL7qAYEzIwMjYwOTE1MTIyMzE5LjcxNFowBIACAfSg # gemkgeYwgeMxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYD # VQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xLTAr # BgNVBAsTJE1pY3Jvc29mdCBJcmVsYW5kIE9wZXJhdGlvbnMgTGltaXRlZDEnMCUG # A1UECxMeblNoaWVsZCBUU1MgRVNOOjdBMUEtMDVFMC1EOTQ3MTUwMwYDVQQDEyxN # aWNyb3NvZnQgUHVibGljIFJTQSBUaW1lIFN0YW1waW5nIEF1dGhvcml0eaCCDykw # ggeCMIIFaqADAgECAhMzAAAABeXPD/9mLsmHAAAAAAAFMA0GCSqGSIb3DQEBDAUA # MHcxCzAJBgNVBAYTAlVTMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24x # SDBGBgNVBAMTP01pY3Jvc29mdCBJZGVudGl0eSBWZXJpZmljYXRpb24gUm9vdCBD # ZXJ0aWZpY2F0ZSBBdXRob3JpdHkgMjAyMDAeFw0yMDExMTkyMDMyMzFaFw0zNTEx # MTkyMDQyMzFaMGExCzAJBgNVBAYTAlVTMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29y # cG9yYXRpb24xMjAwBgNVBAMTKU1pY3Jvc29mdCBQdWJsaWMgUlNBIFRpbWVzdGFt # cGluZyBDQSAyMDIwMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAnnzn # UmP94MWfBX1jtQYioxwe1+eXM9ETBb1lRkd3kcFdcG9/sqtDlwxKoVIcaqDb+omF # io5DHC4RBcbyQHjXCwMk/l3TOYtgoBjxnG/eViS4sOx8y4gSq8Zg49REAf5huXhI # kQRKe3Qxs8Sgp02KHAznEa/Ssah8nWo5hJM1xznkRsFPu6rfDHeZeG1Wa1wISvlk # pOQooTULFm809Z0ZYlQ8Lp7i5F9YciFlyAKwn6yjN/kR4fkquUWfGmMopNq/B8U/ # pdoZkZZQbxNlqJOiBGgCWpx69uKqKhTPVi3gVErnc/qi+dR8A2MiAz0kN0nh7SqI # NGbmw5OIRC0EsZ31WF3Uxp3GgZwetEKxLms73KG/Z+MkeuaVDQQheangOEMGJ4pQ # ZH55ngI0Tdy1bi69INBV5Kn2HVJo9XxRYR/JPGAaM6xGl57Ei95HUw9NV/uC3yFj # rhc087qLJQawSC3xzY/EXzsT4I7sDbxOmM2rl4uKK6eEpurRduOQ2hTkmG1hSuWY # BunFGNv21Kt4N20AKmbeuSnGnsBCd2cjRKG79+TX+sTehawOoxfeOO/jR7wo3liw # kGdzPJYHgnJ54UxbckF914AqHOiEV7xTnD1a69w/UTxwjEugpIPMIIE67SFZ2PMo # 27xjlLAHWW3l1CEAFjLNHd3EQ79PUr8FUXetXr0CAwEAAaOCAhswggIXMA4GA1Ud # DwEB/wQEAwIBhjAQBgkrBgEEAYI3FQEEAwIBADAdBgNVHQ4EFgQUa2koOjUvSGNA # z3vYr0npPtk92yEwVAYDVR0gBE0wSzBJBgRVHSAAMEEwPwYIKwYBBQUHAgEWM2h0 # dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvRG9jcy9SZXBvc2l0b3J5Lmh0 # bTATBgNVHSUEDDAKBggrBgEFBQcDCDAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMA # QTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFMh+0mqFKhvKGZgEByfPUBBP # aKiiMIGEBgNVHR8EfTB7MHmgd6B1hnNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20v # cGtpb3BzL2NybC9NaWNyb3NvZnQlMjBJZGVudGl0eSUyMFZlcmlmaWNhdGlvbiUy # MFJvb3QlMjBDZXJ0aWZpY2F0ZSUyMEF1dGhvcml0eSUyMDIwMjAuY3JsMIGUBggr # BgEFBQcBAQSBhzCBhDCBgQYIKwYBBQUHMAKGdWh0dHA6Ly93d3cubWljcm9zb2Z0 # LmNvbS9wa2lvcHMvY2VydHMvTWljcm9zb2Z0JTIwSWRlbnRpdHklMjBWZXJpZmlj # YXRpb24lMjBSb290JTIwQ2VydGlmaWNhdGUlMjBBdXRob3JpdHklMjAyMDIwLmNy # dDANBgkqhkiG9w0BAQwFAAOCAgEAX4h2x35ttVoVdedMeGj6TuHYRJklFaW4sTQ5 # r+k77iB79cSLNe+GzRjv4pVjJviceW6AF6ycWoEYR0LYhaa0ozJLU5Yi+LCmcrdo # vkl53DNt4EXs87KDogYb9eGEndSpZ5ZM74LNvVzY0/nPISHz0Xva71QjD4h+8z2X # MOZzY7YQ0Psw+etyNZ1CesufU211rLslLKsO8F2aBs2cIo1k+aHOhrw9xw6JCWON # NboZ497mwYW5EfN0W3zL5s3ad4Xtm7yFM7Ujrhc0aqy3xL7D5FR2J7x9cLWMq7eb # 0oYioXhqV2tgFqbKHeDick+P8tHYIFovIP7YG4ZkJWag1H91KlELGWi3SLv10o4K # Gag42pswjybTi4toQcC/irAodDW8HNtX+cbz0sMptFJK+KObAnDFHEsukxD+7jFf # EV9Hh/+CSxKRsmnuiovCWIOb+H7DRon9TlxydiFhvu88o0w35JkNbJxTk4MhF/Kg # aXn0GxdH8elEa2Imq45gaa8D+mTm8LWVydt4ytxYP/bqjN49D9NZ81coE6aQWm88 # TwIf4R4YZbOpMKN0CyejaPNN41LGXHeCUMYmBx3PkP8ADHD1J2Cr/6tjuOOCztfp # +o9Nc+ZoIAkpUcA/X2gSMkgHAPUvIdtoSAHEUKiBhI6JQivRepyvWcl+JYbYbBh7 # pmgAXVswggefMIIFh6ADAgECAhMzAAAAW0q1jUEybdx0AAAAAABbMA0GCSqGSIb3 # DQEBDAUAMGExCzAJBgNVBAYTAlVTMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9y # YXRpb24xMjAwBgNVBAMTKU1pY3Jvc29mdCBQdWJsaWMgUlNBIFRpbWVzdGFtcGlu # ZyBDQSAyMDIwMB4XDTI2MDEwODE4NTkwNVoXDTI3MDEwNzE4NTkwNVowgeMxCzAJ # BgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25k # MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xLTArBgNVBAsTJE1pY3Jv # c29mdCBJcmVsYW5kIE9wZXJhdGlvbnMgTGltaXRlZDEnMCUGA1UECxMeblNoaWVs # ZCBUU1MgRVNOOjdBMUEtMDVFMC1EOTQ3MTUwMwYDVQQDEyxNaWNyb3NvZnQgUHVi # bGljIFJTQSBUaW1lIFN0YW1waW5nIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEB # BQADggIPADCCAgoCggIBAJBUzBbbnlDXee0B0KD5G4/475thFyfctCyuESTWQXvl # Li4Wx/td2qUdeq4ideeg6VWhiOHfu3wJV4TUGSRtqh9Ccr1BmiBKv9iuFpgHyIBu # 5Qx38ZsxwlFeXVS+ZqJJKnXRbDNQdcYSoC/6c0hQJ/PH50DBRDQkPXVwyFizLrRH # 9AlrJeUg7BKeT23zftS8/KOJLvEEbHOF6pSOY3ZVprZUWbWjWwRTmoHaQ/E8vrWt # LNyEJ+b089VW1Ikra3t4GTB5Wby3CL1K2zYnAxBIvafsKMFyj9OuXHcTPKMDoFSM # eamG9MKOMb6uoG1PjdnDgsLP6EOMRSzrLL7jED1mbB9RSd9fhty+HQr6vZgsBn6o # Uy+YTpNVLskwdtUM82WYAkPztlOt3AiL0qyV7/U3j/uq3vHMjPM0w0340M57Nei0 # g4BCcMt0dbqoc91VgCb3/36sHQANontn1HOF2oLk8190QRS43isHVra8H8sf5+Gl # qIYsYiCKX04HZiOzZW826nVI6d++8lyTeWmpj90Ua9uPbJhVjwE3oh6tO510ySqm # SMSLEN07p3Ibe3E6BAb2w93rWzb26+dpSthbKF4kApofqBsWPX4MEtHKSOftPmVT # CQ47tghrVuHia9jY+Hsj01m4KW4WtkmVm3L6hMZECMa4sjMxAXz+bX/AJhWTe6TZ # AgMBAAGjggHLMIIBxzAdBgNVHQ4EFgQU7/LqUlWWYhXJdXwgYKx4b8Gv0rYwHwYD # VR0jBBgwFoAUa2koOjUvSGNAz3vYr0npPtk92yEwbAYDVR0fBGUwYzBhoF+gXYZb # aHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jcmwvTWljcm9zb2Z0JTIw # UHVibGljJTIwUlNBJTIwVGltZXN0YW1waW5nJTIwQ0ElMjAyMDIwLmNybDB5Bggr # BgEFBQcBAQRtMGswaQYIKwYBBQUHMAKGXWh0dHA6Ly93d3cubWljcm9zb2Z0LmNv # bS9wa2lvcHMvY2VydHMvTWljcm9zb2Z0JTIwUHVibGljJTIwUlNBJTIwVGltZXN0 # YW1waW5nJTIwQ0ElMjAyMDIwLmNydDAMBgNVHRMBAf8EAjAAMBYGA1UdJQEB/wQM # MAoGCCsGAQUFBwMIMA4GA1UdDwEB/wQEAwIHgDBmBgNVHSAEXzBdMFEGDCsGAQQB # gjdMg30BATBBMD8GCCsGAQUFBwIBFjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20v # cGtpb3BzL0RvY3MvUmVwb3NpdG9yeS5odG0wCAYGZ4EMAQQCMA0GCSqGSIb3DQEB # DAUAA4ICAQAAH+zd+XKh4OxXYMWFmtgilXAQGctOjCUB1w/uBiC/OXcH3Ia4/Xbd # UhKzFbaiTbIE6vYZKd1p4u7nKOLkawymAMVyuO7LSl6rLKttZIyLhWjTK0zXOz0u # 4xLq9+bRtBEKJvA6sD5nJwH1IO6z1YizyuIRoalMCnbrUixfWxQn4TAmN7t9uk+X # 2FUThEa3ewzRwhtG+xwaAbLMkxRmR24JnfXd1VxKo90+m7Wzuov96Uugx5wZdewi # IIm1ZWTj4lCJHup679LcOa7tAxJMipVaSltQH9fm9TOKczlfxtWuBcLU4duZfqwg # sILsH7PMkcX1zwQzQD0yAtPhnYz9KNG125bX+iilOe1S8RHqv2bbBpMpao4kcUvQ # I6dMgKRvFmm1eLbhSNOQplDMTGD1tNVdNGkI96jUu+troUjWMMi46TQfBAHxtDTp # RhIu/87vAVQ8Z6RHhFxesz4Ed5JThaIQRAy6GcO/Jk+QzDzoZ0arRIkIsGJ7rZgO # VAjx9ctfw8lH9RfjcwB3wdGBYNMNVJqQpUai2Taddf5pXzTZEHIqLEF53SrBjIeI # noQrP7U5VlXiMQsxewLdINrAE2l2TR3KBikb+RQRygbTp8jj2yiC0NCUwG+K+ndg # lN5RMbXjFW6aKa59Xq+b8XzK/DK+AJtgOpHgJv8Qrk62A+twOVLOpjGCA9QwggPQ # AgEBMHgwYTELMAkGA1UEBhMCVVMxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3Jh # dGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFB1YmxpYyBSU0EgVGltZXN0YW1waW5n # IENBIDIwMjACEzMAAABbSrWNQTJt3HQAAAAAAFswDQYJYIZIAWUDBAIBBQCgggEt # MBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAvBgkqhkiG9w0BCQQxIgQgI3Qu # P8B1G8Medh2qwuBYOTHCq9othpZqitOzf8K5D0Iwgd0GCyqGSIb3DQEJEAIvMYHN # MIHKMIHHMIGgBCAvMQNVXZ0b0xxlGw8X/3IEybObuT6a5W1d61CW+cGD7zB8MGWk # YzBhMQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9u # MTIwMAYDVQQDEylNaWNyb3NvZnQgUHVibGljIFJTQSBUaW1lc3RhbXBpbmcgQ0Eg # MjAyMAITMwAAAFtKtY1BMm3cdAAAAAAAWzAiBCBuC47zDNOO1uwNTyURGr4FG5DP # w4Qq6Oi2SndovZid5zANBgkqhkiG9w0BAQsFAASCAgAAhxrhwUyYj67rR5Wdx1nt # q3VPgBQJDK+spRAyV/YPHKlHxHTuHruUXpCGsffI7UoyfgbLzIovPAjHGiU+FlcW # iMu7vqBZpXh7m4Ar1Q7hwpJ409rj2HeBjUWIqwuWF+AwuovuDbwoJ+c8Jzp0L8kc # kZC4nrazPSCH6zCRK4DPFSFML0YrvsHIMxejGdBJ5rnhdV10v6niGtw6z2WvTE1l # iWVJ0pWNN9mPS4n8IqEJDMIkj1wk8A4eizgw1N3Qdc87go5YcpyErZ0stnL6+6XF # D0ItoVSNl7xqFhVRagBnucZumQEoMXtDiyYc8KDaLZ8PEDFAMgNo+VK4dHz5j9Mr # P+FauLRc1XDeaI5SkMc8m/YKUkIUgf7fQSfmpSkoyXQPMbw/ZLFdZPMpyAg4Ktmd # y1xgEf1mu53aXuZwInEyHvY2mxP72509hrISWHL0Lfjd9R96nrgqlHzZnfcTyVUx # q5V+WDYW0FOmFXzpZuA28kYq5qjX3AMxzr/UwEpmtVq1sGJrBnjzl1JKbRoufx3W # aVNRS30xYJUrI7ABrFvE0gQ3NzCsM0rqZvcLgbopMU157kdmE/MwV6yVRBAizNmx # +Ip1oaUrxHH5DXZhAWjFlw+wycXn1mBGpCKHk3XZ6XNfSN9X8zYbNHc8SPAElRLe # hn68giIPvdRYVtzAbIXv/w== # SIG # End signature block |