Modules/businessdev.ALbuild.Containers/Private/Get-BcContainerEnterArgument.ps1

function Get-BcContainerEnterArgument {
    <#
    .SYNOPSIS
        The 'docker exec' argument list for an interactive shell inside a container.
 
    .DESCRIPTION
        Split out from Enter-BcContainer because it is the only part that can be tested: the cmdlet
        itself hands the console to another process, which a test cannot do anything useful with. Pure -
        it builds a string array and touches nothing.
 
        '-it' is what makes the session interactive: '-i' keeps stdin attached, '-t' allocates a
        pseudo-terminal so the remote shell draws a prompt and line editing works. Without '-t' the
        shell runs but shows nothing and looks hung.
 
        '-NoExit' is the point of the whole thing: the setup command runs and the prompt stays. Without
        it the shell would execute the setup and exit immediately.
 
    .PARAMETER ContainerName
        Container to enter.
 
    .PARAMETER PowerShellExe
        The in-container shell, from Get-BcContainerPowerShellExe.
 
    .PARAMETER Command
        Optional command to run before the prompt appears.
 
    .PARAMETER WorkingDirectory
        Where the session starts. Default 'C:\run', which is where the generic image keeps its scripts.
 
    .PARAMETER SkipPrompt
        Do not dot-source the image's prompt.ps1 even when it exists.
 
    .OUTPUTS
        System.String[] - the arguments for the Docker executable.
    #>

    [CmdletBinding()]
    [OutputType([string[]])]
    param(
        [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [string] $ContainerName,
        [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [string] $PowerShellExe,
        [string] $Command,
        [string] $WorkingDirectory = 'C:\run',
        [switch] $SkipPrompt
    )

    $setup = [System.Collections.Generic.List[string]]::new()

    # -LiteralPath, and only if it is there: a container whose working directory does not exist should
    # still give a usable shell rather than an error before the prompt.
    if ($WorkingDirectory) {
        $setup.Add("if (Test-Path -LiteralPath '$($WorkingDirectory.Replace("'", "''"))') { Set-Location -LiteralPath '$($WorkingDirectory.Replace("'", "''"))' }")
    }

    # The generic image ships C:\Run\prompt.ps1, which is what makes an interactive BC container feel
    # familiar. Guarded rather than assumed: it is an image detail, not a contract, and an image without
    # it must still open a shell.
    if (-not $SkipPrompt) {
        $setup.Add("if (Test-Path -LiteralPath 'C:\Run\prompt.ps1') { . 'C:\Run\prompt.ps1' }")
    }

    if ($Command) { $setup.Add($Command) }

    $arguments = @('exec', '-it', $ContainerName, $PowerShellExe, '-NoLogo')
    if ($setup.Count -gt 0) {
        # Not -EncodedCommand: with -NoExit an encoded command leaves the session in a state where the
        # prompt is drawn but the host's own initialisation has been skipped. A plain -Command keeps the
        # normal interactive host behaviour, and everything here is generated, not user text.
        $arguments += @('-NoExit', '-Command', ($setup -join '; '))
    }
    return , [string[]]$arguments
}