Managing Microsoft 365

Adaxes lets you manage your Microsoft 365 tenant and Microsoft 365 accounts programmatically, via the dedicated ADSI interfaces. The principles outlined in this article can be applied to help you write standalone scripts and programs or build custom integrations with third-party software. PowerShell scripts that manage Microsoft 365 can also be executed from within Adaxes, for instance, from business rules, custom commands, and scheduled tasks.

Registering a tenant

The following code sample uses application credentials to register a Microsoft 365 tenant in Adaxes.

PowerShell
[Reflection.Assembly]::LoadWithPartialName("Softerra.Adaxes.Adsi")

$applicationId = "My Application ID"
$tenantId = "My Tenant ID"
$clientSecret = "My Secret"

# Connect to the Adaxes service.
$ns = New-Object "Softerra.Adaxes.Adsi.AdmNamespace"
$service = $ns.GetServiceDirectly("localhost")

# Bind to the Microsoft 365 container.
$containerPath = $service.Backend.GetConfigurationContainerPath("CloudServicesO365")
$container = $service.OpenObject($containerPath.ToString(), $null, $null, 0)

# Specify app credentials.
$credential = $container.CreateCredential("ADM_M365TENANT_CREDTYPE_APPSECRET")
$credential.AppId = $applicationId
$credential.TenantId = $tenantId
$credential.SetSecret($clientSecret)

# Specify registration parameters and register the tenant.
$parameters = $container.CreateRegistrationParams()
$parameters.Credential = $credential
$parameters.NationalCloud = "ADM_M365NATIONALCLOUD_DEFAULT"

$container.RegisterTenant($parameters, $false)
C#
using Softerra.Adaxes.Adsi;
using Softerra.Adaxes.Interop.Adsi.Microsoft365;
using Softerra.Adaxes.Interop.Adsi.PersistentObjects;

class Program
{
    static void Main(string[] args)
    {
        const string applicationId = "My Application ID";
        const string tenantId = "My Tenant ID";
        const string clientSecret = "My Secret";

        // Connect to the Adaxes service.
        AdmNamespace ns = new AdmNamespace();
        IAdmService service = ns.GetServiceDirectly("localhost");

        // Bind to the Microsoft 365 container.
        string containerPath = service.Backend.GetConfigurationContainerPath(
            "CloudServicesO365");
        IAdmM365Container container = (IAdmM365Container)service.OpenObject(
            containerPath, null, null, 0);

        // Specify app credentials.
        IAdmM365AppSecretTenantCredential credential =
            (IAdmM365AppSecretTenantCredential)container.CreateCredential(
                ADM_M365TENANT_CREDTYPE_ENUM.ADM_M365TENANT_CREDTYPE_APPSECRET);
        credential.AppId = applicationId;
        credential.TenantId = tenantId;
        credential.SetSecret(clientSecret);

        // Specify registration parameters and register the tenant.
        IAdmM365TenantRegistrationParams parameters = container.CreateRegistrationParams();
        parameters.Credential = credential;
        parameters.NationalCloud = ADM_M365NATIONALCLOUD_ENUM.ADM_M365NATIONALCLOUD_DEFAULT;

        container.RegisterTenant(parameters, false);
    }
}

Details

To register a tenant, you need to connect to your Adaxes service and bind to the container where Microsoft 365 tenants are stored, also known as the CloudServicesO365 container. It implements the IAdmM365Container interface.

After binding to the container, you need to create tenant credentials and tenant registration parameters.

Create tenant credentials

Tenant credentials is an object that holds the application or user credentials that Adaxes will use to perform operations in your tenant.

To create an instance of tenant credentials, call IAdmM365Container::CreateCredential and pass the desired credential type as a parameter. The available credential types are specified in ADM_M365TENANT_CREDTYPE_ENUM.

The object returned by CreateCredential will implement one of the following interfaces, depending on the credential type.


Use the methods and properties of the suitable interface to specify the credentials you want to register the tenant with.

Create tenant registration parameters

Tenant registration parameters is an object that holds the tenant credentials and the cloud environment where your tenant belongs.

To create an instance of tenant registration parameters, call IAdmM365Container::CreateRegistrationParams. The object returned by CreateRegistrationParams implements IAdmM365TenantRegistrationParams. Use its properties to set the tenant credentials and the cloud environment type. The available cloud types are specified in ADM_M365NATIONALCLOUD_ENUM.

Finally, call IAdmM365Container::RegisterTenant and pass your IAdmM365TenantRegistrationParams as the first parameter of the method. Set the second parameter to false.

Modifying tenants

The following code sample enables the Synchronize passwords option for a tenant.

PowerShell
[Reflection.Assembly]::LoadWithPartialName("Softerra.Adaxes.Adsi")

$tenantName = "My Tenant"

# Connect to the Adaxes service.
$ns = New-Object "Softerra.Adaxes.Adsi.AdmNamespace"
$service = $ns.GetServiceDirectly("localhost")

# Bind to the Microsoft 365 tenant.
$containerPath = $service.Backend.GetConfigurationContainerPath("CloudServicesO365")
$containerPathObj = New-Object "Softerra.Adaxes.Adsi.AdsPath" $containerPath
$tenantPath = $containerPathObj.CreateChildPath("CN=$tenantName")
$tenant = $service.OpenObject($tenantPath.ToString(), $null, $null, 0)

# Synchronize passwords.
$tenant.SynchronizePasswords = $true

# Save the changes.
$tenant.SetInfo()
C#
using Softerra.Adaxes.Adsi;
using Softerra.Adaxes.Interop.Adsi.Microsoft365;
using Softerra.Adaxes.Interop.Adsi.PersistentObjects;

class Program
{
    static void Main(string[] args)
    {
        const string tenantName = "My Tenant";

        // Connect to the Adaxes service.
        AdmNamespace ns = new AdmNamespace();
        IAdmService service = ns.GetServiceDirectly("localhost");

        // Bind to the Microsoft 365 tenant.
        string containerPath = service.Backend.GetConfigurationContainerPath("CloudServicesO365");
        AdsPath containerPathObj = new AdsPath(containerPath);
        AdsPath tenantPath = containerPathObj.CreateChildPath($"CN={tenantName}");
        IAdmM365Tenant tenant =
            (IAdmM365Tenant)service.OpenObject(tenantPath.ToString(), null, null, 0);

        // Synchronize passwords.
        tenant.SynchronizePasswords = true;

        // Save the changes.
        tenant.SetInfo();
    }
}

Details

To modify a registered tenant, you need to connect to your Adaxes service and bind to the directory object representing the tenant.

After binding to the tenant, you can use the IAdmM365Tenant interface to modify the tenant. To save the changes, call SetInfo.

Modifying available license plans

You can access the array of all license plans that belong to a particular tenant via the Skus property of the IAdmM365Tenant interface. Each plan in the array implements the IAdmM365Sku interface. To identify the license plan you want to modify, you can use the SkuPartNumber property – it will get the exact name of the plan in Microsoft 365.

After you locate the plan and make the necessary changes, call SetInfo to apply them.

Examples

 Example 1 – Update application credentials

The following code sample updates the client secret in the application credentials used to register the tenant.

PowerShell
[Reflection.Assembly]::LoadWithPartialName("Softerra.Adaxes.Adsi")

$tenantName = "My Tenant"
$newSecret = "My Secret"

# Connect to the Adaxes service.
$ns = New-Object "Softerra.Adaxes.Adsi.AdmNamespace"
$service = $ns.GetServiceDirectly("localhost")

# Bind to the Microsoft 365 tenant.
$containerPath = $service.Backend.GetConfigurationContainerPath("CloudServicesO365")
$containerPathObj = New-Object "Softerra.Adaxes.Adsi.AdsPath" $containerPath
$tenantPath = $containerPathObj.CreateChildPath("CN=$tenantName")
$tenant = $service.OpenObject($tenantPath.ToString(), $null, $null, 0)

# Update credentials.
$tenantCredentials = $tenant.GetCredential()
$tenantCredentials.SetSecret($newSecret)
$tenant.SetCredentials($tenantCredentials, $false)
C#
using Softerra.Adaxes.Adsi;
using Softerra.Adaxes.Interop.Adsi.Microsoft365;
using Softerra.Adaxes.Interop.Adsi.PersistentObjects;

class Program
{

    static void Main(string[] args)
    {
        const string tenantName = "My Tenant";
        const string newSecret = "My Secret";

        // Connect to the Adaxes service.
        AdmNamespace ns = new AdmNamespace();
        IAdmService service = ns.GetServiceDirectly("localhost");

        // Bind to the Microsoft 365 tenant.
        string containerPath = service.Backend.GetConfigurationContainerPath("CloudServicesO365");
        AdsPath containerPathObj = new AdsPath(containerPath);
        AdsPath tenantPath = containerPathObj.CreateChildPath($"CN={tenantName}");
        IAdmM365Tenant tenant =
            (IAdmM365Tenant)service.OpenObject(tenantPath.ToString(), null, null, 0);

        // Update credentials.
        IAdmM365AppSecretTenantCredential tenantCredentials = 
            (IAdmM365AppSecretTenantCredential)tenant.GetCredential();
        tenantCredentials.SetSecret(newSecret);
        tenant.SetCredentials(tenantCredentials, false);
    }
}
 Example 2 – Disable a Microsoft 365 license plan

The following code sample disables the Microsoft 365 E3 plan in the tenant. It will become impossible to view, assign, or revoke these licenses via Adaxes.

PowerShell
[Reflection.Assembly]::LoadWithPartialName("Softerra.Adaxes.Adsi")

$tenantName = "My Tenant"
$skuPartNumber = "SPE_E3" # Microsoft 365 E3 plan

# Connect to the Adaxes service.
$ns = New-Object "Softerra.Adaxes.Adsi.AdmNamespace"
$service = $ns.GetServiceDirectly("localhost")

# Bind to the Microsoft 365 tenant.
$containerPath = $service.Backend.GetConfigurationContainerPath("CloudServicesO365")
$containerPathObj = New-Object "Softerra.Adaxes.Adsi.AdsPath" $containerPath
$tenantPath = $containerPathObj.CreateChildPath("CN=$tenantName")
$tenant = $service.OpenObject($tenantPath.ToString(), $null, $null, 0)

# Locate and disable the Microsoft 365 E3 plan.
$planToModify = $tenant.Skus | Where {$_.SkuPartNumber -eq $skuPartNumber}
$planToModify.Enabled = $false
$plan.SetInfo()
C#
using System;
using Softerra.Adaxes.Adsi;
using Softerra.Adaxes.Interop.Adsi.Microsoft365;
using Softerra.Adaxes.Interop.Adsi.PersistentObjects;

class Program
{
    static void Main(string[] args)
    {
        const string tenantName = "My Tenant";
        const string skuPartNumber = "SPE_E3"; // Microsoft 365 E3 plan

        // Connect to the Adaxes service.
        AdmNamespace ns = new AdmNamespace();
        IAdmService service = ns.GetServiceDirectly("localhost");

        // Bind to the Microsoft 365 tenant.
        string containerPath = service.Backend.GetConfigurationContainerPath("CloudServicesO365");
        AdsPath containerPathObj = new AdsPath(containerPath);
        AdsPath tenantPath = containerPathObj.CreateChildPath($"CN={tenantName}");
        IAdmM365Tenant tenant =
            (IAdmM365Tenant)service.OpenObject(tenantPath.ToString(), null, null, 0);

        // Locate and disable the Microsoft 365 E3 plan.
        IAdmM365Sku[] plans = tenant.Skus;
        foreach (IAdmM365Sku plan in plans)
        {
            if (StringComparer.
                OrdinalIgnoreCase.
                Equals(plan.SkuPartNumber, skuPartNumber))
                {
                    plan.Enabled = false;
                    plan.SetInfo();
                    break;
                }
        }
    }
}
 Example 3 – Check the number of available licenses

The following code sample outputs the number of consumed and available licenses for each plan of your Microsoft 365 tenant.

PowerShell
[Reflection.Assembly]::LoadWithPartialName("Softerra.Adaxes.Adsi")

$tenantName = "My Tenant"

# Connect to the Adaxes service.
$ns = New-Object "Softerra.Adaxes.Adsi.AdmNamespace"
$service = $ns.GetServiceDirectly("localhost")

# Bind to the Microsoft 365 tenant.
$containerPath = $service.Backend.GetConfigurationContainerPath("CloudServicesO365")
$containerPathObj = New-Object "Softerra.Adaxes.Adsi.AdsPath" $containerPath
$tenantPath = $containerPathObj.CreateChildPath("CN=$tenantName")
$tenant = $service.OpenObject($tenantPath.ToString(), $null, $null, 0)

# Output plan information.
$plans = $tenant.Skus
foreach ($plan in $plans)
{
    Write-Host "Plan:" $plan.DefaultDisplayName
    Write-Host "Consumed licenses:" $plan.ConsumedUnits
    Write-Host "Available licenses:" ($plan.TotalUnits - $plan.ConsumedUnits) `n
}
C#
using Softerra.Adaxes.Adsi;
using Softerra.Adaxes.Interop.Adsi.Microsoft365;
using Softerra.Adaxes.Interop.Adsi.PersistentObjects;

class Program
{

    static void Main(string[] args)
    {
        const string tenantName = "My Tenant";

        // Connect to the Adaxes service.
        AdmNamespace ns = new AdmNamespace();
        IAdmService service = ns.GetServiceDirectly("localhost");

        // Bind to the Microsoft 365 tenant.
        string containerPath = service.Backend.GetConfigurationContainerPath("CloudServicesO365");
        AdsPath containerPathObj = new AdsPath(containerPath);
        AdsPath tenantPath = containerPathObj.CreateChildPath($"CN={tenantName}");
        IAdmM365Tenant tenant =
            (IAdmM365Tenant)service.OpenObject(tenantPath.ToString(), null, null, 0);

        // Output plan information.
        IAdmM365Sku[] plans = tenant.Skus;
        foreach (IAdmM365Sku plan in plans)
        {
            Console.WriteLine("Plan: " + plan.DefaultDisplayName);
            Console.WriteLine("Consumed licenses: " + plan.ConsumedUnits);
            Console.WriteLine("Available licenses: " + (plan.TotalUnits - plan.ConsumedUnits));
            Console.WriteLine(string.Empty);
        }
    }
}

Defining the associated directory scope

The following code sample adds the example.com domain to the scope of a Microsoft 365 tenant.

PowerShell
[Reflection.Assembly]::LoadWithPartialName("Softerra.Adaxes.Adsi")

$tenantName = "My Tenant"
$domainName = "example.com"

# Connect to the Adaxes service.
$ns = New-Object "Softerra.Adaxes.Adsi.AdmNamespace"
$service = $ns.GetServiceDirectly("localhost")

# Bind to the Microsoft 365 tenant.
$containerPath = $service.Backend.GetConfigurationContainerPath("CloudServicesO365")
$containerPathObj = New-Object "Softerra.Adaxes.Adsi.AdsPath" $containerPath
$tenantPath = $containerPathObj.CreateChildPath("CN=$tenantName")
$tenant = $service.OpenObject($tenantPath.ToString(), $null, $null, 0)

# Bind to the domain.
$domain = $service.OpenObject("Adaxes://$domainName", $null, $null, 0)

# Add the domain to the scope of the tenant.
$scopeItem = $tenant.AssociatedScopeItems.Create()
$scopeItem.BaseObject = $domain
$scopeItem.Type = "ADM_SCOPEBASEOBJECTTYPE_CONTAINER"
$scopeItem.Inheritance = "ADS_SCOPE_SUBTREE"
$scopeItem.Exclude = $false
$scopeItem.SetInfo()
$tenant.AssociatedScopeItems.Add($scopeItem)
C#
using Softerra.Adaxes.Adsi;
using Softerra.Adaxes.Interop.Adsi;
using Softerra.Adaxes.Interop.Adsi.Microsoft365;
using Softerra.Adaxes.Interop.Adsi.PersistentObjects;

class Program
{
    static void Main(string[] args)
    {
        const string tenantName = "My Tenant";
        const string domainName = "example.com";

        // Connect to the Adaxes service
        AdmNamespace ns = new AdmNamespace();
        IAdmService service = ns.GetServiceDirectly("localhost");

        // Bind to the Microsoft 365 tenant.
        string containerPath = service.Backend.GetConfigurationContainerPath("CloudServicesO365");
        AdsPath containerPathObj = new AdsPath(containerPath);
        AdsPath tenantPath = containerPathObj.CreateChildPath($"CN={tenantName}");
        IAdmM365Tenant tenant =
            (IAdmM365Tenant)service.OpenObject(tenantPath.ToString(), null, null, 0);

        // Bind to the domain.
        IAdmTop domain = (IAdmTop)service.OpenObject($"Adaxes://{domainName}", null, null, 0);

        // Add the domain to the scope of the tenant.
        IAdmActivityScopeItem scopeItem =
            (IAdmActivityScopeItem)tenant.AssociatedScopeItems.Create();
        scopeItem.BaseObject = domain;
        scopeItem.Type = ADM_SCOPEBASEOBJECTTYPE_ENUM.ADM_SCOPEBASEOBJECTTYPE_CONTAINER;
        scopeItem.Inheritance = ADS_SCOPEENUM.ADS_SCOPE_SUBTREE;
        scopeItem.Exclude = false;
        scopeItem.SetInfo();
        tenant.AssociatedScopeItems.Add(scopeItem);
    }
}

Details

The scope of a tenant determines what part of your directory it is associated with. The scope can include domains, members of groups and business units, objects located in specific organizational units, etc.

A tenant must be associated with all users whose Microsoft 365 accounts you would like to manage and with all Active Directory groups whose Exchange Online mailboxes you would like to manage.

In hybrid environments (synchronized via Microsoft Entra Connect), it is recommended to match the tenant scope with the Microsoft Entra Connect scope.

To modify the tenant scope, use the AssociatedScopeItems property of the IAdmM365Tenant interface. The property represents a collection of activity scope items and implements the IAdmCollection interface. Each item in the collection either includes or excludes certain objects from the scope.

For more information on how to manage activity scope items, see Defining the scope of activity.

Managing Microsoft 365 accounts

To perform operations on a Microsoft 365 account, you need to bind to the user object whose account you want to modify. All user objects implement the IAdmM365Account interface.

The IAdmM365Account interface has two methods that let you get and set the Microsoft 365 properties of a user. They are GetMicrosoft365Properties and SetMicrosoft365Properties respectively. Microsoft 365 properties are represented by the IAdmM365AccountProperties interface.

Every user account within the scope of a Microsoft 365 tenant has Microsoft 365 properties in Adaxes, even if that user doesn't have an actual Microsoft 365 account yet.

Retrieving Microsoft 365 properties

The following code sample retrieves the user's Microsoft 365 properties and outputs the status of the Sign In Blocked option.

PowerShell
[Reflection.Assembly]::LoadWithPartialName("Softerra.Adaxes.Adsi")

# Connect to the Adaxes service.
$ns = New-Object "Softerra.Adaxes.Adsi.AdmNamespace"
$service = $ns.GetServiceDirectly("localhost")

# Bind to the user.
$userDN = "CN=John Smith,CN=Users,DC=example,DC=com"
$user = $service.OpenObject("Adaxes://$userDN", $null, $null, 0)

# Retrieve Microsoft 365 properties.
$m365Props = $user.GetMicrosoft365Properties()

Write-Host "Sign in blocked:" $m365Props.SignInBlocked
C#
using System;
using Softerra.Adaxes.Adsi;
using Softerra.Adaxes.Interop.Adsi.Microsoft365;
using Softerra.Adaxes.Interop.Adsi.PersistentObjects;

class Program
{
    static void Main(string[] args)
    {
        // Connect to the Adaxes service.
        AdmNamespace ns = new AdmNamespace();
        IAdmService service = ns.GetServiceDirectly("localhost");

        // Bind to the user.
        IAdmM365Account user = (IAdmM365Account)service.OpenObject(
            "Adaxes://CN=John Smith,CN=Users,DC=example,DC=com", null, null, 0);

        // Retrieve Microsoft 365 properties.
        IAdmM365AccountProperties m365Props = user.GetMicrosoft365Properties();

        bool signInBlocked = m365Props.SignInBlocked;
        Console.WriteLine("Sign in blocked: " + signInBlocked.ToString());
    }
}

Calling GetMicrosoft365Properties is expensive with regard to performance because it fetches all information about the user from Microsoft 365.

Activating Microsoft 365 accounts

The following code sample activates a Microsoft 365 account for a user and sets the location in Microsoft 365 to United States.

PowerShell
[Reflection.Assembly]::LoadWithPartialName("Softerra.Adaxes.Adsi")

# Connect to the Adaxes service.
$ns = New-Object "Softerra.Adaxes.Adsi.AdmNamespace"
$service = $ns.GetServiceDirectly("localhost")

# Bind to the user.
$userDN = "CN=John Smith,CN=Users,DC=example,DC=com"
$user = $service.OpenObject("Adaxes://$userDN", $null, $null, 0)

# Get Microsoft 365 properties.
$m365Props = $user.GetMicrosoft365Properties()

# Set location to United States.
$m365Props.Location = "US"
$user.SetMicrosoft365Properties($m365Props)

# Save the changes.
$user.SetInfo()
C#
using Softerra.Adaxes.Adsi;
using Softerra.Adaxes.Interop.Adsi;
using Softerra.Adaxes.Interop.Adsi.Microsoft365;
using Softerra.Adaxes.Interop.Adsi.PersistentObjects;

class Program
{
    static void Main(string[] args)
    {
        // Connect to the Adaxes service.
        AdmNamespace ns = new AdmNamespace();
        IAdmService service = ns.GetServiceDirectly("localhost");

        // Bind to the user.
        IAdmM365Account user = (IAdmM365Account)service.OpenObject(
            "Adaxes://CN=John Smith,CN=Users,DC=example,DC=com", null, null, 0);

        // Retrieve Microsoft 365 properties.
        IAdmM365AccountProperties m365Props = user.GetMicrosoft365Properties();

        // Set location to United States.
        m365Props.Location = "US";
        user.SetMicrosoft365Properties(m365Props);

        // Save the changes.
        IAdmTop user2 = (IAdmTop)user;
        user2.SetInfo();
    }
}

Details

To activate a Microsoft 365 account for a user, you just need to set their usage location in Microsoft 365. The location value must be specified in the ISO 3166-1 format – a two-letter country code (e.g. US or DE).

First, call GetMicrosoft365Properties to retrieve the user's Microsoft 365 properties. Then, use the Location property of the IAdmM365AccountProperties interface to set the location.

Optionally, you can also set the initial password for the Microsoft 365 account. To do this, specify the password in the InitialPassword property of IAdmM365AccountProperties. You can do it only if the Synchronize passwords option is enabled for the Microsoft 365 tenant associated with the user.

Finally, call SetMicrosoft365Properties to update the user's Microsoft 365 properties and call SetInfo to commit the changes to Microsoft 365.

Automatic creation of Microsoft Entra accounts in hybrid environments

By default, in hybrid environments, when an Active Directory object is created in Adaxes within the scope of a Microsoft 365 tenant, Adaxes will create the corresponding object in Microsoft Entra ID. However, you still need to specify the usage location to activate the Microsoft 365 account and be able to assign licenses to that user.

For details on how to configure automatic user creation in Microsoft Entra, see Disable automatic Microsoft Entra object creation.

Assigning/revoking licenses

The following code sample assigns all available licenses to a user.

PowerShell
[Reflection.Assembly]::LoadWithPartialName("Softerra.Adaxes.Adsi")

# Connect to the Adaxes service.
$ns = New-Object "Softerra.Adaxes.Adsi.AdmNamespace"
$service = $ns.GetServiceDirectly("localhost")

# Bind to the user.
$userDN = "CN=John Smith,CN=Users,DC=example,DC=com"
$user = $service.OpenObject("Adaxes://$userDN", $null, $null, 0)

# Retrieve Microsoft 365 properties
$m365Props = $user.GetMicrosoft365Properties()

# Assign all licenses.
foreach ($license in $m365Props.Licenses)
{
    $license.Assigned = $true
}

# Save the changes.
$user.SetMicrosoft365Properties($m365Props)
$user.SetInfo()
C#
using Softerra.Adaxes.Adsi;
using Softerra.Adaxes.Interop.Adsi;
using Softerra.Adaxes.Interop.Adsi.Microsoft365;
using Softerra.Adaxes.Interop.Adsi.PersistentObjects;

class Program
{
    static void Main(string[] args)
    {
        // Connect to the Adaxes service.
        AdmNamespace ns = new AdmNamespace();
        IAdmService service = ns.GetServiceDirectly("localhost");

        // Bind to the user.
        IAdmM365Account user = (IAdmM365Account)service.OpenObject(
            "Adaxes://CN=John Smith,CN=Users,DC=example,DC=com", null, null, 0);

        // Retrieve Microsoft 365 properties.
        IAdmM365AccountProperties m365Props = user.GetMicrosoft365Properties();

        // Assign all licenses.
        foreach (IAdmM365License license in m365Props.Licenses)
        {
            license.Assigned = true;
        }

        // Save the changes.
        user.SetMicrosoft365Properties(m365Props);
        IAdmTop user2 = (IAdmTop)user;
        user2.SetInfo();
    }
}

Details

To assign licenses to a user, first call GetMicrosoft365Properties to retrieve the user's Microsoft 365 properties. Then, use the Licenses property of the IAdmM365AccountProperties interface to assign and revoke licenses.

The Licenses property is an array of all licenses that can be assigned to the user. Each item in the array implements the IAdmM365License interface. Set the IAdmM365License::Assigned property to true to assign the corresponding license or set it to false to revoke the license.

To identify which of the items in the Licenses array represents the license you want to assign, use the Sku property of the IAdmM365License interface. The property gets the IAdmM365SkuInfo interface that can be used to access information about the license plan. For example, the IAdmM365SkuInfo::SkuPartNumber property will return the exact name of the plan in Microsoft 365.

When you modify the value of the Assigned property, Adaxes also sets the AssignedModificationEnabled property to true. If you manually change AssignedModificationEnabled to false, the license status will not be modified.

To revoke all licenses from a user, simply set the RevokeAllLicenses property of the IAdmM365AccountProperties interface to true.

Finally, call SetMicrosoft365Properties to update the user's Microsoft 365 properties and call SetInfo to commit the changes to Microsoft 365.

Examples

 Example 1 – Assign a specific license

The following code sample assigns the Microsoft 365 E3 license to a user.

PowerShell
[Reflection.Assembly]::LoadWithPartialName("Softerra.Adaxes.Adsi")

$licenseName = "SPE_E3" # Microsoft 365 E3 plan

# Connect to the Adaxes service.
$ns = New-Object "Softerra.Adaxes.Adsi.AdmNamespace"
$service = $ns.GetServiceDirectly("localhost")

# Bind to the user.
$userDN = "CN=John Smith,CN=Users,DC=example,DC=com"
$user = $service.OpenObject("Adaxes://$userDN", $null, $null, 0)

# Retrieve Microsoft 365 properties.
$m365Props = $user.GetMicrosoft365Properties()

# Locate and assign the license.
$license = $m365Props.Licenses | Where {$_.Sku.SkuPartNumber -eq $licenseName}
$license.Assigned = $true

# Save the changes.
$user.SetMicrosoft365Properties($m365Props)
$user.SetInfo()
C#
using System;
using Softerra.Adaxes.Adsi;
using Softerra.Adaxes.Interop.Adsi;
using Softerra.Adaxes.Interop.Adsi.Microsoft365;
using Softerra.Adaxes.Interop.Adsi.PersistentObjects;

class Program
{
    static void Main(string[] args)
    {
        const string licenseName = "SPE_E3"; // Microsoft 365 E3 plan

        // Connect to the Adaxes service.
        AdmNamespace ns = new AdmNamespace();
        IAdmService service = ns.GetServiceDirectly("localhost");

        // Bind to the user.
        IAdmM365Account user = (IAdmM365Account)service.OpenObject(
            "Adaxes://CN=John Smith,CN=Users,DC=example,DC=com", null, null, 0);

        // Retrieve Microsoft 365 properties.
        IAdmM365AccountProperties m365Props = user.GetMicrosoft365Properties();

        // Asign the license.
        foreach (IAdmM365License license in m365Props.Licenses)
        {
            if (StringComparer.
                OrdinalIgnoreCase.
                Equals(license.Sku.SkuPartNumber, licenseName))
                {
                    license.Assigned = false;
                    break;
                }
        }

        // Save the changes.
        user.SetMicrosoft365Properties(m365Props);
        IAdmTop user2 = (IAdmTop)user;
        user2.SetInfo();
    }
}
 Example 2 – Revoke all licenses

The following code sample revokes all Microsoft 365 licenses from a user.

PowerShell
[Reflection.Assembly]::LoadWithPartialName("Softerra.Adaxes.Adsi")

# Connect to the Adaxes service.
$ns = New-Object "Softerra.Adaxes.Adsi.AdmNamespace"
$service = $ns.GetServiceDirectly("localhost")

# Bind to the user.
$userDN = "CN=John Smith,CN=Users,DC=example,DC=com"
$user = $service.OpenObject("Adaxes://$userDN", $null, $null, 0)

# Retrieve Microsoft 365 properties.
$m365Props = $user.GetMicrosoft365Properties()

# Revoke all licenses.
$m365Props.RevokeAllLicenses = $true
$user.SetMicrosoft365Properties($m365Props)

# Save the changes.
$user.SetInfo()
C#
using Softerra.Adaxes.Adsi;
using Softerra.Adaxes.Interop.Adsi;
using Softerra.Adaxes.Interop.Adsi.Microsoft365;
using Softerra.Adaxes.Interop.Adsi.PersistentObjects;

class Program
{
    static void Main(string[] args)
    {
        // Connect to the Adaxes service.
        AdmNamespace ns = new AdmNamespace();
        IAdmService service = ns.GetServiceDirectly("localhost");

        // Bind to the user.
        IAdmM365Account user = (IAdmM365Account)service.OpenObject(
            "Adaxes://CN=John Smith,CN=Users,DC=example,DC=com", null, null, 0);

        // Retrieve Microsoft 365 properties.
        IAdmM365AccountProperties m365Props = user.GetMicrosoft365Properties();

        // Revoke all licenses.
        m365Props.RevokeAllLicenses = true;
        user.SetMicrosoft365Properties(m365Props);

        // Save the changes.
        IAdmTop user2 = (IAdmTop)user;
        user2.SetInfo();
    }
}

Enabling/disabling services within a license

The following code sample disables the Power BI Pro service within the Microsoft 365 E3 license assigned to a user.

PowerShell
[Reflection.Assembly]::LoadWithPartialName("Softerra.Adaxes.Adsi")

$licenseName = "SPE_E3" # Microsoft 365 E3 plan
$serviceName = "BI_AZURE_P2" # Power BI Pro

# Connect to the Adaxes service.
$ns = New-Object "Softerra.Adaxes.Adsi.AdmNamespace"
$service = $ns.GetServiceDirectly("localhost")

# Bind to the user.
$userDN = "CN=Barney Calhoun,OU=Users,OU=Alexo,OU=Adaxes Test OU,DC=lab2,DC=softerra,DC=com"
$user = $service.OpenObject("Adaxes://$userDN", $null, $null, 0)

# Retrieve Microsoft 365 properties.
$m365Props = $user.GetMicrosoft365Properties()

# Locate the license and allow modification.
$license = $m365Props.Licenses | Where {$_.Sku.SkuPartNumber -eq $licenseName}
$license.AssignedModificationEnabled = $true

# Locate and disable the service.
$serviceToModify = $license.Services | Where {$_.Service.ServiceName -eq $serviceName}
$serviceToModify.Assigned = $false

# Save the changes.
$user.SetMicrosoft365Properties($m365Props)
$user.SetInfo()

C#
using System;
using Softerra.Adaxes.Adsi;
using Softerra.Adaxes.Interop.Adsi;
using Softerra.Adaxes.Interop.Adsi.Microsoft365;
using Softerra.Adaxes.Interop.Adsi.PersistentObjects;

class Program
{
    static void Main(string[] args)
    {
        const string licenseName = "SPE_E3"; // Microsoft 365 E3 plan
        const string serviceName = "BI_AZURE_P2"; // Power BI Pro

        // Connect to the Adaxes service.
        AdmNamespace ns = new AdmNamespace();
        IAdmService service = ns.GetServiceDirectly("localhost");

        // Bind to the user.
        IAdmM365Account user = (IAdmM365Account)service.OpenObject(
            "Adaxes://CN=John Smith,CN=Users,DC=example,DC=com", null, null, 0);

        // Retrieve Microsoft 365 properties.
        IAdmM365AccountProperties m365Props = user.GetMicrosoft365Properties();

        // Locate the license.
        foreach (IAdmM365License license in m365Props.Licenses)
        {
            if (StringComparer.
                OrdinalIgnoreCase.
                Equals(license.Sku.SkuPartNumber, licenseName))
                {
                    // Allow license modification.
                    license.AssignedModificationEnabled = true;

                    // Locate and disable the service.
                    foreach (IAdmM365ServiceAssignment serviceAssignment in license.Services)
                    {
                        if (StringComparer.
                            OrdinalIgnoreCase.
                            Equals(serviceAssignment.Service.ServiceName, serviceName))
                            {
                                serviceAssignment.Assigned = true;
                                break;
                            }
                    }
                    break;
                }
        }

        // Save the changes.
        user.SetMicrosoft365Properties(m365Props);
        IAdmTop user2 = (IAdmTop)user;
        user2.SetInfo();
    }
}

Details

To modify a service within a license assigned to a user, first call GetMicrosoft365Properties to retrieve the user's Microsoft 365 properties. Then, use the Licenses property of the IAdmM365AccountProperties interface to get the license you want to modify.

Set the IAdmM365License::AssignedModificationEnabled property to true to allow the license modification.

All services that belong to a particular license can be accessed using the IAdmM365License::Services property. It returns an array of service assignments where each item in the array implements the IAdmM365ServiceAssignment interface.

To identify which item in the array represents the service you want to modify, use the Service property of the IAdmM365ServiceAssignment interface. The property gets the IAdmM365Service interface that can be used to access information about the service. For example, the IAdmM365Service::ServiceName property will return the exact name of the service in Microsoft 365.

Set the IAdmM365ServiceAssignment::Assigned property to true to enable the corresponding service or set it to false to disable the service.

Finally, call SetMicrosoft365Properties to update the user's Microsoft 365 properties and call SetInfo to commit the changes to Microsoft 365.

Deactivating Microsoft 365 accounts

To deactivate a Microsoft 365 account of a user and block their access to Microsoft 365 services, you need to set the SignInBlocked property of the IAdmM365AccountProperties interface to true.

The following code sample deactivates a Microsoft 365 account for a user.

PowerShell
[Reflection.Assembly]::LoadWithPartialName("Softerra.Adaxes.Adsi")

# Connect to the Adaxes service.
$ns = New-Object "Softerra.Adaxes.Adsi.AdmNamespace"
$service = $ns.GetServiceDirectly("localhost")

# Bind to the user.
$userDN = "CN=John Smith,CN=Users,DC=example,DC=com"
$user = $service.OpenObject("Adaxes://$userDN", $null, $null, 0)

# Retrieve Microsoft 365 properties.
$m365Props = $user.GetMicrosoft365Properties()

# Block access to Microsoft 365 services.
$m365Props.SignInBlocked = $true
$user.SetMicrosoft365Properties($m365Props)

# Save the changes.
$user.SetInfo()
C#
using Softerra.Adaxes.Adsi;
using Softerra.Adaxes.Interop.Adsi;
using Softerra.Adaxes.Interop.Adsi.Microsoft365;
using Softerra.Adaxes.Interop.Adsi.PersistentObjects;

class Program
{
    static void Main(string[] args)
    {
        // Connect to the Adaxes service.
        AdmNamespace ns = new AdmNamespace();
        IAdmService service = ns.GetServiceDirectly("localhost");

        // Bind to the user.
        IAdmM365Account user = (IAdmM365Account)service.OpenObject(
            "Adaxes://CN=John Smith,CN=Users,DC=example,DC=com", null, null, 0);

        // Retrieve Microsoft 365 properties.
        IAdmM365AccountProperties m365Props = user.GetMicrosoft365Properties();

        // Block Access to Microsoft 365 services.
        m365Props.SignInBlocked = true;
        user.SetMicrosoft365Properties(m365Props);

        // Save the changes.
        IAdmTop user2 = (IAdmTop)user;
        user2.SetInfo();
    }
}

See also