Office 365 - PowerShell Script To Disable Specific License Services

In this blog, we will learn how to disable specific license services in E1/E3/E4/E5 subscription using PowerShell script.

This is my first blog. To introduce myself, I have over 13 years of experience in a messaging environment and have automated my tasks using PowerShell.
 
Being an Office365 Admin, you might have entered into a difficult situation where Microsoft has rolled out new license features, like (Todo, TEAMS, Staffhub, Flow....etc.) in E1, E3, E4, or E5. And, your IT security team wants to disable this feature license for all the users immediately. This script will help you to disable that specific license without impacting other licenses.
 
The following script will help you to disable a specific service plan from each license.
 
Let me explain the script.
 
$Users = Import-Csv .\Users.csv
 
The above line gets the input from the CSV file, updates the path of the CSV file where the CSV file is located and make "users.csv" your input file. Have the header called "Email" and the header value will be Userprincipalname. 
 
 $ldo += “BPOS_S_TODO_2”,"STREAM_O365_E3"
 
This line is the important one. Mention the service plan you want to disable. For each license service plan, the Name will differ.
 
You can get the service plan by executing the below cmdlet.
  1. $t = Get-MsolUser -UserPrincipalName <UPN>  
  2. $t.Licenses[0].servicestatus  
  3. if($ld.AccountSkuId -eq “<AccountSkuId>”)  
You need to specify the AccountSKUID. You will find the accountskuid by running the below cmdlet.
 
Get-MsolAccountSKU Cmdlet in Azure Msol
 
At the end, the script will give you the following output logs.
 
Powershell transcript file. <Transcript-DD-MM-YYYY-T>
License before disabling. <Disable_LicensePlan_Before-DD-MM-YYYY-T>
License after disabling <Disable_LicensePlan_After-DD-MM-YYYY-T>
 
Script
  1. #Variable declaration  
  2. $Global: Eventlog = @()  
  3. $Global: Eventlog1 = @()  
  4. $Logfiles = @()  
  5. $currentUser = [Environment]::UserName  
  6. $TimeStamp = get - date - uformat "%d-%m-%Y-%T"  
  7. $Logfilename = "Disable_LicensePlan_Before-$($TimeStamp.Replace("",$null)).csv"  
  8. $Logfilename1 = "Disable_LicensePlan_After-$($TimeStamp.Replace("",$null)).csv"  
  9. $Trans = "Transcript-$($TimeStamp.Replace("",$null)).txt"  
  10. Start - Transcript - Path ".\$trans"###  
  11. Funtion  
  12. for Logs  
  13. Function Logwrite([String] $UPN, [String] $Loginfo) {  
  14.     $Emailaddress = $UPN  
  15.     $Loginformation = $Loginfo  
  16.     $Admin = [Environment]::UserName  
  17.     $Logstatus = $Status  
  18.     # Write - host   
  19.     $Status  
  20.     $TimeStamp = get - date - uformat "%d-%m-%Y-%T"  
  21.     $Logs = New - Object PsObject  
  22.     $Logs | add - member - membertype NoteProperty - name "TimeStamp" - value $TimeStamp  
  23.     $Logs | add - member - membertype NoteProperty - name "UserprincipalName" - value $Emailaddress  
  24.     $Logs | add - member - membertype NoteProperty - name "Log Information" - value $Loginfo  
  25.     $Logs | add - member - membertype NoteProperty - name "Script Executedby" - value $currentUser  
  26.     $Logfiles += $logs  
  27.     Return $Logfiles  
  28. }  
  29. $Users = Import - Csv.\Users.csv  
  30. Foreach($act in $users) {  
  31.         $upn = $act.Email  
  32.         # current licenses(this pulls the top level, like Office 365 Enterprise, Project Online etc.$Lic = Get - MsolUser - UserPrincipalName $upn - ErrorAction 0 If($Lic.UserPrincipalName - notlike $null) {  
  33.                 $ouserlicense = $Lic.Licenses | Select - Object - ExpandProperty ServiceStatus  
  34.                 $EnabledServices_Before = ($ouserlicense | Where - Object - Property ProvisioningStatus - EQ "Success").ServicePlan.ServiceName  
  35.                 $DisablededServices_Before = ($ouserlicense | Where - Object - Property ProvisioningStatus - EQ "Disabled").ServicePlan.ServiceName  
  36.                 $CurrentLic = $Lic.Licenses.AccountSkuId  
  37.                 $Log1 = Logwrite "$upn"  
  38.                 "Current Enabled Plan: $CurrentLic : $EnabledServices_Before"  
  39.                 $Global: Eventlog += $Log1  
  40.                 $Log2 = Logwrite "$upn"  
  41.                 "Current Disabled Plan:$CurrentLic : $DisablededServices_Before"  
  42.                 $Global: Eventlog += $Log2  
  43.                 $licensedetails = (Get - MsolUser - UserPrincipalName $upn).Licenses  
  44.                 #Using an array to pull all of my disabled plans together– and start with the new one I want to disable  
  45.                 $ldo = @()  
  46.                 $tmp = @()  
  47.                 $ldo_Disable  
  48.                 # = @()  
  49.                 $DisabledServicesNew = @()   
  50.                 <   
  51.                   #You can add the service name you want to disable below.,  
  52.                     if you want to add mulitple service add each service separated by comma line below“ SWAY”, "FLOW_O365_P1""POWERAPPS_O365_P1""TEAMS1""Deskless"  
  53.                 Following are the service plan you can see in E3 Subscription.  
  54.                 ServicePlan Description  
  55.                 -- -- -- -- -- - -- -- -- -- -- -- -- -- - MYANALYTICS_P2 MyAnalytics  
  56.                 BPOS_S_TODO_2 TODO  
  57.                 FORMS_PLAN_E3 Forms  
  58.                 STREAM_O365_E3 Stream  
  59.                 Deskless Staff Hub  
  60.                 FLOW_O365_P2 Flow  
  61.                 POWERAPPS_O365_P2 PowerApps  
  62.                 TEAMS1 Teams  
  63.                 PROJECTWORKMANAGEMENT Microsoft Planner  
  64.                 SWAY Sway  
  65.                 INTUNE_O365 Intune MDM  
  66.                 YAMMER_ENTERPRISE YAMMER  
  67.                 RMS_S_ENTERPRISE Azure Rights Management  
  68.                 OFFICESUBSCRIPTION Office Proplus  
  69.                 MCOSTANDARD Skype  
  70.                 for Business  
  71.                 SHAREPOINTWAC Office Online  
  72.                 SHAREPOINTENTERPRISE SharePoint Online  
  73.                 EXCHANGE_S_ENTERPRISE Exchange Online  
  74.                 # > $ldo += “BPOS_S_TODO_2”, "STREAM_O365_E3"  
  75.                 $ldo_Disable = $ldo  
  76.                 $Log1 = Logwrite "$upn"  
  77.                 "Selected plan to disable: $ldo"  
  78.                 $Global: Eventlog += $Log1  
  79.                 $licensedetails.Count;  
  80.                 #Making sure there are some licenses  
  81.                 if ($licensedetails.Count - gt 0) {  
  82.                     foreach($ld in $licensedetails) {  
  83.                         #AccountSkuId = Provide the AccountSKUid  
  84.                         for License E1 / E3 / E5 etc.  
  85.                         #You can get AccountSkuid using Get - MsolAccountSKU Cmdlet in Azure Msol.  
  86.                         if($ld.AccountSkuId - eq“ < AccountSkuId > ”) {  
  87.                             $UPN  
  88.                             $CurrentLic  
  89.                             $ld.ServiceStatus  
  90.                             foreach($lds in $ld.ServiceStatus) {  
  91.                                 if ($lds.ProvisioningStatus - like“ Success”) {  
  92.                                     #looking for ones that are already Enabled and adding them to my array  
  93.                                     $Temp1 = $lds.ServicePlan.ServiceName.ToString()  
  94.                                     $ldo_Success = $ldo + $Temp1  
  95.                                 }  
  96.                                 if ($lds.ProvisioningStatus - like“ Disabled”) {  
  97.                                     #looking for ones that are already disabled and adding them to my array  
  98.                                     $temp2 = $lds.ServicePlan.ServiceName.ToString()  
  99.                                     $temp2  
  100.                                     Foreach($l in $ldo) {  
  101.                                         #$l  
  102.                                         If($l - eq $temp2) {  
  103.                                             $AlreadyDisabled = $l  
  104.                                             Write - host "Plan already Disabled $l"  
  105.                                         }  
  106.                                     }  
  107.                                     if ($AlreadyDisabled - eq $temp2) {  
  108.                                         #Write - host "Plan already Disabled $l"  
  109.                                     }  
  110.                                     Else {  
  111.                                         $tmp = $tmp + $temp2  
  112.                                     }  
  113.                                 }  
  114.                             }  
  115.                             $ldo_Disable = $ldo + $tmp  
  116.                             $ldo_Disable  
  117.                             $tmp = $null  
  118.                             Write - host "Following Plan will be disabled $ldo_Disable for $upn"  
  119.                             #then create a new license option– and set the DisabledPlans to my array– Planner plus the others it finds  
  120.                             Try {  
  121.                                 $LO = New - MsolLicenseOptions - AccountSkuId“ AccountSKUID” - DisabledPlans $ldo_Disable  
  122.                                 Set - MsolUserLicense - UserPrincipalName $upn - LicenseOptions $LO - Erroraction Stop  
  123.                             }  
  124.                             Catch {  
  125.                                 $ErrorMessage = $_.Exception.Message  
  126.                                 Write - host "ERROR: $ErrorMessage" - Foreground red  
  127.                                 $Log = Logwrite "$upn"  
  128.                                 "ERROR occured during execution $ErrorMessage"  
  129.                                 $Global: Eventlog += $Log  
  130.                                 Break  
  131.                             }  
  132.                             $ldo_Disable = $null  
  133.                         }  
  134.                         Else {  
  135.                             Write - host "Error: The account $upn User License deosn't Match with AccountSKUID" - Foreground red  
  136.                             $Log = Logwrite "$upn"  
  137.                             "ERROR: The User License deosn't Match with AccountSKUID"  
  138.                             $Global: Eventlog += $Log  
  139.                         }  
  140.                     }  
  141.                 }  
  142.                 $Lic = Get - MsolUser - UserPrincipalName $upn  
  143.                 $ouserlicense = $Lic.Licenses | Select - Object - ExpandProperty ServiceStatus  
  144.                 $EnabledServices = ($ouserlicense | Where - Object - Property ProvisioningStatus - EQ "Success").ServicePlan.ServiceName  
  145.                 $DisablededServices = ($ouserlicense | Where - Object - Property ProvisioningStatus - EQ "Disabled").ServicePlan.ServiceName  
  146.                 $Log2 = Logwrite "$upn"  
  147.                 "Enabled Plan Post Change $CurrentLic :$EnabledServices"  
  148.                 $Global: Eventlog1 += $Log2  
  149.                 $Log3 = Logwrite "$upn"  
  150.                 "Disabled Plan Post Change $CurrentLic : $DisablededServices"  
  151.                 $Global: Eventlog1 += $Log3  
  152.             }  
  153.             Else {  
  154.                 Write - host "The account $upn deosn't exist in cloud" - Foreground red  
  155.                 $Log3 = Logwrite "$upn"  
  156.                 "The account deosn't exist in cloud"  
  157.                 $Global: Eventlog += $Log3  
  158.             }  
  159.         }  
  160.         If($Global: Eventlog1 - ne $null) {  
  161.             $Global: Eventlog1 | Export - csv.\$Logfilename1 - notype  
  162.         }  
  163.         If($Global: Eventlog - ne $null) {  
  164.             $Global: Eventlog | Export - csv.\$Logfilename - notype  
  165.         }  
  166.         Stop - Transcript