functions/Get-WELCEventChannel.ps1

function Get-WELCEventChannel {
    <#
    .Synopsis
        Get-WELCEventChannel
 
    .DESCRIPTION
        Query Windows Eventlog Channel(s) and their provider information.
 
    .PARAMETER ComputerName
        The computer(s) to connect to.
        Supports PSSession objects also.
 
    .PARAMETER Session
        A PSSession object for remote connection to another machine
 
    .PARAMETER Credential
        The credentials to use on remote calls
 
    .PARAMETER ChannelFullName
        The name of the EventChannel to query
 
        Default is every channel
 
    .EXAMPLE
        PS C:\> Get-WELCEventChannel
 
        Display all available subscription
 
    .EXAMPLE
        PS C:\> Get-WELCEventChannel -ChannelFullName MyChannel
 
        Display Channel "MyChannel"
 
    .EXAMPLE
        PS C:\> Get-WELCEventChannel -ChannelFullName MyChannel -ComputerName SRV01
 
        Display Channel "MyChannel" from remote computer "SRV01".
 
    .EXAMPLE
        PS C:\> Get-WELCEventChannel -ChannelFullName MyChannel -Sesion $PSSession
 
        Display Channel "MyChannel" from all connections within the $PSSession variable
 
        Assuming $PSSession variable is created something like this:
        $PSSession = New-PSSession -ComputerName SRV01
 
    .NOTES
        Author: Andreas Bellstedt
 
    .LINK
        https://github.com/AndiBellstedt/WinEventLogCustomization
 
    #>

    [CmdletBinding(
        DefaultParameterSetName = 'ComputerName',
        PositionalBinding = $true,
        ConfirmImpact = 'low'
    )]
    [OutputType([WELC.EventLogChannel])]
    Param(
        [Parameter(
            ValueFromPipeline = $true,
            Position = 0
        )]
        [Alias("Name", "ChannelName", "LogName")]
        [ValidateNotNullOrEmpty()]
        [String[]]
        $ChannelFullName = "*",

        [Parameter(
            ParameterSetName = "ComputerName",
            ValueFromPipeline = $true,
            ValueFromPipelineByPropertyName = $true,
            Position = 1
        )]
        [Alias("Host", "Hostname", "Computer", "DNSHostName")]
        [PSFComputer[]]
        $ComputerName = $env:COMPUTERNAME,

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

        [Parameter( ParameterSetName = "ComputerName" )]
        [PSCredential]
        $Credential
    )

    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.ComputerName }

        $channelFullNameBound = Test-PSFParameterBinding -ParameterName ChannelFullName
        $computerBound = Test-PSFParameterBinding -ParameterName ComputerName
    }

    process {
        #region parameterset workarround
        Write-PSFMessage -Level Debug -Message "ParameterNameSet: $($PsCmdlet.ParameterSetName)"

        # Workarround parameter binding behaviour of powershell in combination with ComputerName Piping
        if (-not ($channelFullNameBound -or $computerBound) -and $ComputerName.InputObject -and $PSCmdlet.ParameterSetName -ne "Session") {
            if ($ComputerName.InputObject -is [string]) { $ComputerName = $env:ComputerName } else { $ChannelFullName = "*" }
        }
        #endregion parameterset workarround

        #region Processing Channels
        foreach ($computer in $ComputerName) {
            $winEventProviders = @()
            $errorChannel = @()

            foreach ($channel in $ChannelFullName) {

                $ErrorReturn = $null
                $paramInvokeCmd = [ordered]@{
                    "ComputerName" = $computer
                    "ErrorAction"  = "Stop"
                    ErrorVariable  = "ErrorReturn"
                    "ArgumentList" = $channel
                }
                if ($PSCmdlet.ParameterSetName -eq "Session") { $paramInvokeCmd['ComputerName'] = $Session }
                if ($Credential) { $paramInvokeCmd.Add("Credential", $Credential) }

                Write-PSFMessage -Level Verbose -Message "Query EventLog channel '$($channel)' on computer '$($computer)'" -Target $computer
                try {
                    $winEventChannels = Invoke-PSFCommand @paramInvokeCmd -ScriptBlock { Get-WinEvent -ListLog $args[0] -ErrorAction Stop }
                } catch {
                    Stop-PSFFunction -Message "Unable to query EventLog channel '$($channel)' on computer '$($computer)'. ErrorMessage: $($ErrorReturn.Exception.Message | Select-Object -Unique)" -Target $computer -ErrorRecord $_
                    continue
                }

                [array]$providerNames = $winEventChannels.ProviderNames | Select-Object -Unique
                Write-PSFMessage -Level Verbose -Message "Query $($providerNames.count) provider from EventLog channel '$($winEventChannels.LogName)'" -Target $computer

                $errorMessages = @()
                $providerNames = $providerNames | Where-Object { $_ -notin $winEventProviders.name -and $_ -notin $errorChannel }
                $winEventProviders += foreach ($providerName in $providerNames) {
                    $ErrorReturn = $null
                    $paramInvokeCmd['ArgumentList'] = $providerName
                    try {
                        Invoke-PSFCommand @paramInvokeCmd -ScriptBlock {
                            Get-WinEvent -ListProvider $args -ErrorAction SilentlyContinue -ErrorVariable ErrorOccured
                            if ($ErrorOccured) { Write-Error -Message ([string]::Join(" " , ($ErrorOccured.Exception.Message | Select-Object -Unique))) -ErrorAction Stop }
                        } -Verbose:$false
                    } catch {
                        Write-PSFMessage -Level Debug -Message "Unable to query provider '$($providerName)' from computer '$($computer)'. ErrorMessage: $($ErrorReturn.Exception | Select-Object -ExpandProperty Message -Unique)" -Target $computer -ErrorRecord $_
                        $errorChannel += $providerName
                        $errorMessages += $ErrorReturn.Exception[-1].Message
                    }
                }

                if ($errorMessages) {
                    Write-PSFMessage -Level Error -Message "Error query provider ($([string]::Join(", ", $providerNames))) from EventLog Channel '$($winEventChannels.LogName)' on computer '$($computer)'. ErrorMessage: $([string]::join(" ", $errorMessages))" -Target $computer
                }

                Write-PSFMessage -Level Verbose -Message "Output $(([Array]$winEventChannels).count) EventLog channel$(if(([Array]$winEventChannels).count -gt 1){"s"})" -Target $computer
                # Output result
                foreach ($winEventChannel in $winEventChannels) {

                    $output = [WELC.EventLogChannel]@{
                        "PSComputerName" = $computer
                        "WinEventLog"    = $winEventChannel
                        "Provider"       = ( $winEventChannel.ProviderNames | ForEach-Object { $_name = $_; $winEventProviders | Where-Object ProviderName -like $_name } )
                    }

                    $output
                }
            }
        }
        #endregion Processing Events

    }

    end {
    }
}