Modules/businessdev.ALbuild.Containers/Public/Resolve-BcContainerHostShare.ps1

function Resolve-BcContainerHostShare {
    <#
    .SYNOPSIS
        Returns the host folder actually bind-mounted to C:\run\my in a container (with a fallback).
 
    .DESCRIPTION
        Files are exchanged with a Business Central container through the host folder bind-mounted to
        C:\run\my (Copy-BcFileToContainer writes there; Invoke-BcContainerCommand stages large command
        scripts there). Get-BcContainerHostShare returns the DETERMINISTIC folder that ALbuild's own
        New-BcContainer mounts - which is correct only for a container this module created in the current
        job, because the convention is rooted under the job-scoped AGENT_TEMPDIRECTORY. For a container
        created elsewhere - a BcContainerHelper container, or a long-lived container targeted by a
        release / on-prem deployment - that path does NOT match the real mount, so staged files are
        written to a folder the container cannot see (the deploy then fails with "the argument
        'C:\run\my\...ps1' to the -File parameter does not exist").
 
        This resolves the REAL host path by inspecting the container's mounts (authoritative regardless
        of who created it) and returning the Source of the C:\run\my bind mount. If the container cannot
        be inspected - Docker missing, or the container does not exist yet (e.g. called at creation time) -
        it falls back to the deterministic Get-BcContainerHostShare convention.
 
    .PARAMETER Name
        Container name.
 
    .PARAMETER DockerExecutable
        The Docker executable to use (default 'docker').
 
    .OUTPUTS
        System.String - the host folder path bind-mounted to C:\run\my.
    #>

    [CmdletBinding()]
    [OutputType([string])]
    param(
        [Parameter(Mandatory, Position = 0)] [ValidateNotNullOrEmpty()] [string] $Name,
        [string] $DockerExecutable = 'docker'
    )

    try {
        # One line per mount: '<destination>|<source>'. PassThru+Quiet so a missing container returns a
        # non-success result (we fall back) instead of throwing or logging.
        $inspect = Invoke-BcDocker -DockerExecutable $DockerExecutable -PassThru -Quiet -Arguments @(
            'inspect', '--format', '{{range .Mounts}}{{.Destination}}|{{.Source}}{{println}}{{end}}', $Name)
        if ($inspect.Success -and $inspect.StdOut) {
            foreach ($line in ($inspect.StdOut -split "`r?`n")) {
                $sep = $line.IndexOf('|')
                if ($sep -lt 1) { continue }
                # Destinations come back as 'c:\run\my' (docker lower-cases the drive); normalise slashes,
                # trailing separator and case before matching.
                $dst = $line.Substring(0, $sep).Trim().Replace('/', '\').TrimEnd('\').ToLowerInvariant()
                if ($dst -eq 'c:\run\my') {
                    $src = $line.Substring($sep + 1).Trim()
                    if ($src) {
                        Write-ALbuildLog -Level Verbose "Resolved '$Name' C:\run\my host mount to '$src' (from docker inspect)."
                        return $src
                    }
                }
            }
        }
    }
    catch {
        Write-ALbuildLog -Level Verbose "Could not inspect '$Name' for its C:\run\my mount ($($_.Exception.Message)); using the conventional host share."
    }

    return (Get-BcContainerHostShare -Name $Name)
}