Thursday, December 15, 2016

Unable to delete contacts from Outlook Contacts folder (Skype for Business or Lync)


You want to delete contacts from Office 365 Outlook folder: "Skype for Business Contacts" or "Lync Contacts". You get error:
"You cannot make changes to contents of this read-only folder"


Go to the "light" Exchange Online mode: and delete contacts.

Wednesday, December 14, 2016

Easy way to determine UEFI or Legacy BIOS from PowerShell

PowerShell script which determines the underlying system firmware (BIOS) type - either UEFI or Legacy BIOS:

if (Test-Path $env:windir\Panther\setupact.log) {(Select-String 'Detected boot environment' -Path "$env:windir\Panther\setupact.log"  -AllMatches).line -replace '.*:\s+'else {if (Test-Path HKLM:\System\CurrentControlSet\control\SecureBoot\State) {"UEFI"} else {"BIOS"}}

PowerShell script which determines EFI partition:

Get-WmiObject  -query 'Select * from Win32_DiskPartition Where Type = "GPT: System"' | select Name, Index, Bootable, BootPartition,PrimaryPartition, @{n="SizeInMB";e={$_.Size/1MB}}

You may need this information for VMware/Physical machines to Azure with Azure Site Recovery scenario (or even Hyper-V Gen 2 VMs where you don't have actual access to Hyper-V itself, ex. 3rd party IaaS provider). As of today UEFI partitions are not supported in these scenarios and you will end with
ERROR ID 78006
The requested operation did not complete. 
Provider error code: 95185 Provider error message: Protection could not be enabled. Provider error possible causes: Enable protection failed for the source disks {GUID} on the source machine <Hostname> (IP Address). UEFI partitions are not supported. Provider error recommended action: UEFI partitions are not supported. See for the pre-requisites.
Check the provider error for more details.
Resolve the issue as recommended in the provider error details.

Saturday, November 5, 2016

Cert Exam Prep Materials: 70-740, 70-741, 70-742, 70-743: MCSA: Windows Server 2016

These exams are required for the new MCSA: Windows Server 2016 certification: 70-740, 70-741, 70-742 (or just 70-743 for upgrade from MCSA: Windows Server 2008 or MCSA: Windows Server 2012 R2)

Cert Exam Prep: Exam 70-740: Installation, Storage, and Compute

This Certification Exam Prep session is designed for people experienced with Microsoft Windows Server who are interested in taking the 70-740 exam or the 70-743 exam.


Cert Exam Prep: Exam 70-741: Networking with Windows Server 2016

This Certification Exam Prep session is designed for people experienced with Microsoft Windows Server who are interested in taking the 70-741 exam or the 70-743 exam.


Cert Exam Prep: Exam 70-742: Identity with Windows Server 2016

This Certification Exam Prep session is designed for people experienced with Microsoft Windows Server who are interested in taking the 70-742 exam or the 70-743 exam.



Friday, November 4, 2016

"Office 365 mailbox" creation link is missing from Exchange Admin Center (EAC) UI


You install Microsoft Exchange Server for "Synchronized Identity" management only.

Ex.: after 3rd party mail server migration (Kerio Mailserver, Lotus Notes, CommunigatePro, etc.) and you have existing Active Directory configured with AAD Connect. Microsoft Exchange Server (EAC or EMS) is the only supported way for "Synchronized Identity" management with AAD Connect.
You try to create new "Office 365 mailbox" via EAC UI and with "Organization Management" permissions but no "Office 365 mailbox" button appears.

Notwithstanding this fact, you can create Office 365 mailbox via Exchange Management Shell (New-RemoteMailbox)


Install the Hybrid license key (free for Office 365 customers) on the Exchange Server (there is no need to configure full Exchange Server Hybrid however)

To obtain a Hybrid Edition product key for your Exchange 2010 SP3 or 2013 or 2016 server, go to the Exchange hybrid product key distribution wizard using Office 365 Global Admin credentials.

Apply obtained key to your Hybrid Exchange Server:

Set-ExchangeServer -Identity HybServer01 -ProductKey XXXXX-XXXXX-XXXXX-XXXXX-XXXXX
Get-Service -Name MSExchangeIS -ComputerName HybServer01 | Restart-Service

Add remote domain:

New-RemoteDomain -Name "Online Domain" -DomainName ""
Set-RemoteDomain -Identity "Online Domain" -TargetDeliveryDomain $true

Refresh browser session and "Office 365 mailbox" UI button will appear in EAC UI. Restart Exchange server if button is still missing

Another reason why you could have the button missing is misconfigured RBAC.


Tuesday, October 25, 2016

Exchange Cutover migration batch error "Couldn‎'t find object "/o=NT5..."


You migrate mailboxes to Exchange Online using Exchange Cutover scenario. You start the Cutover migration batch, and get following error for some users:
Error: ProvisioningFailedException: Failed to update one of the recipient properties. --> Couldn‎'t find object "/o=NT5/ou=9b22534a504ae64e826374ec36c06562/cn=a3b7c64174213644975404f83e27205a". Please make sure that it was spelled correctly or specify a different object.
Unfortunately, the error message and the report gives no further details about exactly which recipient's property failed to update. The synchronization of affected mailboxes cannot be successfully completed due to this error.


In my case affected on-premises mailbox account had "Send-On-Behalf" permissions or the "Manager" field which pointed to disabled Active Directory account (ex. people who are no longer working for the company).  

The solution is to clear this stale account from the properties of affected mailbox. Then stop and re-run the Migration Cutover batch again.
Paul Cunningham provided few PowerShell scripts which allow to find such stale objects:

Friday, September 23, 2016

The target mailbox doesn't have an SMTP proxy matching ''


To handle mail flow in an Exchange Hybrid scenario every mailbox needs an e-mail routing address matching the tenant e-mail domain name (

Hybrid Configuration Wizard (HCW) adds this new configuration automatically and the new e-mail address on every mailbox which has the e-mail address policy enabled on it ("Automatically update email addresses based on the email address policy applied to this recipient" checkbox). Challenge appears when a lot of mailboxes within Exchange organization don't have the e-mail address policy enabled. I hope Exchange HCW development team will fix this behavior soon.

When you try to move mailboxes from your on-premises environment to Exchange Online, you receive the following error message without smtp alias:
The target mailbox doesn't have an SMTP proxy matching '<domain>'

Following simple PowerShell script will automatically add the new e-mail address in format  of "" on every mailbox within your Exchange Organization which have disabled the e-mail address policy.

$mailboxes=Get-Mailbox -ResultSize Unlimited | where {!$_.EmailAddressPolicyEnabled} | select DisplayName, Alias, PrimarySmtpAddress, Identity

foreach ($mailbox in $mailboxes) {

$email=$alias + “”
Set-mailbox $mailbox.Identity -EmailAddresses @{add=$email}

$mailboxes | Export-Csv -Path "$env:USERPROFILE\Desktop\mailboxes_changed.csv"

Office 365 users are missing in Dynamics 365 for Business (CRM Online)


Office 365 users have not been synchronized to Dynamics CRM Online after you have assigned them a CRM Online licence then you should check the following.


In the Office 365 portal under the admin menu select the CRM option.

From there select the "Edit Settings" for the CRM instance you are having problems with. Check that the "Instance Security Group" is not set otherwise only users in the assigned group will be allowed access to that CRM instance. If there is any other value like "<none>" you may need to clear and save settings it before users will appear in CRM Online

Thursday, July 21, 2016

Configure OAuth between Skype for Business Server and Exchange Online

This PowerShell script (Author: Aaron Marks) configures OAuth between Skype for Business Server and Exchange Online.

    Aaron Marks
    Version 2.0, 5/26/2016
    Configure Oauth between Exchange Online and Skype for Business Server.
        - Must be ran from Skype4B Server
        - Run from Elevated AAD PowerShell
        - MS Online Service Sign-in Assistant RTW:  
        - AAD PowerShell:  
    Special thanks to Christian Burke for providing the  
    commands used to assemble this script:
    And, Thanks to @PatRichard for writing the part to export the OAuth certificate.
    Revision History
    1.0     Initial release
    2.0     Auto-export of OAuth Cert
    Web External url from Skype for Business Front End Pool.
    .\Configure-OAuth_ExOn_SfB_Server.ps1 -WebExt ""  
    [Parameter(Mandatory=$True, ParameterSetName="Default")]
) #Param
Process {
    $CertPath = "C:\OAuth-SfB-EXO.cer"
    $Thumbprint = (Get-CsCertificate -Type OAuthTokenIssuer).Thumbprint
    $OAuthCert = Get-ChildItem -Path Cert:\LocalMachine\My\$Thumbprint
    Export-Certificate -Cert $OAuthCert -FilePath $CertPath -Type CERT
    # Script
    Import-Module LyncOnlineConnector
    # Logging into SfB Online
    Write-Output "Logging into SfB Online"
    $cred = Get-Credential
    $CSSession = New-CsOnlineSession -Credential $cred  
    Import-PSSession $CSSession -AllowClobber  
    # Clean up Old Entries if necessary
    Write-Output "Clean up Old Entries if necessary"
    If ( (Get-CsOauthServer).Identity -match "microsoft.sts") {
        Write-Output "Removing existing microsoft.sts OauthServer"
        Remove-CsOauthServer -Identity microsoft.sts
    If ( (Get-CsPartnerApplication).Identity -match "") {
        Write-Output "Removing existing PartnerApplication"
        Remove-CsPartnerApplication -Identity
    # Create New OAuth Server
    Write-Output "Create New OAuth Server"
    $TenantId = (Get-CsTenant).TenantId
    $metadataurl = "" `
    + "$TenantId" + "/metadata/json/1"
    New-CsOAuthServer -Identity microsoft.sts -metadataurl $metadataurl
    # Create New Partner Application
    Write-Output "Create New Partner Application"
    New-CsPartnerApplication -Identity `
    -ApplicationIdentifier 00000002-0000-0ff1-ce00-000000000000 `
    -ApplicationTrustLevel Full -UseOAuthServer
    #Set-CsOAuthConfiguration -ServiceName 00000004-0000-0ff1-ce00-000000000000
    # Elevate the SfB PowerShell  
    Write-Output "Elevate the SfB PowerShell"
    Import-Module MSOnlineExtended
    Connect-MsolService -Credential $cred
    # Upload your OAuth Certificate
    Write-Output "Upload your OAuth Certificate"
    $certificate =  
    New-Object System.Security.Cryptography.X509Certificates.X509Certificate
    $binaryValue = $certificate.GetRawCertData()  
    $credentialsValue = [System.Convert]::ToBase64String($binaryValue)  
    New-MsolServicePrincipalCredential `
    -AppPrincipalId 00000004-0000-0ff1-ce00-000000000000 `
    -Type Asymmetric -Usage Verify -Value $credentialsValue  
    Set-MSOLServicePrincipal -AppPrincipalID `
    00000002-0000-0ff1-ce00-000000000000 -AccountEnabled $true  
    # Add Your Lync External Web Services Name
    Write-Output "Add Your Lync External Web Services Name"
    $lyncSP = Get-MSOLServicePrincipal -AppPrincipalID `
    $WebExtSpn = "00000004-0000-0ff1-ce00-000000000000/" + "$WebExt"
    Set-MSOLServicePrincipal -AppPrincipalID `
    00000004-0000-0ff1-ce00-000000000000 `
    -ServicePrincipalNames $lyncSP.ServicePrincipalNames  
    Remove-PSSession $CSSession
} #Process


Thursday, June 30, 2016

Juniper EX4550: Convert SCOM Network Device from GENERIC to CERTIFIED with Extended Monitoring Capability


There is some way how to get CERTIFIED status and extended monitoring capabilities in SCOM 2012+ for non-certified GENERIC network device Juniper EX4550 using just Notepad and no XML MP (Management Pack) development effort. 

I guess following method would work for another GENERIC network device that you might have. Just take an idea of my approach. 

Juniper EX4550:
Note: Although MS published list for SCOM 2012 and SCOM 2012R2/2016 neither contains whole device list which SCOM will discover as "Certified" and with extended monitoring capabilities. Refer to my previous article if you want to get full list of "Certified" devices for your particular SCOM environment.
The idea is to find similar device from the Juniper which is already "Certified" and to use its configuration for SCOM Generic network device.


Juniper EX4550-48T 
(System OID: .

Step 1. After initial SCOM network discovery you have something similar to the picture below:

  • cannot determine Model, Vendor;
  • has GENERIC Certification status for the device
  • there is no CPU/RAM/Network extended monitoring for the device
  • make a note it has System Object ID: .
Step 2. Juniper EX series contains of EX2200, EX3300, EX4200, EX4500 and EX4550 models. Each device has its unique system OID and characteristics. However, the whole device family is managed by the same OS called "JunOS" and it makes me think they have similar SNMP MIBs (or maybe even the same), could be monitored by SCOM (or any SNMP monitoring software) in the same way using the same SNMP OID trees and counters.

Step 3There is the folder "C:\Program Files\Microsoft System Center 2012 R2\Operations Manager\Server\NetworkMonitoring\conf\discovery" (for SCOM 2012R2) on SCOM Management servers which contains a lot of specific vendor files with prefix "oid2type" and file extension ".conf". Our focus will be on "oid2type_Juniper.conf" file.
Make a copy of this file for backup purposes.

Step 4. Open oid2type_Juniper.conf file with Notepad or with your favorite text editor (you should run Notepad as Administrator and navigate to folder path mentioned in Step 3) and search for string "EX4". You find the device: Juniper EX4200 (we detected it was in the same device family in step 2) which is present in the list of the network devices supported by Operations Manager 2012R2 and 2016

Step 5. Copy the whole # Juniper EX4200 section and duplicate (paste) it under "}"

Step 6. Change configuration strings to device specific that you want to "certify".

In my case:
# Juniper EX4200 changed to # Juniper EX4550-48T (it's just a comment string, you can type anything you want)
. changed to . (OID was taken from Step 1)
EX4200-48T changed to EX4550-48T (Model's DisplayName which will be shown in SCOM console)
Do not change "HEALTH = Juniper-EX4200" or anything else!

Changes summary in txt format:

# Juniper EX4550-48T
. {
     TYPE = Switch
     VENDOR = Juniper
     MODEL  = EX4550-48T
     CONT = Juniper-EX-Series
     HEALTH = Juniper-EX4200
     VLAN = Juniper-Vlan-Mib
     BRIDGE = Dot1q

     Environment                = JuniperEnvMon:DeviceID
     CPU/Memory                 = JuniperRouter:DeviceID
     Card-Fault                 = Juniper
     Interface-Fault            = MIB2
     Interface-Performance      = MIB2SNMP
     Port-Fault                 = MIB2
     Port-Performance           = MIB2
     Port-Ethernet-Performance  = dot3_Ethernet

Step 7. Save file changes in oid2type_Juniper.conf  
If you haven't run Notepad as Administrator in Step 4 you get "Access denied" error and it doesn't allow you to save file.

Step 8. Repeat oid2type_Juniper.conf changes on each SCOM Management server which participates in Network Discovery Pool.

Step 9. Restart SCOM Management Server.

Step 10. Run "Rediscover Device" from SCOM console.

In a few moments Juniper EX4550 network device will be shown in SCOM as "Certified" and in a few minutes you see all network, memory and CPU performance counters and their health.

Summary, you see that:
  • SCOM network device is "Certified" which was "Generic" previously
  • extended monitoring capabilities are present (such as: Processor, Memory and Network monitoring)
  • it was no complex MP XML development effort
Things to remember:
  • always make backup of *.conf file before changes
  • article is not an official guide
  • your customization maybe overwritten with SCOM update rollup or Service Pack (you may need to re-add txt sections again if it's happened)

Wednesday, June 29, 2016

Winmail.dat attachment problem from Exchange Server or Exchange Online


By default, email messages that are sent from Exchange Online in Office 365 (same for Exchange Server on-premises) use the Transport Neutral Encapsulation Format (TNEF) format. Messaging systems that aren't based on Microsoft Exchange may be unable to interpret messages that use this rich text format (RTF). If the recipient’s messaging system can’t process this format, a file attachment that's called "Winmail.dat" is added to the message.


Office 365 admins can use Windows PowerShell to change the message format to prevent the "Winmail.dat" attachment from being sent to external recipients. 
MS suggests you (kb2487954) to configure it per external contact or per external domain. However, you may find this article useless and you won't like to fix it again and again for every new detected domain or external contact. Proposed solution is to make global change for any external domain.

1. Connect to Exchange Online PowerShell or run Exchange Management Shell:

Monday, June 20, 2016

C2R error: "Is your internet connection working? Do you have enough free space on your main hard drive?"

You have configured Click-To-Run (C2R) Office 365 ProPlus installation package with Office Deployment Tool (ODT) and deployed Office 365 ProPlus or Business Premium. Additionally, you want to install C2R MS Visio or C2R MS Project downloaded from Office 365 portal via self-service user deployment. You get following error:

"Couldn't install
We're sorry, we had a problem installing your Office programs(s).
Is your internet connection working? Do you have enough free space on your main hard drive?
Please try installing again after you've checked above
Error Code: 30125-1011 (502)"

You definitely know that there is no issue with the Internet connectivity and you have quite enough free space on your main drive.

Move your C2R installation executable (C2R MS Visio or C2R MS Project *setup.exe) to the same location where ODT has downloaded Office 365 ProPlus installation files. 

Run *setup.exe executable again.

Sunday, June 19, 2016

Cross-premises free/busy calendar sharing between Exchange on-premises and Exchange Online organizations


You federate Exchange Server 2010+ on-premises and Exchange Online for calendar sharing. This specific use case is for two organizations to share Free/Busy calendar information between each other. The first organization has an Exchange Server 2010+ on premises environment. The second organization uses Office 365 with Exchange Online. Neither organization is configured for Hybrid.


From Exchange Server 2010+ on premises EMS:

1. Create Federation Trust:

$ski = [System.Guid]::NewGuid().ToString("N")
New-ExchangeCertificate -FriendlyName "Exchange Federated Delegation" -DomainName $env:USERDNSDOMAIN -Services Federation -KeySize 2048 -PrivateKeyExportable $true -SubjectKeyIdentifier $ski
Get-ExchangeCertificate | ?{$_.friendlyname -eq "Exchange Federated Delegation"} | New-FederationTrust -Name "Microsoft Federation Gateway"

2. Create the federated domain proof encryption string for calendar sharing domain "":

Get-FederatedDomainProof -DomainName

3. Add domain proof as TXT record (generated in step 2) to "" public DNS domain and TXT record value is something like:


4. Once TXT record is added to public DNS then add domain "" as a federated domain and enable federation for the Exchange organization:

Set-FederatedOrganizationIdentifier -DelegationFederationTrust "Microsoft Federation Gateway" -AccountNamespace "" -Enabled $true

5. Create an organization relationship with "" Exchange Online domain:

Get-FederationInformation -DomainName "" | New-OrganizationRelationship -Name "On-premises to Exchange Online" -DomainNames "" -FreeBusyAccessEnabled $true -FreeBusyAccessLevel AvailabilityOnly

From Exchange Online

1. Connect to EXO in another PowerShell session or with "prefixed" session:

Import-PSSession (New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri -Credential (Get-Credential) -Authentication Basic -AllowRedirection)

2. Create a new organization relationship with Exchange Server on premises domain "":

Get-FederationInformation -DomainName "" | New-OrganizationRelationship -Name "Exchange Online to on-premises" -DomainNames "" -FreeBusyAccessEnabled $true -FreeBusyAccessLevel AvailabilityOnly

Now it’s time for testing.

You may notice office 365 users are not able to see the on-prem calendar free/busy info immediately while it's working from the other end. In this case you may need to restart IIS (iisreset) of on-premises Exchange Server 2010+ CAS to get this working. Alternative solution (without IIS restart) you may find at: Exchange Online users in Office 365 cannot see on-premises Exchange Server Free/Busy information.


Friday, June 10, 2016

Office 365 CSP Tenants Subscription Usage summary using DAP access

You are Cloud Solution Provider (CSP) and have a mix of new CSP customers and invited from other Channels like Advisor, EA and etc. Following PowerShell scripts give you an idea what's going on in your CSP world of customer tenants and their subscriptions.

Microsoft Online Service Sign-in Assistant for IT Professionals RTW
You need to be connected with Office 365 "Connect-MsolService" cmdlet using Partner account that has delegated access permission (DAP) to Cloud Solution Provider (CSP) customer tenants prior to PowerShell script execution.

Included functions:


Get-MsolDomain -ErrorAction SilentlyContinue | out-null
if(!($?)) {Connect-MsolService}

   Following function will provide subscription usage summary info for tenant/s
   Following function  will search for the tenant/s by keyword and provide subscription usage summary for the tenant/s
   Keyword is a search string which is included into tenant displayname or "" tenantname or primary domain name
   Ex. for "Rosemann Technology Inc." you can specify just "Rosemann" or "Rose" or ""
   Get-MsolSubscriptionUsage -Name Rose
   Will search for the subscriptions of the tenant or tenants which contains "Rose" string in their name
   ex. "Rose" matches "Rosemann Inc." or "" or "Rose Inc.", etc.
   Get-MsolSubscriptionUsage -Name
   Will search for the subscriptions of the single customer with "" tenant name
   Get-MsolSubscriptionUsage -Name
   Will search for the subscriptions of the single customer with "" primary domain name
   Will search for all available tenants
   Get-MsolSubscriptionUsage > Report.txt
   Will search for all available tenants and save results into Report.txt
function Get-MsolSubscriptionUsage

Write-Verbose "Searching for the tenant/s that contains string $Name"

$Customer = Get-MsolCustomer -Name $Name

Write-Verbose "Found company: $($Customer.Name) - $($Customer.DefaultDomainName)"

if ($Customer) { $Customer | ForEach-Object {
    [System.Guid]$TenantID = $_.TenantId
    $Subscription = Get-MsolSubscription -TenantId $TenantID  -ErrorAction SilentlyContinue

    Show-MsolSubscription -Subscription $Subscription -TenantID $TenantID -Customer $_
    }} else {Write-Warning "Customer not found!"}

   This function will search for customers by primary domain name or by "" name or by DisplayName
   This function will search for customers by primary domain name or by "" name or by DisplayName
   Get-MsolCustomer -Name
   Get-MsolCustomer -Name
   Get-MsolCustomer -Name CustomerName
function Get-MsolCustomer
if ($Name -match ".*[.].*") {Get-MsolPartnerContract -SearchKey DefaultDomainName -DomainName $Name}
else {Get-MsolPartnerContract -All | ? {$_.Name -like "*$Name*"}}


   This function will search for MS Subscriptions
   This function will search for all tenants which contain at least one MS subscription (deployment opportunity of moving to CSP subscription)
function Get-MsolTenantMSSubscription


    $Customer = Get-MsolPartnerContract -All

    $Customer | foreach {
    Write-Verbose "Looking into tenant $($_.DefaultDomainName)"

    $Subscription = Get-MsolSubscription -TenantId $_.TenantID  -ErrorAction SilentlyContinue | `
    ? {!($_.OwnerObjectId) -and ($_.Status -eq "Enabled" -or $_.Status -eq "Warning") -and $_.NextLifecycleDate}

    if ($Subscription) {
            Show-MsolSubscription -Subscription $Subscription -TenantID $_.TenantID -Customer $_

    Write-Warning "Subscriptions provisioned by MS are detected in $($CustomerList.Count) customer tenants"

   This internal function will print subscription summary information for the particular tenant on screen
function Show-MsolSubscription
    $Customer | ft Name,TenantId,DefaultDomainName

    $Subscription | select `
    @{n="Created";e={$_.Datecreated.ToShortDateString()}}, `
    @{n="Expires";e={$_.NextLifecycleDate.ToShortDateString()}}, `
    @{n="SubscriptionId";e={$_.ObjectId}}, `
    @{n="ProvisionedBy";e={if (!$_.OwnerObjectId) {"Microsoft"} elseif `
    ($_.OwnerObjectId -eq "e63464b7-2b94-4841-8033-5b7f66d196d7") {"CSP"} `
    else {$_.OwnerObjectId}}}, `
    @{n="SKU";e={Get-MsolOffer -SkuPartNumber $_.SkuPartNumber}},TotalLicenses,Status | ft -AutoSize

    Write-Verbose "Resolving $($_.SkuPartNumber)"

    Get-MsolAccountSku -TenantId $TenantID -ErrorAction SilentlyContinue | select `
    @{n="SKU";e={Get-MsolOffer -SkuPartNumber $_.SkuPartNumber}}, `
    ActiveUnits,ConsumedUnits,SubscriptionIds | ft -AutoSize

    Write-Output "============================================================================================================"

   This function will show tenants with no active CSP subscriptions (no CSP benefit usage at all or just invited customers)
function Get-MsolTenantNoActiveCSP


    $Customer = Get-MsolPartnerContract -All

    $Customer | foreach {

    Write-Verbose "Looking into tenant $($_.DefaultDomainName)"

    $Subscription = Get-MsolSubscription -TenantId $_.TenantID  -ErrorAction SilentlyContinue | `
    ? {$_.OwnerObjectId -and ($_.Status -eq "Enabled" -or $_.Status -eq "Warning")}
    if (!$Subscription) {
            Get-MsolSubscriptionUsage -Name $_.Name

    Write-Warning "$($CustomerList.Count) CSP tenants have no active CSP subscriptions"


   This function will convert original Office SKU PartNumber name into friendly name
   Get-MsolOffer -SkuPartNumber MCOIMP
   Gives you "SfB Online (Plan 1)"
function Get-MsolOffer
        # Param1 help description
    switch ($SkuPartNumber) {

    "AAD_BASIC" {"Azure Active Directory Basic"}
    "AAD_PREMIUM" {"Azure Active Directory Premium"}
    "RIGHTSMANAGEMENT" {"Azure Rights Management Premium"}
    "LOCKBOX" {"Customer Lockbox"}
    "EXCHANGE_ANALYTICS" {"Delve Analytics"}
    "EMS" {"Enterprise Mobility Suite"}
    "EXCHANGESTANDARD" {"Exchange Online (Plan 1)"}
    "EXCHANGEENTERPRISE" {"Exchange Online (Plan 2)"}
    "ATP_ENTERPRISE" {"Exchange Online ATP"}
    "EXCHANGEARCHIVE_ADDON" {"EOA for Exchange Online"}
    "EXCHANGEARCHIVE" {"EOA for Exchange Server"}
    "EXCHANGEDESKLESS" {"Exchange Online Kiosk"}
    "EOP_ENTERPRISE" {"Exchange Online Protection"}
    "INTUNE_A" {"Intune"}
    "INTUNE_STORAGE" {"Intune Extra Storage"}
    "ADALLOM_STANDALONE" {"Cloud App Security"}
    "EQUIVIO_ANALYTICS" {"O365 Advanced eDiscovery"}
    "O365_BUSINESS" {"O365 Business"}
    "O365_BUSINESS_ESSENTIALS" {"O365 Business Essentials"}
    "O365_BUSINESS_PREMIUM" {"O365 Business Premium"}
    "STANDARDWOFFPACK" {"O365 Enterprise E2 (Nonprofit E1)"}
    "STANDARDPACK" {"O365 Enterprise E1"}
    "ENTERPRISEPACK" {"O365 Enterprise E3"}
    "ENTERPRISEWITHSCAL" {"O365 Enterprise E4"}
    "ENTERPRISEPREMIUM" {"O365 Enterprise E5"}
    "ENTERPRISEPREMIUM_NOPSTNCONF" {"O365 Enterprise E5 w/o PSTN Conf"}
    "DESKLESSPACK" {"O365 Enterprise K1"}
    "SHAREPOINTSTORAGE" {"O365 Extra File Storage"}
    "WACONEDRIVESTANDARD" {"OneDrive for Business (Plan 1)"}
    "WACONEDRIVEENTERPRISE" {"OneDrive for Business (Plan 2)"}
    "POWER_BI_STANDARD" {"Power BI (free)"}
    "POWER_BI_PRO" {"Power BI (Pro)"}
    "PROJECTESSENTIALS" {"Project Lite"}
    "PROJECTONLINE_PLAN_1" {"Project Online"}
    "PROJECTCLIENT" {"Project Pro for O365"}
    "SHAREPOINTSTANDARD" {"SharePoint Online (Plan 1)"}
    "SHAREPOINTENTERPRISE" {"SharePoint Online (Plan 2)"}
    "MCOEV" {"SfB Cloud PBX"}
    "MCOIMP" {"SfB Online (Plan 1)"}
    "MCOSTANDARD" {"SfB Online (Plan 2)"}
    "MCOMEETADV" {"SfB PSTN Conferencing"}
    "MCOPLUSCAL" {"SfB Plus CAL"}
    "MCOPSTN1" {"SfB PSTN Dom. Calling"}
    "MCOPSTN2" {"SfB PSTN Dom. and Int. Calling"}
    "VISIOCLIENT" {"Visio Pro for O365"}
    "CRMIUR" {"Dynamics CRM Online Pro IUR"}
    "YAMMER_ENTERPRISE_STANDALONE" {"Yammer Enterprise"}
    "LITEPACK" {"O365 Small Business"}
    "LITEPACK_P2" {"O365 Small Business Premium"}
    "CRMPLAN1" {"Dynamics CRM Online Essential"}
    "CRMPLAN2" {"Dynamics CRM Online Basic"}
    "CRMSTANDARD" {"Dynamics CRM Online Pro"}

Manage Office 365 tenants with Windows PowerShell for Delegated Access Permissions (DAP) partners