Public/Set-HDTWindowText.ps1

function Set-HDTWindowText {
    <#
        .SYNOPSIS
            Writes a string table's text onto a loaded window.

        .DESCRIPTION
            THE OTHER HALF OF Get-HDTStringTable. The table is keyed
            Control.Property; this finds each control by name and writes that
            property. Nothing else about a window changes - it is the same
            by-name application New-HDTWizardHost already does for the wizard's
            fields, which is deliberate: one mechanism for "put this text there"
            rather than two that behave differently on a machine nobody can
            debug.

            A KEY WITH NO CONTROL IS SKIPPED, because a table serves every
            window in the module and no window has all the controls. A CONTROL
            WITH NO KEY IS LEFT ALONE, because a value somebody typed into a box
            is not text this command owns.

            A MISSING STRING SHOWS ITS KEY, AND THAT IS THE POINT. The
            alternative is a blank label, which looks like a layout bug and gets
            reported as one; 'HDTBootImageNameLabel.Text' on screen names the
            key somebody has to add. It cannot happen from the shipped table -
            en-us is the floor - but it can happen the moment somebody adds a
            control and forgets the string, which is exactly when it needs to be
            obvious.

            IT RETURNS WHAT IT COULD NOT DO. Applied and Missing come back so a
            caller can log them and a test can assert them without a display.

        .PARAMETER Root
            The window, or the page root. A page loaded into a host carries its
            own name scope, so the ROOT is passed in rather than the window -
            the same reason New-HDTWizardHost's Apply takes one.

        .PARAMETER String
            The table from Get-HDTStringTable.

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

        .OUTPUTS
            System.Management.Automation.PSCustomObject with Applied and
            Missing.

        .EXAMPLE
            Set-HDTWindowText -Root $window -String (Get-HDTStringTable)
    #>

    [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '',
        Justification = 'Writes text onto controls of a window the caller just loaded; it changes no system state and a confirmation prompt while a window is opening would hang it.')]
    [CmdletBinding()]
    [OutputType([pscustomobject])]
    param(
        [Parameter(Mandatory = $true, Position = 0)]
        [ValidateNotNull()]
        [object] $Root,

        [Parameter(Mandatory = $true)]
        [ValidateNotNull()]
        [System.Collections.IDictionary] $String
    )

    Set-StrictMode -Version Latest
    $ErrorActionPreference = 'Stop'

    $applied = New-Object -TypeName System.Collections.ArrayList
    $missing = New-Object -TypeName System.Collections.ArrayList

    foreach ($key in @($String.Keys)) {

        $text = [string] $String[$key]
        $name = [string] $key
        $property = 'Text'

        $split = $name.LastIndexOf('.')
        if ($split -gt 0) {
            $property = $name.Substring($split + 1)
            $name = $name.Substring(0, $split)
        }

        $control = $Root.FindName($name)
        if ($null -eq $control) { continue }

        try {
            $control.$property = $text
            [void] $applied.Add([string] $key)
        } catch {
            # A KEY NAMING A PROPERTY THE CONTROL HAS NOT GOT is a mistake in
            # the table, not a reason to leave the rest of the window in
            # English: 'HDTNextButton.Text' on a Button, where the property is
            # Content, would otherwise stop every string after it.
            [void] $missing.Add(('{0}: {1}' -f $key, [string] $_.Exception.Message))
        }
    }

    return [pscustomobject] @{
        Applied = [string[]] @($applied)
        Missing = [string[]] @($missing)
    }
}