O365 PowerShell: Find users that have specific product license services enabled

I’m using the following article View account license and service details with Office 365 PowerShell to try to obtain a report of all users in our tenant where the product license Office 365 Enterprise E3 is assigned but with only the the service Exchange Online (Plan 2) enabled.

The article suggests this can be done with a command similar to the following:

Get-MsolUser | 
Where-Object {
   $_.isLicensed -eq $true 
   -and $_.Licenses[0].ServiceStatus[16].ProvisioningStatus -eq "Enabled"

In my case [16] being the 17th service in the list for Office 365 Enterprise E3.

There are additional lines before to set the criteria for the rest of the services as “disabled” but hopefully you get the idea however, the article also states that the index number reflects the order that the product license and service plan appears when running either of the below script blocks:


Get-MsolUser -UserPrincipalName o365.test1@tenant.com  | Format-List DisplayName,Licenses


Get-MsolUser -UserPrincipalName o365.test2@tenant.com).Licenses.ServiceStatus

The issue with the above is that many users have different combinations of plans enabled so for some, a license index of [0] would refer to a different service plan. e.g. user1 has Visio Online Plan 2 and Office 365 Enterprise E3 product licenses assigned but user2 only Office 365 Enterprise E3. Index [0] in this instance would be different making the initial script block useless in finding all users with a specific service enabled regardless of combination of product licenses assigned.

Am I missing something here?

This might help you in your search, specifically the accountskuid.


Had some more time to look into this, does this give you what you need?

$users = get-msoluser -all
$users | where { $_.licenses.servicestatus.serviceplan.servicename -like "*exchange*"}

Hi Jon,

Many thanks for spending time looking at this. This may do the job but will do some testing and let you know.


Ok, This does work but am only part way there.

Using the above will return just users with this service present in their ServicePlan list which means the product license has been assigned but I need to search for users where the ServicePlan is not only present but has a ProvisioningStatus of “Success” or “Disabled”

Example user:
ServicePlan ProvisioningStatus

BPOS_S_TODO_2 Success

I’ve changed the ServicePlan I’m trying to interrogate for these examples to something a little more uncommon for ease of testing.

I tried the following based on the above user’s assignment:

Get-MsolUser -All | 
Where-Object {
    $_.Licenses.ServiceStatus.ServicePlan.ServiceName -match "POWERFLOWSFREE" `
    -and ($_.Licenses.ServiceStatus.ProvisioningStatus -match "Disabled")

This doesn’t return the above user but think this would simply be looking for any ServicePlan in the list returned as “Disabled” anyway.

I then thought maybe it needs to be more like this:

Get-MsolUser -All | 
Where-Object {
    $_.Licenses.ServiceStatus.ServicePlan.ServiceName -match "POWERFLOWSFREE"} | `
    Where {$_.Licenses.ServiceStatus.ProvisioningStatus -match "Disabled"

Still no joy but was hoping that it would restrict the “Disabled” match search to just the specified ServicePlan.

Hopefully you can see what I’m trying to achieve? In this example I’m trying to find all users with the POWERFLOWSFREE ServicePlan with a ProvisioningStatus of “Disabled”


edited: nevermind, not enough coffee and misread.

After more coffee, and time to look at it. I pasted your code (the second example), and replaced powerflowsfree with one of my services I have, and that I know is disabled and it works fine.

I have two users that have the ServicePlan POWERFLOWSFREE present but one with it disabled. When running my second example script, both users still get returned rather than just one which obviously isn’t the desired result.

Ok, my first test I only had one service that was disabled and no one else was even licensed for that service. So I went and disabled a service on my own account and after taking forever it finally showed as disabled, then ran this command it only returned me

Get-MsolUser -all | where {$_.licenses.servicestatus.serviceplan.servicename -match "mcomeetadv_gov"} | where {$_.licenses.servicestatus.provisioningstatus -Match "Disabled"}

If I run

Get-MsolUser -all | where {$_.licenses.servicestatus.serviceplan.servicename -match "mcomeetadv_gov"} | where {$_.licenses.servicestatus.provisioningstatus -Match "Success"}

My account still shows up, because when I do this:

(get-msoluser -userprincipalname me@mydomain.com).licenses.servicestatus.provisioningstatus 

I get back


Which contains “success”, does the other account have another item set to disabled?

This should do it

$cred = get-credential

Connect-MsolService -Credential $cred

$Users = Get-Msoluser -all 

$results = ForEach ($user in $users) {
 ForEach ($license in $user.licenses.servicestatus) {
  $props = @{'UPN'=$user.userprincipalname
             'Name' = $license.ServicePlan.ServiceName
             'Status' = $license.ProvisioningStatus}

  New-Object -Type PSObject -Prop $props

$results | where {$_.status -eq "Disabled" -and $_.name -eq "powerflowsfree"}

Wow, thanks for the thought and effort you’ve put into this. I’m on holiday today but will try this out on Monday and let you know how I get on.


Apologies, I thought this site was down as am getting a “503 Service Unavailable” page from my desktop computer but obviously isn’t.

Wow that’s certainly given me the information I require and can build on this. I think I need to go over this to make sure I understand all aspects but think I understand most parts.

Thank you so much again for the time and effort you’ve put into helping me here. I’d like to say I could help you in return but as you can see, my skills aren’t quite there yet :wink: