Public/Helpers/Select-AzureContext.ps1
function Select-AzureContext { [CmdletBinding(DefaultParameterSetName = 'List')] param ( [Parameter(Mandatory = $false, ParameterSetName = 'List')] [switch]$List, [Parameter(Mandatory = $false, ParameterSetName = 'Switch', ValueFromPipelineByPropertyName = $true)] [ArgumentCompleter({ param($Command, $Parameter, $WordToComplete, $CommandAst, $FakeBoundParams) $contexts = Get-AzContext -ListAvailable $index = 1 $contextCompletions = @() $contexts | ForEach-Object { $userName = $_.Account.Id.Split('@')[0] $subscriptionName = $_.Subscription.Name -replace '^\s+', '' $indexedName = "$index - [$userName] $subscriptionName" $contextCompletions += "$indexedName" $index++ } if ($WordToComplete) { $contextCompletions | Where-Object { $_ -like "*$WordToComplete*" } } else { $contextCompletions } })] [Alias("Context", "Name")] [string]$SwitchTo, [Parameter(Mandatory = $false, ParameterSetName = 'Switch')] [switch]$Force, [Parameter(Mandatory = $false, ParameterSetName = 'Switch')] [switch]$ShowDetails ) begin { Write-Verbose "Starting function $($MyInvocation.MyCommand.Name)" $MyInvocation.MyCommand.Name | Invoke-BlackCat } process { try { $contexts = Get-AzContext -ListAvailable $currentContext = Get-AzContext if ($PSCmdlet.ParameterSetName -eq 'List' -or !$SwitchTo) { $index = 1 $contextList = $contexts | ForEach-Object { $userName = $_.Account.Id.Split('@')[0] $subscriptionName = $_.Subscription.Name -replace '^\s+', '' $isCurrent = ($_.Id -eq $currentContext.Id) $currentMarker = if ($isCurrent) { "* " } else { " " } [PSCustomObject]@{ ' ' = $currentMarker Index = $index++ Account = $_.Account.Id Subscription = $subscriptionName Tenant = $_.Tenant.Id.Substring(0, 32) + "..." # Shortened for readability Environment = $_.Environment.Name IsDefault = $_.IsDefault } } Write-Host "Available Azure Contexts (* indicates current context):" -ForegroundColor Cyan $contextList | Format-Table -AutoSize Write-Host "To switch contexts, use: Select-AzureContext -SwitchTo <Index>" -ForegroundColor DarkCyan return } else { # First, try to find an exact match $targetContext = $null # Check if SwitchTo is an index number if ($SwitchTo -match '^\d+$') { $indexNumber = [int]$SwitchTo if ($indexNumber -gt 0 -and $indexNumber -le $contexts.Count) { $targetContext = $contexts[$indexNumber - 1] } else { Write-Message -FunctionName $($MyInvocation.MyCommand.Name) -Message "Index '$SwitchTo' is out of range (1-$($contexts.Count))" -Severity 'Error' return } } else { $targetContext = $contexts | Where-Object { $userName = $_.Account.Id.Split('@')[0] $subscriptionName = $_.Subscription.Name -replace '^\s+', '' $friendlyName = """[$userName] $subscriptionName""" # Check for exact matches first $_.Name -eq $SwitchTo -or $_.Account.Id -eq $SwitchTo -or $_.Subscription.Name -eq $SwitchTo -or $friendlyName -eq $SwitchTo -or $userName -eq $SwitchTo } if (-not $targetContext) { $targetContext = $contexts | Where-Object { $userName = $_.Account.Id.Split('@')[0] $_.Name -like "*$SwitchTo*" -or $_.Account.Id -like "*$SwitchTo*" -or $_.Subscription.Name -like "*$SwitchTo*" -or $userName -like "*$SwitchTo*" } | Select-Object -First 1 } } if ($targetContext) { if ($targetContext -is [array] -and $targetContext.Count -gt 1) { Write-Host "Multiple contexts matched your criteria. Please be more specific:" -ForegroundColor Yellow $index = 1 $targetContext | ForEach-Object { $userName = $_.Account.Id.Split('@')[0] $subscriptionName = $_.Subscription.Name -replace '^\s+', '' Write-Host "$index - [$userName] $subscriptionName" -ForegroundColor Yellow $index++ } return } Select-AzContext -InputObject $targetContext $MyInvocation.MyCommand.Name | Invoke-BlackCat -ChangeProfile $currentContext = Get-AzContext $userName = $currentContext.Account.Id.Split('@')[0] $subscriptionName = $currentContext.Subscription.Name -replace '^\s+', '' Write-Message -FunctionName $($MyInvocation.MyCommand.Name) -Message "Switched to context: [$userName] $subscriptionName" -Severity 'Information' # Show detailed info if requested if ($ShowDetails) { $userDetails = ConvertFrom-JWT -Base64JWT $script:authHeader.Values [PSCustomObject]@{ Context = "[$userName] $subscriptionName" FirstName = $userDetails.FirstName LastName = $userDetails.LastName Account = $currentContext.Account.Id ObjectId = $userDetails.ObjectId Subscription = $currentContext.Subscription.Name SubscriptionId = $currentContext.Subscription.Id Tenant = $currentContext.Tenant.Id Environment = $currentContext.Environment.Name Roles = $userDetails.Roles } } else { # Just show minimal info [PSCustomObject]@{ Context = "[$userName] $subscriptionName" Account = $currentContext.Account.Id SubscriptionId = $currentContext.Subscription.Id Tenant = $currentContext.Tenant.Id } } } else { Write-Message -FunctionName $($MyInvocation.MyCommand.Name) -Message "No context found matching '$SwitchTo'" -Severity 'Error' } } } catch { Write-Message -FunctionName $($MyInvocation.MyCommand.Name) -Message $($_.Exception.Message) -Severity 'Error' } } <# .SYNOPSIS Lists and selects Azure PowerShell contexts. .DESCRIPTION Lists available Azure contexts and allows switching between them using friendly names, index numbers, subscription names, or usernames. Provides tab completion and partial name matching for easier context selection. .PARAMETER List Switch parameter to list all available contexts (default behavior). .PARAMETER SwitchTo Specifies the context to switch to. Can be: - Index number (as displayed in the list) Supports tab completion and partial name matching. .PARAMETER ShowDetails Shows detailed information about the selected context after switching. .EXAMPLE Select-AzureContext Lists all available Azure contexts. .EXAMPLE Select-AzureContext -SwitchTo "MySubscription" Switches to the context with the specified subscription name. .EXAMPLE Select-AzureContext -SwitchTo 2 Switches to the context at index 2 in the list. .EXAMPLE Select-AzureContext -SwitchTo "prod" -Force Switches to the context matching "prod" without confirmation. .EXAMPLE Select-AzureContext -SwitchTo "john" -ShowDetails Switches to the context for user "john" and shows detailed information. .NOTES Author: Rogier Dijkman #> } # Create an alias for backward compatibility New-Alias -Name Switch-Context -Value Select-AzureContext -Description "Alias for backward compatibility" -Force Export-ModuleMember -Function Select-AzureContext -Alias Switch-Context |