Obtaining Licenses and Service Status using MSOnline PowerShell Module

Interestingly enough, I was being asked on how they could obtain O365 Licenses information for an enterprise and how they could get all the Services status allocated to per User.

It is no surprise to me after all, IT auditing is a usual practice in any organization and I responded with PowerShell from a Microsoft article – View account license and service details with Office 365 PowerShell that demonstrate it.

Sadly, to discovered that they copied the code below from the article and execute with it to discovered that the information does not look correct because they have more provisioned service in service that they do not have license allocated or service that they have licenses which are not reported on the HTML.

# PowerShell Code Snippet from https://technet.microsoft.com/en-us/library/dn771771.aspx
Get-MsolUser | `
Select-Object `
DisplayName, `
@{Name="Sway";Expression={$_.Licenses[0].ServiceStatus[0].ProvisioningStatus}}, `
@{Name="MDM";Expression={$_.Licenses[0].ServiceStatus[1].ProvisioningStatus}}, `
@{Name="Yammer";Expression={$_.Licenses[0].ServiceStatus[2].ProvisioningStatus}}, `
@{Name="AD RMS";Expression={$_.Licenses[0].ServiceStatus[3].ProvisioningStatus}}, `
@{Name="OfficePro";Expression={$_.Licenses[0].ServiceStatus[4].ProvisioningStatus}}, `
@{Name="Skype";Expression={$_.Licenses[0].ServiceStatus[5].ProvisioningStatus}}, `
@{Name="OfficeWeb";Expression={$_.Licenses[0].ServiceStatus[6].ProvisioningStatus}}, `
@{Name="SharePoint";Expression={$_.Licenses[0].ServiceStatus[7].ProvisioningStatus}}, `
@{Name="Exchange";Expression={$_.Licenses[0].ServiceStatus[8].ProvisioningStatus}} | `
ConvertTo-Html > "C:\My Documents\Service Info.html"

That’s bizarre and I went to discovered the example provided in the article has hardcoded the service against the array numeration. I logged to a few other O365 accounts to double check the array numeration and found that it is dynamic based on your subscription. Great, that doesn’t work and begin to explore how we can constantly and accurately get the report without hardcoding.

Ok. Let’s try this out. Firstly, we will need to install the MSOnline PowerShell Module on the PowerShell console.

# Install MSOnline PowerShell Module
Install-Module `
-Name MSOnline ;

Next, we will need to establish a connection to the O365 service using the Connect-MsolService cmdlet with your O365 credential.

# Connect to MSOnline Service
Connect-MsolService `
-Credential (Get-Credential) ;

Once we have established connectivity, let us take a look at all the O365 Subscription SKU, Services and their Provisioning Status using the PowerShell code below.

# Get MSOL Account SKU and associated Services
Get-MsolAccountSku | ForEach-Object {
Write-Host "`n"$_.AccountSkuId ;
$_.ServiceStatus | ForEach-Object {
Write-Host "`t`t+" $_.ServicePlan.ServiceName [ $_.ProvisioningStatus ] ;
} ;
} ;

Now, you get a bird eye view of all the Services and Provisioning Status aligned with the Subscription SKU.

If full detail is what you are looking for, try the PowerShell code below.

# Get MSOL Account SKU, Consumption and associated Services in detail
Get-MsolAccountSku | ForEach-Object {
Write-Host "`n"$_.AccountSkuId ;
Write-Host "`t* SKUId:"$_.SkuId ;
Write-Host "`t* ActiveUnits:"$_.ActiveUnits ;
Write-Host "`t* WarningUnits:"$_.WarningUnits ;
Write-Host "`t* ConsumedUnits:"$_.ConsumedUnits ;
Write-Host "`t* LockedOutUnits:"$_.LockedOutUnits ;
$_.ServiceStatus | ForEach-Object {
Write-Host "`t`t+" $_.ServicePlan.ServiceName ;
Write-Host "`t`t`t- ServicePlanId:" $_.ServicePlan.ServicePlanId ;
Write-Host "`t`t`t- ServiceType:" $_.ServicePlan.ServiceType ;
Write-Host "`t`t`t- ProvisioningStatus:" $_.ProvisioningStatus ;
} ;
} ;

But we need to know each individual user is allocated to which service and their service provisioning status from O365. In order to find out those information, we will need to use the Get-MsolUser cmdlet and specify UserPrincipalName using the -UserPrincipalName parameter instead of the -All parameter.

In the example below, we will demonstrate how we can generate all users allocated services and their provisioning status for IT license auditing compliance.

# Get all O365 Users Service Status
Get-MsolUser -All | ForEach-Object {

# Construct an O365 User Service Status PSObject Properties
$UserO365ServiceStatus = New-Object PSObject `
-Property @{
"DisplayName" = "" ;
"SignInName" = "" ;
"UserPrincipalName" = "" ;
"Licenses" = "" ;
} ;

# Construct an O365 User Service Status PSObject Properties with
#  all the Service Name that are available
Get-MsolAccountSku | `
ForEach-Object {
$_.ServiceStatus | `
ForEach-Object {
$UserO365ServiceStatus | `
Add-Member `
-MemberType Noteproperty `
-Name $_.ServicePlan.ServiceName `
-Value "" `
-Force ;
} ;
} ;

$UserO365ServiceStatus.DisplayName = `
[String] $_.DisplayName ;

$UserO365ServiceStatus.SignInName = `
[String] $_.SignInName ;

$UserO365ServiceStatus.UserPrincipalName = `
[String] $_.UserPrincipalName ;

if($_.Licenses -ne (Out-Null)) {
$UserO365ServiceStatus.Licenses = `
[String] $_.Licenses.AccountSku.SkuPartNumber -replace " ","," ;

$_.Licenses | ForEach-Object {
$_.ServiceStatus | ForEach-Object {

$UserO365ServiceStatus.$($_.ServicePlan.ServiceName) = `
[String] $_.ProvisioningStatus ;
} ;
} ;
} ;

Return $UserO365ServiceStatus  ;
} | ConvertTo-Html > "C:\O365_User_Service_Status.html" ;

With the command above, it will convert the data to a HTML file using the ConvertTo-Html cmdlet but you can also use Out-GridView cmdlet for viewing or Export-Csv cmdlet to output into CSV file format for Excel. That’s it.