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 } |