AL/Get-AllSymbol.ps1

<#
 .Synopsis
  Downloads Symbols for apps
 .Description
  Downloads Symbols from container for app, dependency apps, and optionally test app
 .Parameter SourcePath
  Path to the current project
 .Parameter ContainerName
  If blank, the container name will be retrieved from settings.json
 .Parameter includeTestSymbols
  Add this switch to get the test app symbols as well
 .Example
  Get-AllSymbol -SourcePath "C:\Temp" -ContainerName "container" -includeTestSymbols
#>

function Get-AllSymbol {
    Param(
        [Parameter(Mandatory=$false)]
        [string]$SourcePath = (Get-Location),
        [Parameter(Mandatory=$false)]
        [string]$ContainerName = (Get-ContainerFromLaunchJson),
        # optionally download the test symbols
        [Parameter(Mandatory=$false)]
        [switch]
        $includeTestSymbols
    )

    $PackagesPath = Join-Path $SourcePath '.alpackages'

    if (!(Test-Path $PackagesPath)) {
        New-EmptyDirectory $PackagesPath
    }

    # prepare a list of apps to download
    $PlatformVersion = Get-PlatformFromContainer -ContainerName $ContainerName
    $appsToDownload = [System.Collections.ArrayList]@()
    $serviceTier = 'BC'

    if ($PlatformVersion.Major -ge 15) {
        $Dependencies = Get-AppKeyValue -SourcePath $SourcePath -KeyName 'dependencies'
        foreach ($Dependency in $Dependencies) {
            $appsToDownload.Add([PSCustomObject]@{
                Publisher = $Dependency.Publisher
                Name = $Dependency.name
                Version = $Dependency.Version
                fileName = ""
            }) | Out-Null
        }

        if ((Get-AppKeyValue -SourcePath $SourcePath -KeyName "Application") -ne "") {
            $applicationInfo = Get-BcContainerAppInfo -containerName $ContainerName -tenant "default" -tenantSpecificProperties | Where-Object {$_.Name -eq "Application"}
            $appsToDownload.Add([PSCustomObject]@{
                Publisher = $applicationInfo.Publisher
                Name = $applicationInfo.name
                Version = $applicationInfo.Version
                fileName = ""
            }) | Out-Null
        }

        $applicationInfo = Get-BcContainerAppInfo -containerName $ContainerName -SymbolsOnly
        foreach ($app in $applicationInfo) {
            $appsToDownload.Add([PSCustomObject]@{
                Publisher = $app.Publisher
                Name = $app.Name
                Version = $app.Version
                fileName = ""
            }) | Out-Null
        }
    }
    else {
        $appsToDownload.Add([PSCustomObject]@{
            Publisher = 'Microsoft'
            Name = 'Application'
            Version = (Get-AppKeyValue -SourcePath $SourcePath -KeyName 'application')
            fileName = ""
        }) | Out-Null
        $appsToDownload.Add([PSCustomObject]@{
            Publisher = 'Microsoft'
            Name = 'System'
            Version = (Get-AppKeyValue -SourcePath $SourcePath -KeyName 'platform')
            fileName = ""
        }) | Out-Null
        if ($includeTestSymbols.IsPresent) {
            $appsToDownload.Add([PSCustomObject]@{
                Publisher = 'Microsoft'
                Name = 'Test'
                Version = (Get-AppKeyValue -SourcePath $SourcePath -KeyName 'test')
                fileName = ""
            }) | Out-Null
        }

        $serviceTier = 'NAV'
    }

    $appsDownloaded = [System.Collections.ArrayList]@()
    $appsNewDownloaded = [System.Collections.ArrayList]@()

    $Headers = New-Header

    while ($appsToDownload.Count -ne 0) {
        $appsNewDownloaded.Clear()

        # now download all apps
        foreach($app in $appsToDownload) {
            $version = [version]$app.Version
            $existingFile = Get-Item (Join-Path $PackagesPath ('{0}_{1}_{2}.{3}.*.*.app' -f $app.Publisher, $app.Name, $version.Major, $version.Minor).Replace(":", "_").Replace("__", "_")) -ErrorAction SilentlyContinue
            if ($null -eq $existingFile) {
                $Uri = 'http://{0}:7049/{1}/dev/packages?publisher={2}&appName={3}&versionText=' -f $ContainerName, $serviceTier, $app.Publisher, $app.Name
                if ($PlatformVersion.Major -ge 15) {
                    $Uri = '{0}&tenant=default' -f $Uri
                }
                Write-Output "Downloading $($app.Publisher) - $($app.Name)"
                try {
                    $file = Invoke-WebRequest -Uri $Uri -Headers $Headers -OutFile (Join-Path $PackagesPath ('{0}_{1}_{2}.app' -f $app.Publisher, $app.Name, $app.Version).Replace(":", "_").Replace("__", "_")) -PassThru
                }
                catch {
                    $appinfo = Get-BcContainerAppInfo -containerName $containerName -tenant default -tenantSpecificProperties | Where-Object {$_.Name -like ("*{0}*" -f $app.Name)}
                    if ($null -ne $appinfo) {
                        $Uri = 'http://{0}:7049/{1}/dev/packages?publisher={2}&appName={3}&versionText=' -f $ContainerName, $serviceTier, $appinfo.Publisher, $appinfo.Name
                        if ($PlatformVersion.Major -ge 15) {
                            $Uri = '{0}&tenant=default' -f $Uri
                        }
                        $file = Invoke-WebRequest -Uri $Uri -Headers $Headers -OutFile (Join-Path $PackagesPath ('{0}_{1}_{2}.app' -f $appinfo.Publisher, $appinfo.Name, $appinfo.Version).Replace(":", "_").Replace("__", "_")) -PassThru
                        $app.Name = $appinfo.Name
                        $app.Version = $appinfo.Version
                    }
                }
                if ($file.Headers."Content-Disposition".Contains('"')) {
                    $fileName = $file.Headers."Content-Disposition".Split('"')[1]
                }
                else {
                    $fileName = $file.Headers."Content-Disposition".Split(';')[1].Split('=')[1]
                }
                if ($fileName -ne ('{0}_{1}_{2}.app' -f $app.Publisher, $app.Name, $app.Version).Replace(":", "_").Replace("__", "_")) {
                    if (Test-Path (Join-Path $PackagesPath $fileName)) {
                        Remove-Item (Join-Path $PackagesPath $fileName) -Force
                    }
                    Rename-Item (Join-Path $PackagesPath ('{0}_{1}_{2}.app' -f $app.Publisher, $app.Name, $app.Version).Replace(":", "_").Replace("__", "_")) $fileName -Force
                    $app.Version = [version]($fileName.Split("_")[-1].Split(".")[0..3] -join ".")
                }
                $app.fileName = $fileName
            }
            else {
                $fileName = Split-Path $existingFile -Leaf
                $app.fileName = $fileName
                try {
                    $app.Version = [version]($fileName.Split("_")[-1].Split(".")[0..3] -join ".")
                }
                catch {
                    $existingInfo = Get-AppInfoFromContainer -containerName $ContainerName -appFile $existingFile
                    $app.Version = [version]$existingInfo.Version
                }
            }
            $appsDownloaded.Add($app) | Out-Null
            $appsNewDownloaded.Add($app) | Out-Null
        }

        # now go through all apps and check for dependencies
        $appsToDownload.Clear()
        foreach ($app in $appsNewDownloaded) {
            # unpack app
            $appFolder = New-TempDirectory
            try {
                Extract-AppFileToFolder -appFilename (Join-Path $PackagesPath $app.fileName) -appFolder $appFolder -generateAppJson | Out-Null

                # loop through dependencies and add apps to
                $appJson = Get-Content -Path (Join-Path $appFolder 'app.json') | ConvertFrom-Json
            }
            catch {
                $appJson = Get-AppInfoFromContainer -containerName $ContainerName -appFile (Join-Path $PackagesPath $app.fileName)
            }

            if ($null -ne $appJson.dependencies) {
                foreach($dep in $appJson.dependencies) {
                    $found = $appsDownloaded | Where-Object {$_.Publisher -eq $dep.Publisher -and $_.Name -eq $dep.name -and $_.Version -ge $dep.Version}
                    $version = [version]$dep.Version
                    $existingFile = Get-Item (Join-Path $PackagesPath ('{0}_{1}_{2}.*.*.*.app' -f $dep.Publisher, $dep.Name, $version.Major)) -ErrorAction SilentlyContinue
                    if ($null -ne $existingFile) {
                        $existingFileParts = $existingFile.FullName.Split(".")
                        if (($existingFileParts[1] -lt $version.Minor) -or ($existingFileParts[1] -eq $version.Minor -and $existingFileParts[2] -lt $version.Build) -or ($existingFileParts[1] -eq $version.Minor -and $existingFileParts[2] -eq $version.Build -and $existingFileParts[3] -lt $version.Revision)) {
                            $existingFile = $null
                        }
                    }
                    if ($null -eq $found -and $null -eq $existingFile) {
                        $appsToDownload.Add([PSCustomObject]@{
                            Publisher = $dep.Publisher
                            Name = $dep.name
                            Version = $dep.Version
                            fileName = ""
                        }) | Out-Null
                    }
                }
            }

            # cleanup
            Remove-Item -Path $appFolder -Recurse -Force
        }
    }

    Write-Output "downloaded all symbols"
}

function New-Header
{
    [CmdletBinding(SupportsShouldProcess, ConfirmImpact="low")]
    [OutputType([System.Collections.Hashtable])]
    Param ()

    if ($PSCmdlet.ShouldProcess("Authorization", "Adding authorization headers to ")) {
        $ba = '{0}:{1}' -f (Get-Secret -vaultName "NAV-X" -secretName "Username"), (Get-Secret -vaultName "NAV-X" -secretName "Password")
        $ba = [System.Text.Encoding]::UTF8.GetBytes($ba)
        $ba = [System.Convert]::ToBase64String($ba)
        $h = @{Authorization=("Basic {0}" -f $ba);'Accept-Encoding'='gzip,deflate'}
        $h
    }
}

Export-ModuleMember -Function Get-AllSymbol