functions/Set-WEFSubscription.ps1

function Set-WEFSubscription {
    <#
        .Synopsis
            Set-WEFSubscription
 
        .DESCRIPTION
            Set properties on a Windows Eventlog Forwarding subscription
 
        .PARAMETER InputObject
            Pipeline catching object for Get-WEFSubscription
 
        .PARAMETER ComputerName
            The computer(s) to connect to.
            Supports PSSession objects, will reuse sessions.
 
            Available aliases: "host", "hostname", "Computer", "DNSHostName"
 
        .PARAMETER Session
            PSSession(s) to connect to.
 
        .PARAMETER Name
            Name of the subscription to modify.
            Only needed when InputObject is not used.
            Must be specified when piping in a computername or PSSession.
 
            Available aliases: "DisplayName", "SubscriptionID", "Idendity"
 
        .PARAMETER Credential
            The credentials to use on remote calls.
 
        .PARAMETER NewName
            The new name for the subscription.
 
        .PARAMETER Description
            The discription for a subscription.
 
        .PARAMETER Enabled
            Set the status of a subscription.
 
            Available aliases: "Enable" and "Status"
 
        .PARAMETER ReadExistingEvents
            Specifies which kind of events are transfered.
            If set TRUE, all events will be transfered. If set to false,
            only newly created events will be transfered.
 
        .PARAMETER ContentFormat
            Can be set to "Events" or "RenderedText".
            This setting specifies, how events are transfered and rendered
            to server.
            If setting is "RenderedText", the events will be rendered in the
            localization from the client. If setting is "Events", the
            interpreting of the events will be done on the server.
 
        .PARAMETER Locale
            Localization schema for events.
            Setting only apply when ContentFormat is "RenderedText".
            <String>
 
        .PARAMETER LogFile
            Name of the eventlog where to store the forwarded events.
 
        .PARAMETER Query
            Query string(s) which events will be included in the subscription.
            Only the "Select"-part of the query has to be specified.
 
            Example:
            '<Select Path="System">*[System[(Level=1 or Level=2 or Level=3)]]</Select>'
 
        .PARAMETER MaxLatency
            Maximum latency interval in milliseconds while forwarding events.
 
        .PARAMETER HeartBeatInterval
            Heartbeat interval in milliseconds.
 
        .PARAMETER MaxItems
            Amount of maxium events per interval to transfer.
 
        .PARAMETER TransportName
            Type of connection for transfering events. Possible values are "http" or "https".
            (data is always encrypted, event when transfer mode is "http", which is the default)
 
        .PARAMETER SourceDomainComputer
            Name(s) and/or SID(s) of computers or groups, to apply on the subscription.
 
            Example:
            "Domain computers", "Domain controllers", "MyComputerGroup"
            "S-1-5-21-1234567890-12345678-123456789-515", "S-1-5-21-1234567890-12345678-123456789-516"
 
        .PARAMETER SourceNonDomainDNSList
            Name(s) of DNS match list.
 
            Example:
            "*.mydomain.com"
 
        .PARAMETER SourceNonDomainIssuerCAThumbprint
            Certificate thumbprint(s) of trusted certificate authority..
 
            Example:
            "100F1CAED645BB78B3EA2B94C0697C7407330010"
 
        .PARAMETER Expires
            Specifies a datetime when the subscription expires and computers will be no more active.
 
        .PARAMETER PassThru
            Output the changed subscription on the end of the operation
 
        .PARAMETER WhatIf
 
            If this switch is enabled, no actions are performed but informational messages will be displayed that explain what would happen if the command were to run.
 
        .PARAMETER Confirm
 
            If this switch is enabled, you will be prompted for confirmation before executing any operations that change state.
 
        .PARAMETER PassThru
 
            If this switch is enabled, the function will return the working object to the pipeline for further processing
 
        .EXAMPLE
            PS C:\> Set-WEFSubscription -Name "Subscription1" -NewName "Subscription1New"
 
            Rename the subscription "Subscription1" to "Subscription1New"
 
        .EXAMPLE
            PS C:\> Get-WEFSubscription -Name "Subscription1" | Set-WEFSubscription -Enabled $true
 
            Enable "Subscription1" by using the pipeline.
            Aliases "Enable" and "Status" available for parameter "Enabled".
 
        .EXAMPLE
            PS C:\> Set-WEFSubscription -Name "MySubscription" -ComputerName "SERVER1" -Enabled $true -ReadExistingEvents $true -Query '<Select Path="System">*[System[(Level=1 or Level=2 or Level=3)]]</Select>' -Description "This is my subscription" -SourceDomainComputer "Domain controllers", "MyComputerGroup"
 
            Enable "MySubscription" and set properties.
 
        .NOTES
            Author: Andreas Bellstedt
 
        .LINK
            https://github.com/AndiBellstedt/WindowsEventForwarding
    #>

    [CmdletBinding( DefaultParameterSetName = 'ComputerName',
        SupportsShouldProcess = $true,
        ConfirmImpact = 'medium')]
    Param(
        [Parameter(ValueFromPipeline = $true, Position = 0, ParameterSetName = "InputObject")]
        [WEF.Subscription[]]
        $InputObject,

        [Parameter(ValueFromPipeline = $false, Position = 0, Mandatory = $false, ParameterSetName = "ComputerName")]
        [Parameter(ValueFromPipeline = $false, Position = 0, Mandatory = $false, ParameterSetName = "Session")]
        [Alias("DisplayName", "SubscriptionID", "Idendity")]
        [ValidateNotNullOrEmpty()]
        [String[]]
        $Name,

        [Parameter(ValueFromPipeline = $true, Position = 1, Mandatory = $false, ParameterSetName = "ComputerName")]
        [Alias("host", "hostname", "Computer", "DNSHostName")]
        [PSFComputer[]]
        $ComputerName = $env:COMPUTERNAME,

        [Parameter(ParameterSetName = "Session")]
        [System.Management.Automation.Runspaces.PSSession[]]
        $Session,

        [PSCredential]
        $Credential,

        [ValidateNotNullOrEmpty()]
        [String]
        $NewName,

        [ValidateNotNullOrEmpty()]
        [string]
        $Description,

        [Alias("Enable", "Status")]
        [bool]
        $Enabled,

        [bool]
        $ReadExistingEvents,

        [ValidateSet("Events", "RenderedText")]
        [string]
        $ContentFormat,

        [ValidateNotNullOrEmpty()]
        [string]
        $LogFile,

        [ValidateSet("en-US", "de-DE", "fr-FR", "es-ES", "nl-NL", "it-IT", "af-ZA", "cs-CZ", "en-GB", "en-NZ", "en-TT", "es-PR", "ko-KR", "sk-SK", "zh-CN", "zh-HK")]
        [string]
        $Locale,

        [ValidateNotNullOrEmpty()]
        [string[]]
        $Query,

        [ValidateNotNullOrEmpty()]
        [timespan]
        $MaxLatency,

        [ValidateNotNullOrEmpty()]
        [timespan]
        $HeartBeatInterval,

        [ValidateNotNullOrEmpty()]
        [int]
        $MaxItems,

        [ValidateSet("HTTP", "HTTPS")]
        [string]
        $TransportName,

        [ValidateNotNull()]
        [String[]]
        $SourceDomainComputer,

        [ValidateNotNull()]
        [string[]]
        $SourceNonDomainDNSList,

        [ValidateNotNull()]
        [string[]]
        $SourceNonDomainIssuerCAThumbprint,

        [ValidateNotNullOrEmpty()]
        [datetime]
        $Expires,

        [switch]
        $PassThru
    )

    Begin {
        # If session parameter is used -> transfer it to ComputerName,
        # The class "PSFComputer" from PSFramework can handle it. This simplifies the handling in the further process block
        if ($Session) { $ComputerName = $Session }
    }

    Process {
        try { [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 } catch { Write-PSFMessage -Level Significant -Message "Exception while setting UTF8 OutputEncoding. Continue script." -ErrorRecord $_ }
        Write-PSFMessage -Level Debug -Message "ParameterNameSet: $($PsCmdlet.ParameterSetName)"

        #region query specified subscription when not piped in
        if ($PsCmdlet.ParameterSetName -ne "InputObject") {
            # when not inputobject --> query for existing object to modify
            Write-PSFMessage -Level Verbose -Message "Gathering $ComputerName for subscription $Name"
            try {
                $paramGetWEFSubscription = @{
                    Name         = $Name
                    ComputerName = $ComputerName
                    ErrorAction  = "Stop"
                }
                if ($Credential) { $paramGetWEFSubscription.Add("Credential", $Credential) }
                $InputObject = Get-WEFSubscription @paramGetWEFSubscription
                Remove-Variable paramGetWEFSubscription -Force -Confirm:$false -Verbose:$false -WhatIf:$false -Debug:$false
            }
            catch {
                Stop-PSFFunction -Message "Error finding subscription '$name' on computer $computer" -ErrorRecord $_
            }
            if (-not $InputObject) {
                $message = "Subscription $Name not found"
                if ($ComputerName) { $message = $message + " on " + $ComputerName }
                Stop-PSFFunction -Message $message
            }
        }
        #endregion query specified subscription when not piped in

        foreach ($subscription in $InputObject) {
            Write-PSFMessage -Level Verbose -Message "Processing $($subscription.Name) on $($subscription.ComputerName)" -Target $subscription.ComputerName
            #region preparation
            # Keep original name to identify existing subscription later
            $subscriptionNameOld = $subscription.Name
            #endregion preparation

            #region Change properties on subscription depending on given parameters (in memory operations)
            $propertyNameChangeList = @()
            switch ($PSBoundParameters.Keys) {
                "NewName" {
                    $propertyNameChangeList += "NewName"
                    Write-PSFMessage -Level Verbose -Message "Modifying property 'NewName'" -Target $subscription.ComputerName

                    $subscription.BaseObject.Subscription.SubscriptionId = $NewName #+((get-date -Format s).ToString().Replace(":","").Replace(".","")) # for testing
                }

                "Description" {
                    $propertyNameChangeList += "Description"
                    Write-PSFMessage -Level Verbose -Message "Modifying property 'Description'" -Target $subscription.ComputerName

                    $subscription.BaseObject.Subscription.Description = $Description
                }

                "Enabled" {
                    $propertyNameChangeList += "Enabled"
                    Write-PSFMessage -Level Verbose -Message "Modifying property 'Enabled'" -Target $subscription.ComputerName

                    $subscription.BaseObject.Subscription.Enabled = $Enabled.ToString()
                }

                "ReadExistingEvents" {
                    $propertyNameChangeList += "ReadExistingEvents"
                    Write-PSFMessage -Level Verbose -Message "Modifying property 'ReadExistingEvents'" -Target $subscription.ComputerName

                    $subscription.BaseObject.Subscription.ReadExistingEvents = $ReadExistingEvents.ToString()
                }

                "ContentFormat" {
                    $propertyNameChangeList += "ContentFormat"
                    Write-PSFMessage -Level Verbose -Message "Modifying property 'ContentFormat'" -Target $subscription.ComputerName

                    $subscription.BaseObject.Subscription.ContentFormat = $ContentFormat
                }

                "LogFile" {
                    $propertyNameChangeList += "LogFile"
                    Write-PSFMessage -Level Verbose -Message "Modifying property 'LogFile'" -Target $subscription.ComputerName

                    $subscription.BaseObject.Subscription.LogFile = $LogFile
                }

                "Locale" {
                    $propertyNameChangeList += "Locale"
                    Write-PSFMessage -Level Verbose -Message "Modifying property 'Locale'" -Target $subscription.ComputerName

                    $subscription.BaseObject.Subscription.Locale.Language = $Locale
                }

                "Query" {
                    $propertyNameChangeList += "Query"
                    Write-PSFMessage -Level Verbose -Message "Modifying property 'Query'" -Target $subscription.ComputerName

                    # Build the XML string to insert the query
                    $queryString = "<![CDATA[<QueryList> <Query Id='0'>`r`t$( [string]::Join("`r`t", $Query) )`r</Query></QueryList>]]>"

                    # Insert the new query in the subscription
                    $subscription.BaseObject.Subscription.Query.InnerXml = $queryString

                    # Cleanup the mess
                    Remove-Variable -Name queryString -Force -Confirm:$false -WhatIf:$false -Debug:$false -Verbose:$false -ErrorAction SilentlyContinue -WarningAction SilentlyContinue
                }

                "MaxLatency" {
                    $propertyNameChangeList += "MaxLatency"
                    Write-PSFMessage -Level Verbose -Message "Modifying property 'MaxLatency'" -Target $subscription.ComputerName

                    $subscription.BaseObject.Subscription.ConfigurationMode = "Custom"
                    $subscription.BaseObject.Subscription.Delivery.Batching.MaxLatencyTime = $MaxLatency.TotalMilliseconds.ToString()
                }

                "HeartBeatInterval" {
                    $propertyNameChangeList += "HeartBeatInterval"
                    Write-PSFMessage -Level Verbose -Message "Modifying property 'HeartBeatInterval'" -Target $subscription.ComputerName

                    $subscription.BaseObject.Subscription.ConfigurationMode = "Custom"
                    $subscription.BaseObject.Subscription.Delivery.PushSettings.Heartbeat.Interval = $HeartBeatInterval.TotalMilliseconds.ToString()
                }

                "MaxItems" {
                    $propertyNameChangeList += "MaxItems"
                    Write-PSFMessage -Level Verbose -Message "Modifying property 'MaxItems'" -Target $subscription.ComputerName

                    $subscription.BaseObject.Subscription.ConfigurationMode = "Custom"
                    if (-not ($subscription.BaseObject.Subscription.Delivery.Batching.MaxItems| Get-Member -ErrorAction SilentlyContinue)) {
                        $subscription.BaseObject.Subscription.Delivery.Batching.InnerXml = $subscription.BaseObject.Subscription.Delivery.Batching.InnerXml + '<MaxItems xmlns="http://schemas.microsoft.com/2006/03/windows/events/subscription"></MaxItems>'
                    }
                    $subscription.BaseObject.Subscription.Delivery.Batching.MaxItems = $MaxItems.ToString()
                }

                "TransportName" {
                    $propertyNameChangeList += "TransportName"
                    Write-PSFMessage -Level Verbose -Message "Modifying property 'TransportName'" -Target $subscription.ComputerName

                    $subscription.BaseObject.Subscription.TransportName = $TransportName
                }

                "SourceDomainComputer" {
                    $propertyNameChangeList += "SourceDomainComputer"
                    Write-PSFMessage -Level Verbose -Message "Modifying property 'SourceDomainComputer'" -Target $subscription.ComputerName
                    # not support yet

                    # check if property "AllowedSourceDomainComputers" exist
                    $dummyProperty = '<AllowedSourceDomainComputers xmlns="http://schemas.microsoft.com/2006/03/windows/events/subscription"></AllowedSourceDomainComputers>'
                    if (-not ($subscription.BaseObject.Subscription.AllowedSourceDomainComputers | Get-Member -ErrorAction SilentlyContinue)) {
                        $subscription.BaseObject.Subscription.InnerXml = $subscription.BaseObject.Subscription.InnerXml + $dummyProperty
                    }

                    # Parse every value specified, translate from name to SID
                    $sddlString = "O:NSG:BAD:P"
                    foreach ($sourceDomainComputerItem in $SourceDomainComputer) {
                        if ($sourceDomainComputerItem -match 'S-1-5-21-(\d|-)*$') {
                            # sourceDomainComputerItem is a SID, no need to translate
                            $SID = $sourceDomainComputerItem
                        }
                        else {
                            # try to translate name to SID
                            try {
                                $SID = [System.Security.Principal.NTAccount]::new( $sourceDomainComputerItem ).Translate([System.Security.Principal.SecurityIdentifier]).Value
                            }
                            catch {
                                Write-PSFMessage -Level Critical -Message "Cannot convert '$sourceDomainComputerItem' to a valid SID! '$sourceDomainComputerItem' will not be included as SourceDomainComputer in subscription." -Target $subscription.ComputerName
                                break
                            }
                        }

                        # Insert SDDL-String with SID
                        $sddlString = $sddlString + "(A;;GA;;;" + $SID + ")"
                    }
                    $sddlString = $sddlString + "S:"
                    $subscription.BaseObject.Subscription.AllowedSourceDomainComputers = $sddlString

                    # cleanup temporary vaiables
                    Remove-Variable -Name dummyProperty, SID, sddlString -Force -Confirm:$false -Verbose:$false -WhatIf:$false -Debug:$false
                }

                "SourceNonDomainDNSList" {
                    $propertyNameChangeList += "SourceNonDomainDNSList"
                    Write-PSFMessage -Level Verbose -Message "Modifying property 'SourceNonDomainDNSList' (AllowedSubjectList)" -Target $subscription.ComputerName

                    # check if property "AllowedSourceNonDomainComputers" exist
                    $dummyProperty = '<AllowedSourceNonDomainComputers xmlns="http://schemas.microsoft.com/2006/03/windows/events/subscription"><AllowedIssuerCAList><IssuerCA></IssuerCA></AllowedIssuerCAList><AllowedSubjectList><Subject></Subject></AllowedSubjectList></AllowedSourceNonDomainComputers>'
                    if (-not ($subscription.BaseObject.Subscription.AllowedSourceNonDomainComputers | Get-Member -ErrorAction SilentlyContinue)) {
                        $subscription.BaseObject.Subscription.InnerXml = $subscription.BaseObject.Subscription.InnerXml + $dummyProperty
                    }
                    elseif ($subscription.BaseObject.Subscription.AllowedSourceNonDomainComputers.pstypenames -contains "System.String") {
                        $subscription.BaseObject.Subscription.InnerXml = $subscription.BaseObject.Subscription.InnerXml -replace '<AllowedSourceNonDomainComputers xmlns="http://schemas.microsoft.com/2006/03/windows/events/subscription"></AllowedSourceNonDomainComputers>', $dummyProperty
                    }

                    # check if property "AllowedSubjectList" exist
                    if (-not ($subscription.BaseObject.Subscription.AllowedSourceNonDomainComputers.AllowedSubjectList | Get-Member -ErrorAction SilentlyContinue)) {
                        $subscription.BaseObject.Subscription.AllowedSourceNonDomainComputers.InnerXml = $subscription.BaseObject.Subscription.AllowedSourceNonDomainComputers.InnerXml + '<AllowedSubjectList xmlns="http://schemas.microsoft.com/2006/03/windows/events/subscription"><Subject></Subject></AllowedSubjectList>'
                    }

                    # build XML and set property
                    $xmlText = ""
                    foreach ($dnsItem in $SourceNonDomainDNSList) {
                        $xmlText += "<Subject xmlns=""http://schemas.microsoft.com/2006/03/windows/events/subscription"">$($dnsItem)</Subject>"
                    }
                    $subscription.BaseObject.Subscription.AllowedSourceNonDomainComputers.AllowedSubjectList.InnerXml = $xmlText

                    # cleanup temporary vaiables
                    Remove-Variable -Name dummyProperty, xmlText -Force -Confirm:$false -Verbose:$false -WhatIf:$false -Debug:$false
                }

                "SourceNonDomainIssuerCAThumbprint" {
                    $propertyNameChangeList += "SourceNonDomainIssuerCAThumbprint"
                    Write-PSFMessage -Level Verbose -Message "Modifying property 'SourceNonDomainIssuerCAThumbprint' (AllowedIssuerCAList)" -Target $subscription.ComputerName

                    # check if property "AllowedSourceNonDomainComputers" exist
                    $dummyProperty = '<AllowedSourceNonDomainComputers xmlns="http://schemas.microsoft.com/2006/03/windows/events/subscription"><AllowedIssuerCAList><IssuerCA></IssuerCA></AllowedIssuerCAList><AllowedSubjectList><Subject></Subject></AllowedSubjectList></AllowedSourceNonDomainComputers>'
                    if (-not ($subscription.BaseObject.Subscription.AllowedSourceNonDomainComputers | Get-Member -ErrorAction SilentlyContinue)) {
                        $subscription.BaseObject.Subscription.InnerXml = $subscription.BaseObject.Subscription.InnerXml + $dummyProperty
                    }
                    elseif ($subscription.BaseObject.Subscription.AllowedSourceNonDomainComputers.pstypenames -contains "System.String") {
                        $subscription.BaseObject.Subscription.InnerXml = $subscription.BaseObject.Subscription.InnerXml -replace '<AllowedSourceNonDomainComputers xmlns="http://schemas.microsoft.com/2006/03/windows/events/subscription"></AllowedSourceNonDomainComputers>', $dummyProperty
                    }

                    # check if property "AllowedIssuerCAList" exist
                    if (-not ($subscription.BaseObject.Subscription.AllowedSourceNonDomainComputers.AllowedIssuerCAList | Get-Member -ErrorAction SilentlyContinue)) {
                        $subscription.BaseObject.Subscription.AllowedSourceNonDomainComputers.InnerXml = $subscription.BaseObject.Subscription.AllowedSourceNonDomainComputers.InnerXml + '<AllowedIssuerCAList xmlns="http://schemas.microsoft.com/2006/03/windows/events/subscription"><IssuerCA></IssuerCA></AllowedIssuerCAList>'
                    }

                    # build XML and set property
                    $xmlText = ""
                    foreach ($thumbprint in $SourceNonDomainIssuerCAThumbprint) {
                        $xmlText += "<IssuerCA xmlns=""http://schemas.microsoft.com/2006/03/windows/events/subscription"">$($thumbprint)</IssuerCA>"
                    }
                    $subscription.BaseObject.Subscription.AllowedSourceNonDomainComputers.AllowedIssuerCAList.InnerXml = $xmlText

                    # cleanup temporary vaiables
                    Remove-Variable -Name dummyProperty, xmlText -Force -Confirm:$false -Verbose:$false -WhatIf:$false -Debug:$false
                }

                "Expires" {
                    $propertyNameChangeList += "Expires"
                    Write-PSFMessage -Level Verbose -Message "Modifying property 'Expires'" -Target $subscription.ComputerName

                    if (-not ($subscription.BaseObject.Subscription.Expires | Get-Member -ErrorAction SilentlyContinue)) {
                        $subscription.BaseObject.Subscription.InnerXml = $subscription.BaseObject.Subscription.InnerXml + '<Expires xmlns="http://schemas.microsoft.com/2006/03/windows/events/subscription"></Expires>'
                    }
                    $subscription.BaseObject.Subscription.Expires = ($Expires | Get-Date -Format s).ToString()
                }

                Default { }
            }

            if ($propertyNameChangeList -contains "Locale" -and $subscription.BaseObject.Subscription.ContentFormat -ne "RenderedText") {
                Write-PSFMessage -Level Important -Message "Property 'Locale' is specified, but 'ContentFormat' is not set to 'RenderedText'. Property setting done, but without effect." -Target $subscription.ComputerName
            }
            #endregion Change properties on subscription depending on given parameters (in memory operations)

            #region Change subscription in system
            # Done by creating temporary XML file from subscription in memory, deleting the old subscription, and recreate it from temporary xml file
            if ($pscmdlet.ShouldProcess("Subscription: $subscriptionNameOld", "Set properties '$( [String]::Join(', ', $propertyNameChangeList) )' on '$($subscription.ComputerName)'.")) {
                Write-PSFMessage -Level Verbose -Message "Start setting properties '$( [String]::Join(', ', $propertyNameChangeList) )' on '$($subscription.ComputerName)' in subscription '$($subscription.Name)'" -Target $subscription.ComputerName

                $invokeParams = @{
                    ComputerName  = $subscription.ComputerName
                    ErrorAction   = "Stop"
                    ErrorVariable = "ErrorReturn"
                    ArgumentList  = @(
                        $subscriptionNameOld,
                        $subscription.BaseObject.InnerXml,
                        "WEF.$( [system.guid]::newguid().guid ).xml"
                    )
                }
                if ($Credential) { $invokeParams.Add("Credential", $Credential)}

                # Create temp file name
                try {
                    Write-PSFMessage -Level Verbose -Message "Create temporary config file '$($invokeParams.ArgumentList[2])' for subscription to be changed." -Target $subscription.ComputerName
                    Invoke-PSFCommand @invokeParams -ScriptBlock { Set-Content -Path "$env:TEMP\$( $args[2] )" -Value $args[1] -Force -ErrorAction Stop } #tempFileName , xmlcontent
                }
                catch {
                    Stop-PSFFunction -Message "Error creating temp file for subscription!" -ErrorRecord $_ -EnableException $true
                }

                # Delete existing subscription. execute wecutil to delete subscription with redirecting error output
                try {
                    Write-PSFMessage -Level Verbose -Message "Delete existing subscription with wecutil.exe." -Target $subscription.ComputerName
                    $invokeOutput = Invoke-PSFCommand @invokeParams -ScriptBlock {
                        try { [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 } catch { Write-Information -MessageData "Exception while setting UTF8 OutputEncoding. Continue script." }
                        $output = . "$env:windir\system32\wecutil.exe" "delete-subscription" "$($args[0])" *>&1
                        $output = $output | Where-Object { $_.InvocationInfo.MyCommand.Name -like 'wecutil.exe' } *>&1
                        if ($output) { Write-Error -Message "$([string]::Join(" ", $output.Exception.Message.Replace("`r`n"," ")))" -ErrorAction Stop }
                    }
                    if ($ErrorReturn) { Write-Error "" -ErrorAction Stop}
                }
                catch {
                    Write-PSFMessage -Level Verbose -Message "This should not happen - unexpected behaviour!" -Target $subscription.ComputerName

                    $ErrorReturnWEC = $ErrorReturn | Where-Object { $_.InvocationInfo.MyCommand.Name -like 'wecutil.exe' } | select-object -Unique
                    if ($ErrorReturnWEC) {
                        $ErrorMsg = [string]::Join(" ", ($ErrorReturnWEC.Exception.Message.Replace("`r`n", " ") | select-object -Unique))
                    }
                    else {
                        $ErrorMsg = [string]::Join(" ", ($ErrorReturn.Exception.Message | select-object -Unique))
                    }

                    Stop-PSFFunction -Message "Error deleting existing subscription before recreating it! $($ErrorMsg)" -ErrorRecord $_ -EnableException $true
                }

                # Recreate changed subscription. execute wecutil to recreate changed subscription with redirecting error output
                $ErrorReturn = $null
                try {
                    Write-PSFMessage -Level Verbose -Message "Recreate subscription with wecutil.exe from temporary config file." -Target $subscription.ComputerName
                    $invokeOutput = Invoke-PSFCommand @invokeParams -ScriptBlock {
                        try { [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 } catch { Write-Information -MessageData "Exception while setting UTF8 OutputEncoding. Continue script." }
                        $output = . "$env:windir\system32\wecutil.exe" "create-subscription" "$env:TEMP\$( $args[2] )" *>&1
                        $output = $output | Where-Object { $_.InvocationInfo.MyCommand.Name -like 'wecutil.exe' } *>&1
                        if ($output) { Write-Error -Message "$([string]::Join(" ", $output.Exception.Message.Replace("`r`n"," ")))" -ErrorAction Stop }
                    }
                    if ($invokeOutput) { $ErrorReturn += $invokeOutput }
                    if ($ErrorReturn) { Write-Error -Message "" -ErrorAction Stop}
                }
                catch {
                    $ErrorReturnWEC = $ErrorReturn | Where-Object { $_.InvocationInfo.MyCommand.Name -like 'wecutil.exe' } | select-object -Unique
                    if ($ErrorReturnWEC) {
                        # this happens when run in local runspace
                        $ErrorMsg = [string]::Join(" ", ($ErrorReturnWEC.Exception.Message.Replace("`r`n", " ") | select-object -Unique))
                    }
                    else {
                        # this happens when run in remote runspace
                        $ErrorMsg = [string]::Join(" ", ($ErrorReturn.Exception.Message | select-object -Unique))
                    }

                    switch ($ErrorMsg) {
                        "*Error = *" {
                            $ErrorCode = ($ErrorMsg -Split "Error = ")[1].split(".")[0]
                        }
                        { ($_ -like "Warning: *") -or ($_ -like "Warnung: *") } {
                            $ErrorCode = "Warn1"
                        }
                        { $_ -like "Warning: Configuration mode for the subscription is not Custom.*"} {
                            $ErrorCode = "Warn2"
                        }
                        Default { $ErrorCode = 0 }
                    }

                    switch ($ErrorCode) {
                        {$_ -like "0x3ae8" -or $_ -like "Warn1"} {
                            # 0x3ae8 = The subscription is saved successfully, but it can't be activated at this time. Use retry-subscription command to retry the subscription. If subscription is running, you can also use get-subscriptionruntimestatus command to get extended error status. Error = 0x3ae8. The subscription fails to activate.
                            # Warn1 = wecutil only throw a warning, which means, this is not a critical thing. No Exception needed.
                            Write-PSFMessage -Level Warning -Message "Warning recreating subscription! wecutil.exe message: $($ErrorMsg)" -Target $subscription.ComputerName
                        }
                        "Warn2" {
                            # Warn2 = Warning: Configuration mode for the subscription is not Custom. Delivery properties are not customizable for such mode. As a result, Delivery node from the provided configuration file will be ignored.
                            Write-PSFMessage -Level VeryVerbose -Message "Noncritical warning on recreating of the subscription! wecutil.exe message: $($ErrorMsg)" -Target $subscription.ComputerName
                        }
                        Default { Write-PSFMessage -Level Warning -Message "Error recreating subscription! wecutil.exe message: $($ErrorMsg)" -Target $subscription.ComputerName -EnableException $true}
                    }
                    Clear-Variable -Name ErrorReturn -Force -Confirm:$false -Verbose:$false -WhatIf:$false -Debug:$false
                }

                # Cleanup the xml garbage (temp file)
                if (-not $result) {
                    Write-PSFMessage -Level Verbose -Message "Changes done. Going to delete temporary config file" -Target $subscription.ComputerName
                    Invoke-PSFCommand @invokeParams -ScriptBlock { Get-ChildItem -Path "$env:TEMP\$( $args[2] )" | Remove-Item -Force -Confirm:$false }
                }
                else {
                    Write-PSFMessage -Level Warning -Message "Error deleting temp files! $($ErrorReturn)" -Target $subscription.ComputerName -EnableException $true
                }

                if ($PassThru) {
                    Write-PSFMessage -Level Verbose -Message "Passthru specified, gathering changed subscription '$($subscription.Name)' on '$ComputerName' again"
                    try {
                        $paramGetWEFSubscription = @{
                            Name         = $subscription.Name
                            ComputerName = $ComputerName
                            ErrorAction  = "Stop"
                        }
                        if ($Credential) { $paramGetWEFSubscription.Add("Credential", $Credential) }
                        $output = Get-WEFSubscription @paramGetWEFSubscription
                        Remove-Variable paramGetWEFSubscription -Force -Confirm:$false -Verbose:$false -WhatIf:$false -Debug:$false
                        if ($output) { $output } else { Write-Error "" -ErrorAction Stop}
                    }
                    catch {
                        Stop-PSFFunction -Message "Error finding subscription '$($subscription.Name)' on computer $computer" -ErrorRecord $_ -EnableException $true
                    }
                }
            }
            #endregion Change subscription in system
        }
    }

    End {
    }
}