Public/Get-ALHOffice365UpdateChannel.ps1

<#PSScriptInfo
 
.VERSION 1.0.0
 
.GUID 8123d13f-7262-4e67-8a6e-363a00781935
 
.AUTHOR Dieter Koch
 
.COMPANYNAME
 
.COPYRIGHT (c) 2021-2023 Dieter Koch
 
.TAGS
 
.LICENSEURI https://github.com/admins-little-helper/ALH/blob/main/LICENSE
 
.PROJECTURI https://github.com/admins-little-helper/ALH
 
.ICONURI
 
.EXTERNALMODULEDEPENDENCIES
 
.REQUIREDSCRIPTS
 
.EXTERNALSCRIPTDEPENDENCIES
 
.RELEASENOTES
    1.0.0
    - Initial release
 
#>



<#
 
.DESCRIPTION
 Retrieve the name of the M365 Apps (Office 365) update channel configured on a computer.
 
#>




function Get-ALHOffice365UpdateChannel {
    <#
    .SYNOPSIS
        Retrieve the name of the M365 Apps (Office 365) update channel configured on a computer.
 
    .DESCRIPTION
        The function 'Get-ALHOffice365UpdateChannel' retrieves the name of the M365 Apps (Office 365) update channel configured on a computer.
 
    .PARAMETER ComputerName
        Specifies the name of the computer for which to retrieve the update channel information. Defaults to the local computername.
 
    .PARAMETER SkipConnectionTest
        If specified, no attempt to ping the computer before trying to retrieve the update channel information is made.
 
    .EXAMPLE
        Get-ALHOffice365UpdateChannel
 
        Computer EffectiveChannel ConfiguredChannels
        -------- ---------------- ------------------
        LocalComputer Current @{Channel=Current; ChannelGuid=492350f6-3a01-4f97-b9c0-c7c6ddf67d60; ChannelRegVal=http://officecdn.microsoft.com/pr/492350f6-3a01-4f97-b9c0-c7c6ddf67d60; Prio=4}
 
        Returns the update channel information for the local computer.
 
    .EXAMPLE
        Get-ALHOffice365UpdateChannel -ComputerName RemoteComputer1, RemoteComputer2
 
        Computer EffectiveChannel ConfiguredChannels
        -------- ---------------- ------------------
        RemoteComputer1 Current @{Channel=Current; ChannelGuid=492350f6-3a01-4f97-b9c0-c7c6ddf67d60; ChannelRegVal=http://officecdn.microsoft.com/pr/492350f6-3a01-4f97-b9c0-c7c6ddf67d60; Prio=4}
        RemoteComputer2 Current @{Channel=Current; ChannelGuid=492350f6-3a01-4f97-b9c0-c7c6ddf67d60; ChannelRegVal=http://officecdn.microsoft.com/pr/492350f6-3a01-4f97-b9c0-c7c6ddf67d60; Prio=4}
 
        Returns the update channel information for the two computers 'RemoteComputer1' and 'RemoteComputer2'. This only works if the specified
        computers are online and if the user executing the function has administrator privileges on them to read the registry remotely.
 
    .INPUTS
        System.String
 
    .OUTPUTS
        PSCustomObject
 
    .NOTES
        Author: Dieter Koch
        Email: diko@admins-little-helper.de
 
    .LINK
        https://github.com/admins-little-helper/ALH/blob/main/Help/Get-ALHOffice365UpdateChannel.txt
 
    .LINK
        https://techcommunity.microsoft.com/t5/microsoft-365-blog/how-to-manage-office-365-proplus-channels-for-it-pros/ba-p/795813
 
    .LINK
        https://learn.microsoft.com/en-us/deployoffice/updates/change-update-channels
    #>


    [OutputType([PSCustomObject])]
    [CmdletBinding()]
    param (
        [Parameter(ValueFromPipeline = $true, Position = 0, HelpMessage = "The name of the computer to retrieve information for.")]
        [string[]]
        $ComputerName = $env:COMPUTERNAME,

        [Parameter(Position = 1, HelpMessage = "Skip to check if the specified computer is online.")]
        [switch]
        $SkipConnectionTest
    )

    begin {
        # Define the Channel Ids and their corrosponding names.
        $ChannelIdMapping = @{
            "55336b82-a18d-4dd6-b5f6-9e5095c314a6" = "MonthlyEnterprise"
            "492350f6-3a01-4f97-b9c0-c7c6ddf67d60" = "Current"
            "64256afe-f5d9-4f86-8936-8840a6a4f5be" = "CurrentPreview"
            "7ffbc6bf-bc32-4f92-8982-f9dd17fd3114" = "SemiAnnualEnterprise"
            "b8f9b850-328d-4355-9145-c59439a0c4cf" = "SemiAnnualEnterprisePreview"
            "5440fd1f-7ecb-4221-8110-145efaa6372f" = "Beta"

            # https://github.com/ItzLevvie/Office16/blob/master/defconfig
            "ea4a4090-de26-49d7-93c1-91bff9e53fc3" = "_Dogfood_DevMain"
            "f3260cf1-a92c-4c75-b02e-d64c0a86a968" = "_Dogfood_CC"
            "b61285dd-d9f7-41f2-9757-8f61cba4e9c8" = "_Microsoft_DevMain"
            "5462eee5-1e97-495b-9370-853cd873bb07" = "_Microsoft_CC"
            "9a3b7ff2-58ed-40fd-add5-1e5158059d1c" = "_Microsoft_FRDC"
            "f4f024c8-d611-4748-a7e0-02b6e754c0fe" = "_Microsoft_DC"
            "86752282-5841-4120-ac80-db03ae6b5fdb" = "_Microsoft_LTSC2021"
            "1d2d2ea6-1680-4c56-ac58-a441c8c24ff9" = "_Microsoft_LTSC"
            "f2e724c1-748f-4b47-8fb8-8e0d210e9208" = "_Production_LTSC"
            <#
            "5440fd1f-7ecb-4221-8110-145efaa6372f" = "Insiders_DevMain"
            "64256afe-f5d9-4f86-8936-8840a6a4f5be" = "Insiders_CC"
            "b8f9b850-328d-4355-9145-c59439a0c4cf" = "Insiders_FRDC"
            "492350f6-3a01-4f97-b9c0-c7c6ddf67d60" = "Production_CC"
            "55336b82-a18d-4dd6-b5f6-9e5095c314a6" = "Production_MEC"
            "7ffbc6bf-bc32-4f92-8982-f9dd17fd3114" = "Production_DC"
            "5030841d-c919-4594-8d2d-84ae4f96e58e" = "Production_LTSC2021"
            #>

        }

        # Define the registry paths and values that are qureied to determine the configured update channels.
        $RegistryPaths = @(
            [PSCustomObject]@{
                RegPath = "HKLM:\software\policies\microsoft\office\16.0\common\officeupdate"
                Value   = "updatepath"
                Prio    = 0
            }
            [PSCustomObject]@{
                RegPath = "HKLM:\software\policies\microsoft\office\16.0\common\officeupdate"
                Value   = "updatebranch"
                Prio    = 1
            }
            [PSCustomObject]@{
                RegPath = "HKLM:\SOFTWARE\Microsoft\Office\ClickToRun\Configuration"
                Value   = @("UpdateURL", "UpdatePath")
                Prio    = 2
            }
            [PSCustomObject]@{
                RegPath = "HKLM:\SOFTWARE\Microsoft\Office\ClickToRun\Configuration"
                Value   = "UnmanagedUpdateURL"
                Prio    = 3
            }
            [PSCustomObject]@{
                RegPath = "HKLM:\SOFTWARE\Microsoft\Office\ClickToRun\Configuration"
                Value   = "CDNBaseUrl"
                Prio    = 4
            }
        )
    }

    process {
        foreach ($Computer in $ComputerName) {
            try {
                # Create an object of type PSCustomObject that's used to carry the information we want to return.
                $UpdateInfo = [PSCustomObject]@{
                    Computer           = $Computer
                    ConfiguredChannels = $null
                    EffectiveChannel   = $null
                }

                # Check if the specififed computer is online.
                $IsComputerOnline = $false
                if ($SkipConnectionTest.IsPresent) {
                    Write-Verbose -Message "[$Computer]: Skipping connection test."
                    $IsComputerOnline = $true
                }
                else {
                    Write-Verbose -Message "[$Computer]: Checking if system is online."
                    $IsComputerOnline = Test-Connection $Computer -Count 1 -Quiet
                    Write-Verbose -Message "[$Computer]: Is online: $IsComputerOnline"
                }

                if ($IsComputerOnline) {
                    Write-Verbose -Message "[$Computer]: Trying to get update channel information for computer."
                    foreach ($Entry in $RegistryPaths) {
                        Write-Verbose -Message "[$Computer]: Checking UpdateChannel Prio [$($Entry.Prio)] - [$($Entry.RegPath)]."
                        foreach ($ValueName in $Entry.Value) {
                            # Define the paramters for the Get-ALHRegistryItem function, which will finally read the registry on the (remote) computer.
                            $GetALHRegistryItemParams = @{
                                ComputerName       = $Computer
                                Path               = $Entry.RegPath
                                ValueName          = $ValueName
                                SkipConnectionTest = $true
                            }
                            $RegistryValue = (Get-ALHRegistryItem @GetALHRegistryItemParams).Data

                            # Check if the value retured is something or nothing...
                            if ([string]::IsNullOrEmpty($RegistryValue)) {
                                Write-Verbose -Message "[$Computer]: RegistryValue is empty, so not in use."
                            }
                            else {
                                Write-Verbose -Message "[$Computer]: RegistryValue: [$RegistryValue]."

                                # Get the GUID value from the URL value.
                                $ChannelGuid = $RegistryValue -replace 'http://officecdn.microsoft.com/pr/', ''
                                Write-Verbose -Message "[$Computer]: This computer is configured for update channel [$($ChannelIdMapping[$ChannelGuid])]."

                                # Fill the 'ToBeReturned' object with data.
                                $UpdateInfo.ConfiguredChannels += [PSCustomObject]@{
                                    Channel       = $($ChannelIdMapping[$ChannelGuid])
                                    ChannelGuid   = $ChannelGuid
                                    ChannelRegVal = $RegistryValue
                                    Prio          = $Entry.Prio
                                }
                            }
                        }
                    }
                }

                # Calculate the effective channel.
                Write-Verbose -Message "[$Computer]: If multiple channels are configued, the one with the lowest priority value wins."
                $UpdateInfo.EffectiveChannel = ($UpdateInfo.ConfiguredChannels | Sort-Object -Property Prio | Select-Object -First 1).Channel

                # Define custom type name for the PSCustomObject to make sure the custom format is applied.
                $UpdateInfo.PSObject.TypeNames.Insert(0, "ALHM365AppsUpdateChannel")

                # Return the object.
                $UpdateInfo
            }
            catch {
                $_
            }
        }
    }
}


#region EndOfScript
<#
################################################################################
################################################################################
#
# ______ _ __ _____ _ _
# | ____| | | / _| / ____| (_) | |
# | |__ _ __ __| | ___ | |_ | (___ ___ _ __ _ _ __ | |_
# | __| | '_ \ / _` | / _ \| _| \___ \ / __| '__| | '_ \| __|
# | |____| | | | (_| | | (_) | | ____) | (__| | | | |_) | |_
# |______|_| |_|\__,_| \___/|_| |_____/ \___|_| |_| .__/ \__|
# | |
# |_|
################################################################################
################################################################################
# created with help of http://patorjk.com/software/taag/
#>

#endregion