functions/bccontainerhelper/Get-BcContainerHelperInstaller.ps1

function Get-BcContainerHelperInstaller {
<#
.SYNOPSIS
Retrieves the path to a usable BcContainerHelper.ps1 script, either from local installation or by downloading it.
 
.DESCRIPTION
This function returns the path to a BcContainerHelper.ps1 script file based on the specified source:
- 'installed': Uses the most recently installed local version under Program Files.
- 'latest': Downloads the latest version from a specified URL (default IBS blob storage).
- 'local': Uses a specific local folder path (if it contains BcContainerHelper.ps1), or attempts to download if invalid.
 
If downloading is required, the script is extracted from a ZIP archive into a temporary folder. A mutex is used to prevent race conditions when multiple processes invoke the function simultaneously.
 
.PARAMETER Source
The source of the BcContainerHelper to use.
Valid values:
- 'installed': Uses the newest locally installed version.
- 'latest': Downloads the latest version from a URL.
- 'local': Uses a local folder path, or falls back to download if invalid.
 
.PARAMETER BcContainerHelperVersion
The URL to the BcContainerHelper ZIP archive (only used when Source is 'latest' or 'local' path is invalid).
Defaults to the IBS-hosted public download location.
 
.EXAMPLE
Get-BcContainerHelperInstaller -Source 'installed'
 
Returns the path to the most recently installed local BcContainerHelper.ps1 script.
 
.EXAMPLE
Get-BcContainerHelperInstaller -Source 'latest'
 
Downloads the latest version of BcContainerHelper from the default IBS storage and returns the extracted script path.
 
.EXAMPLE
Get-BcContainerHelperInstaller -Source 'local' -BcContainerHelperVersion "C:\Tools\BcContainerHelper"
 
Uses the local folder at C:\Tools\BcContainerHelper, if it contains BcContainerHelper.ps1; otherwise downloads latest.
 
.OUTPUTS
System.String
 
The full file path to the BcContainerHelper.ps1 script.
 
.NOTES
Author: Jascha Vincke
Date: 2025-06-14
#>


    [CmdletBinding()]
    param(
        [ValidateSet('installed', 'latest', 'local')]
        [string]$Source = 'latest',

        [string]$BcContainerHelperVersion = "https://jviteuwestcool.blob.core.windows.net/bccontainerhelper/latest.zip"
    )

    $downloadAndInstall = $false
    $path = $null

    switch ($Source) {
        'installed' {
            Write-Information "Using the most recent locally installed BcContainerHelper version." -InformationAction Continue

            $basePath = Join-Path -Path $env:ProgramFiles -ChildPath "WindowsPowerShell\Modules\BcContainerHelper"

            if (-not (Test-Path -Path $basePath)) {
                Write-Warning "Source 'installed' was specified, but BcContainerHelper is not installed. Falling back to download."
                $downloadAndInstall = $true
            } else {
                $latestLocal = Get-NewestItem -Path $basePath -Type Directory -First 1
                if ($latestLocal) {
                    $path = $latestLocal.FullName
                } else {
                    Write-Warning "No valid version found in local BcContainerHelper folder. Falling back to download."
                    $downloadAndInstall = $true
                }
            }
        }

        'latest' {
            Write-Information "Using the latest BcContainerHelper version from IBS storage." -InformationAction Continue

            if (-not ($BcContainerHelperVersion -like 'https://*')) {
                $BcContainerHelperVersion = "https://jviteuwestcool.blob.core.windows.net/bccontainerhelper/latest.zip"
            }

            $downloadAndInstall = $true
        }

        'local' {
            Write-Information "Using a specific local path to BcContainerHelper: $BcContainerHelperVersion" -InformationAction Continue

            $path = $BcContainerHelperVersion

            if (
                -not (Test-Path -Path $path) -or
                -not (Test-Path -Path (Join-Path -Path $path -ChildPath "BcContainerHelper.ps1"))
            ) {
                Write-Warning "Local path '$path' is invalid or does not contain BcContainerHelper.ps1. Attempting to download from URL..."
                $downloadAndInstall = $true
            }
        }
    }

    if ($downloadAndInstall) {
        $path = Join-Path -Path $env:TEMP -ChildPath ([guid]::NewGuid().ToString())

        $mutexName = "bcContainerHelper"
        $mutex = New-Object -TypeName System.Threading.Mutex($false, $mutexName)

        try {
            try {
                $null = $mutex.WaitOne()
            } catch {
                Write-Warning "Failed to acquire mutex lock. Continuing anyway..."
            }

            if (-not (Test-Path -Path $path)) {
                $tempZipName = Join-Path -Path $env:TEMP -ChildPath ([guid]::NewGuid().ToString())
                Write-Information "Downloading $BcContainerHelperVersion..." -InformationAction Continue

                (New-Object -TypeName System.Net.WebClient).DownloadFile($BcContainerHelperVersion, "$tempZipName.zip")

                Expand-Archive -Path "$tempZipName.zip" -DestinationPath $tempZipName -Force
                Remove-Item -Path "$tempZipName.zip" -Force

                $folder = Get-ChildItem -Path $tempZipName -Directory | Select-Object -First 1
                if ($folder) {
                    [System.IO.Directory]::Move($folder.FullName, $path)
                } else {
                    throw "Unable to locate extracted folder in '$tempZipName'."
                }
            }
        }
        finally {
            $mutex.ReleaseMutex()
        }
    }

    $scriptPath = Join-Path -Path $path -ChildPath 'BcContainerHelper.ps1'

    if (-not (Test-Path -Path $scriptPath)) {
        throw "BcContainerHelper.ps1 not found at '$scriptPath'."
    }

    return $scriptPath
}