Table of Contents
Get-AzContext missing a ‘subscription’ while using Set-AzContext
We use the command below as standard in our scripts, but I have also discovered that this is not entirely useful.
$null = Get-AzContext -ListAvailable | Where-Object {$_.Name -match $SubscriptionName} | Set-AzContext
But for more about that you should go to another section on this blog (see the Table of Contents).
You probably found this blog cause of an error message:
Set-AzContext: Please provide a valid tenant or a valid subscription.
$SubscriptionName = 'MSDN_2'
Set-AzContext -SubscriptionName $SubscriptionName
Set-AzContext: Please provide a valid tenant or a valid subscription.
I have selected the Azure contexts that I tried to select via Set-AzContext
more than once, so it is strange that I suddenly couldn’t do this anymore and that the Context itself disappeared from the list that you can see via Get-AzContext.
You can add it again via the steps below.
Let’s re-add the subscription to your AzContext!
To return to the Set-AzContext
that cannot find a tenant or subscription, the subscription is no longer listed in my Get-AzContext -ListAvailable
.
Get-AzContext -ListAvailable
Name Account
------- -------
MSDN (00000000-0000-0000-0000-0000000) [email protected]
But Get-AzSubscription
still showed the subscription I need:
Get-AzSubscription
Name Id
---- --
MSDN 00000000-0000-0000-0000-000000000000
MSDN_2 00000000-0000-0000-0000-000000000000
By selecting a subscription in the current context with Select-AzSubscription
, you remain in the context you are logged in and the subscription is adjusted based on the context itself.
By running the command below:
Select-AzSubscription -SubscriptionName $SubscriptionName
Unfortunately, there is not much documentation about Select-AzSubscription
and it looks like as if Set-AzContext
is the new cmdlet you should use.
We used Select-AzureSubscription
from the previous Azure module version which is legacy nowadays.
A context is shown again with the subscription:
Get-AzContext -ListAvailable
Name Account
------- -------
MSDN (00000000-0000-0000-0000-0000000) [email protected]
MSDN_2 (00000000-0000-0000-0000-000... [email protected]
Yup, that should be it!
Difference between Set-AzSubscription and Set-AzContext
In Azure PowerShell, both Set-AzContext
and Set-AzSubscription
are used to set the current context or subscription, but they serve different purposes:
Set-AzContext
:
- Purpose: Changes the current context in Azure PowerShell.
- Context: In Azure, a context is a combination of a subscription, tenant, and environment. It represents the identity and environment under which Azure PowerShell commands are executed.
- Usage:
powershell Set-AzContext -SubscriptionId <SubscriptionName>
- Note: This cmdlet allows you to set the entire context, including the subscription, tenant, and environment.
Select-AzSubscription
:
- Purpose: Changes the current subscription.
- Subscription: In Azure, a subscription is a logical container used to provision and manage resources. Each subscription can have its own billing, resource limits, and policies.
- Usage:
powershell Select-AzSubscription -SubscriptionName <SubscriptionName>
- Note: This cmdlet specifically sets the active subscription without changing the other aspects of the context.
In summary:
- If you want to change the entire context, including the subscription, tenant, and environment, you use
Set-AzContext
. - If you only want to switch the active subscription within the current context, you use
Select-AzSubscription
.
It’s worth noting that if you set the subscription using Select-AzSubscription
, it does not change the Azure environment or tenant associated with the context; it only changes the active subscription within the current context.
If you need to switch the entire context, including the environment and tenant, you should use Set-AzContext
.
For more about Azure Contexts, I’d like to refer you to:
Azure contexts and sign-in credentials | Microsoft Learn
Why I didn’t get an error using Set-AzContext after pipeline output
We mainly used the cmdlet below in our runbooks.
We first check whether there is an existing context, and if so, whether it matches the subscription we need and then select the correct Context via Set-AzContext
.
$null = Get-AzContext -ListAvailable | Where-Object {$_.Name -match $SubscriptionName} | Set-AzContext
When we analyze the above, it becomes clear to me why this is not correct.
What we do first is check if there are any existing contexts. A context is created when logging in for the first time via Connect-AzAccount
because it simply selects the first subscription with the default settings.
As a result, there is always 1 context.
The Azure Automation environments we use only have access to the subscription they are in, so the subscription name always matches the context that selects the first one.
But why doesn’t this work on our local devices (development), but it seems to work, causing you to get strange error messages in your scripts? Why does it not error out to: Set-AzContext: Please provide a valid tenant or a valid subscription. or Set-AzContext: Cannot bind argument to parameter ‘context’ because it is null?
The Where-Object
contains no output, but it does create a PSObject:
$WhereObject = (Get-AzContext -ListAvailable | Where-Object {$_.Name -eq $SubscriptionName})
$WhereObject.PSObject
Members : {ToString, GetType, Equals, GetHashCode}
Properties : {}
Methods : {ToString, GetType, Equals, GetHashCode}
ImmediateBaseObject :
BaseObject :
TypeNames : {System.Management.Automation.PSCustomObject, System.Object}
Instead of using Get-AzContext -ListAvailable
we could use $null
and it would still work.
So, why we do not get an error I’m not 100% sure, but it has something to do with the Where-Object as things like this also ‘work’ even without an error message:
$null | Where-Object {$_.Name -eq "MyName"} | Set-Service -ErrorAction Stop
So, never use a Where-Object
with things like this as you do not know if it did something.
Another reason not to use pipelines in commands.
Use cases I can think of are more of the type ‘if not all of them are $true
, then set them $true
‘.