Private/Get-WinClatConfigurationScript.ps1

Function Get-WinClatConfigurationScript {

    <#

    .SYNOPSIS
        Returns the self-contained script block that Get-WinClatConfiguration runs on each target.

    .DESCRIPTION
        The script block takes one positional argument, the netsh store name ('active', 'persistent', or 'both'), and follows the execution order in DESIGN.md, section 4.4:
          1. Feature check: 'clat' in the 'netsh interface ?' sub-context list. If absent, returns NotSupported on Windows Server or FeatureNotAvailable on a client (Get-WinClatFeatureFailure), with the OS build.
          2. No elevation check; 'show global' does not require elevation (section 3.3).
          3. Runs 'netsh interface clat show global store=<store>'.
          4. Classifies a non-zero exit code with Get-WinClatNetshFailure.

        On success it returns one WinClat.Configuration object per store, with PolicyControlled from the policy registry key (section 9), OSBuild, and a UTC CollectedAtUtc.

        Get-WinClatConfiguration and the unit tests both use this function, so the tests exercise the script block that is sent remotely.

    .INPUTS
        None. This function does not accept pipeline input.

    .OUTPUTS
        System.Management.Automation.ScriptBlock.

    .EXAMPLE
        & (Get-WinClatConfigurationScript) 'both'

        Returns the active and persistent configuration of the local computer.

    .LINK
        https://learn.microsoft.com/windows-server/administration/windows-commands/netsh

    .NOTES
        Version: 1.0.0
        Creation Date: October 28, 2026
        Last Updated: October 28, 2026
        Author: Richard Hicks
        Organization: Richard M. Hicks Consulting, Inc.
        Contact: rich@richardhicks.com
        Website: https://www.richardhicks.com/

    #>


    [CmdletBinding()]
    [OutputType([scriptblock])]

    Param ()

    $HelperName = @(

        'ConvertFrom-WinClatNetshOutput'
        'ConvertTo-WinClatTimeSpan'
        'ConvertTo-WinClatConfiguration'
        'Get-WinClatNetshFailure'
        'Get-WinClatOSBuild'
        'Get-WinClatPolicyControlled'
        'Get-WinClatFeatureFailure'
        'Test-WinClatFeature'

    )

    $Body = {

        Param ($Store)

        $OSBuild = Get-WinClatOSBuild
        $Help = @(netsh.exe interface '?')

        If (-not (Test-WinClatFeature -InputObject $Help)) {

            # NotSupported on Windows Server, FeatureNotAvailable on a client that has not received the feature.
            $Missing = Get-WinClatFeatureFailure -OSBuild $OSBuild

            $Failure = @{

                ComputerName   = $env:COMPUTERNAME
                Status         = $Missing.Status
                OSBuild        = $OSBuild
                CollectedAtUtc = (Get-Date).ToUniversalTime()
                Message        = $Missing.Message

            }

            ConvertTo-WinClatConfiguration @Failure
            Return

        }

        $Output = @(netsh.exe interface clat show global "store=$Store")
        $ExitCode = $LASTEXITCODE
        $CollectedAtUtc = (Get-Date).ToUniversalTime()

        If ($ExitCode -ne 0) {

            $Classified = Get-WinClatNetshFailure -InputObject $Output -ExitCode $ExitCode

            $Failure = @{

                ComputerName   = $env:COMPUTERNAME
                Status         = $Classified.Status
                OSBuild        = $OSBuild
                CollectedAtUtc = $CollectedAtUtc
                Message        = $Classified.Message

            }

            ConvertTo-WinClatConfiguration @Failure
            Return

        }

        $Settings = @(ConvertFrom-WinClatNetshOutput -InputObject $Output)

        If ($Settings.Count -eq 0) {

            $Failure = @{

                ComputerName   = $env:COMPUTERNAME
                Status         = 'Failed'
                OSBuild        = $OSBuild
                CollectedAtUtc = $CollectedAtUtc
                Message        = "netsh.exe returned no configuration data: $((@($Output) -join ' ').Trim())"

            }

            ConvertTo-WinClatConfiguration @Failure
            Return

        }

        $PolicyControlled = Get-WinClatPolicyControlled

        ForEach ($Item in $Settings) {

            $Result = @{

                ComputerName     = $env:COMPUTERNAME
                Status           = 'Success'
                Settings         = $Item
                PolicyControlled = $PolicyControlled
                OSBuild          = $OSBuild
                CollectedAtUtc   = $CollectedAtUtc

            }

            ConvertTo-WinClatConfiguration @Result

        }

    }

    Get-WinClatRemoteScript -HelperName $HelperName -ScriptBlock $Body

}