Microsoft 365 Lizenz für alle Benutzer austauschen mit der PowerShell

Wenn man Änderungen an den Lizenzen in Microsoft (Office) 365 vornimmt, erlebt man oft dass die „alten“ und die „neuen“ Lizenzen widersprüchliche Optionen enthalten. Zudem gibt es häufiger mal Probleme, wenn Lizenzen „gepoolt“ sind und gleichzeitig zu Konten hinzugefügt werden sollen. Außerdem kommt es schon mal vor, das „mal eben“ eine Lizenz für alle Benutzer zu ersetzen ist.

Da hilt es, wenn man „mal eben“ alle Microsoft 365 Lizenzen auf einmal ersetzen kann.

Die Umstellung der Lizenzen der Benutzern muss selbstverständlich so durchgeführt werden, das die Endbenutzer das nich bemerken und alle Daten erhalten bleiben.

To the rescue: Das neue Lizenz-SKU mit dem Cmdlet Get-MsolAccountSku anschauen und via Set-MsolUserLicense tauschen.

Was habe ich überhaupt für Lizenzen (SKU)?

Die SKU ist die Microsoft „Stock Keepig Unit“, also quasi der Artikel. Das „quasi“ steht hier für den Artikelumfang, wirklich gleich sind ide Artikel nie. Jeder Tenant bekommt siene „eigene“ Kopie davon. In diesem Fall „TCHERNBYL“ als Platzhalter betrachten.

„Seine“ SKUs schaut man sich am besten zuerst an.

PS C:\> Get-MsolAccountSku

AccountSkuId                 ActiveUnits WarningUnits ConsumedUnits
------------                 ----------- ------------ -------------
TCHERNBYL:FLOW_FREE             10000       0            0
TCHERNBYL:SPB                   18          0            18
TCHERNBYL:EXCHANGESTANDARD      1           0            1
TCHERNBYL:O365_BUSINESS_PREMIUM 18          0            0

Hier hat der Tentant FLOW_FREE (GUI-Name „Power Automate Free“), ein paar SPB („Microsoft 365 Business Premium“), Exchange Pa und O365_BUSINESS_PREMIUM (Meint heute „Microsoft 365 Business Standard“).

Welche SKU haben meine Benutzer?

Das lässt sich genau so schnell herausfinden, wenn man Get-MsolUser filtert:

PS C:\> Get-MsolUser -All | Where {$_.isLicensed -eq "TRUE" -and $_.Licenses.AccountSKUID -eq "TCHERNBYL:SPB"}

UserPrincipalName      DisplayName        isLicensed
-----------------      -----------        ----------

[email protected]       Wiktor Petrowytsch  True

Und wie tausche ich eine Lizenz gegen eine andere?

Im Beispiel wird „Business Premium“ durch „Business Standard“ für alle Lizenzierten Benutzer ausgetauscht:

PS C:\> Get-MsolUser -All | Where {$_.isLicensed -eq "TRUE" -and $_.Licenses.AccountSKUID -eq "TCHERNBYL:SPB"} | Set-MsolUserLicense –AddLicenses "TCHERNBYL:O365_BUSINESS_PREMIUM" –RemoveLicenses "TCHERNBYL:SPB"

Das hilt übrigens auch, wenn man im POrtal zwei vermeintlich identische Lizenzen sieht.

Welche einzelnen Microsoft 365 Pläne sind in einem Plan (=Vertrag) enthalten?

Das lässt sich mit dem ServiceStatus Property beantworten. Eine Liste für eine aktive SKU lässt sich, zum Beispiel, so ausgeben:

PS C:\> (Get-MsolAccountSku | where {$_.AccountSkuId -eq "TCHERNBYL:SPB"}).ServiceStatus

ServicePlan                                ProvisioningStatus
-----------                                ------------------
MDE_SMB                                    Success
VIVA_LEARNING_SEEDED                       Success
Nucleus                                    Success
M365_LIGHTHOUSE_PARTNER_PLAN1              Success
WINDOWSUPDATEFORBUSINESS_DEPLOYMENTSERVICE Success
UNIVERSAL_PRINT_01                         Success
M365_LIGHTHOUSE_CUSTOMER_PLAN1             Success
POWER_VIRTUAL_AGENTS_O365_P3               Success
CDS_O365_P3                                Success
PROJECT_O365_P3                            Success
DYN365_CDS_O365_P3                         Success
MFA_PREMIUM                                Success
EXCHANGE_S_FOUNDATION                      Success
ADALLOM_S_DISCOVERY                        Success
AAD_PREMIUM                                Success
KAIZALA_O365_P2                            Success
MICROSOFT_SEARCH                           Success
OFFICE_SHARED_COMPUTER_ACTIVATION          Success
WHITEBOARD_PLAN1                           Success

[...]

Kalender einer Ressource zeigt keinen Betreff an, sondern den Namen des Organisators

Ein Ressourcenpostfach (z.B. Shared Mailbox) ist in Exchange Online mit „AutoAccept“ (automatische Zusagen, AutomateProcessing) konfiguriert, damit der Kalender Besprechungsanfragen bestätigt.

Die Besprechungsanfragen werden auch korrekt automatisch angenommen. Der Besprechungsbetreff wird im Postfach des Organisators auch angezeigt.

Aber alle anderen Benutzer (mit Berechtigungen auf dem Postfach) sehen statt des Besprechungsbetreffs nur den Namen des Organisators.

Lösung

Dies ist das Standardverhalten von Exchange Online (und Exchange seit 2010) und seither irritierend. Das passiert immer dann, wenn AddOrganizerToSubject und/oder DeleteSubject auf True festgelegt sind.

Aktuelle Einstellung anzeigen:

Get-CalendarProcessing -Identity <RESSOURCE> | fl *subject*

Einstellungen ändern:

Set-CalendarProcessing -Identity <RESSOURCE> -DeleteSubject $false -AddOrganizerToSubject $false

DeleteSubject: Soll der Betreff entfernt werden? (true=ja)

AddOrganizerToSubject: Soll der Name des Organisierenden den Betreff ersetzen? (true=ja)

Outlook „Offline Adressbuch kann nicht heruntergeladen werden“ Fehler 0x8004010F

Outlook versucht im Cache Modus immer das Offline Adressbuch (OAB) zu synchronisieren. Der Prozess bricht aber gerne mal mit dem wenig hilfreichen Fehler 0x8004010F ab.

Das Problem tritt gerne nach Migrationen auf, wenn ein Exchange Server auf ein anderes System (oder neue VErsion) migriert wurde. Dabei wird nämlich ein neues OfflineAddressBook (OAB) generiert, welches auch die Verteilung der Adresslisten übernimmt.

Die Adressliste auf den Clients ist dann meist auch nicht mehr richtig (veraltete Inhalte), allerdigns ist im OWA alles korrekt und aktuell.

Lösung

Zuerst: An der EMS prüfen ob das Adressbuch als „Default“ markiert ist:

Get-OfflineAddressBook | select Name, IsDefault

Hier sollte ein IsDefault: True zurückkommen.

Dann kann man mit prüfen, ob das OAB auch korrekt via Autodiscover verbreitet wird:

Get-OfflineAddressBook | select Name, VirtualDirectories, *web*

Und hier passiert gerne der Fehler. Exchange kennt zwei verschiedene Varianten, um dem Client den Zugriff auf das OAB zu wemöglichen:

  1. Man gibt an welche (IIS-) Virtual Directories vom Client abgefragt werden können um das OAB herunterzuladen
  2. Man erlaubt allen Virtual Directories den Download anzubieten

Microsoft (und wir) raten natürlich zur Variante Nummer 2:

Set-OfflineAddressBook "Standard-Offlineadressbuch" -GlobalWebDistributionEnabled $true

Der Name „Standart-Offlineadressbuch“ ist hier exemplarisch, alle existierenden Offline-Adressbücher listet man mit Get-OfflineAddressBook auf.

Alle deaktivierten Benutzer aus (bestimmten) ActiveDirectory Gruppen entfernen

Ich musste grade eine ganze Menge deaktivierter ActiveDirectory Benutzer aus allen Gruppen entfernen. Andernfalls hätten diese im AADConnect Synchronisationsfehler ausgelöst, da hier deaktivierte Benutzer-Objekte nicht synchronisiert werden.

Mein PowerShell Script das das sehr erfolgreich übernommen hat sieht so aus:

# Durch die OU laufen und deaktivierte User einsammeln ...
foreach ($username in (Get-ADUser -Filter {enabled -eq $false} -SearchBase "OU=<HIER SUCHEN>,DC=<DOMAIN>,DC=<TLD>")) {
 
# ... deren Group-Memberships holen ...
$groups = Get-ADPrincipalGroupMembership $username;
 
# ... durch die Gruppen laufen ...
foreach ($group in $groups) {
 
    # ... wenn Gruppenname stimmt (z.B. "VPN*") ...
    if ($group.name -Like "<NAME>") {
 
        # ... User entfernen
        Remove-ADGroupMember -Identity $group.name -Member $username.SamAccountName -Confirm:$false;
 
        # Ausgabe
        write-host "Habe" $username "von" $group.name "entfernt";
    }
}
}

Das funktioniert natürlich nicht nur mit Sicherheitsgruppen, sondern auch mit Verteilerlisten.

Die Suche nach dem/den Gruppennamen kann man in der Zeile $group.name -Like "Domänen-*" anpassen; hier tun es natürlich auch die anderen Operatoren wie -eq oder -neq.

Exchange online migration: Error: MigrationPermanentException: Target user ‎’User‎‘ already has a primary mailbox.

Wenn man versucht ein Exchange OnPremises Postfache mithilfe von „Postfach verschieben – Zu Exchange Online“ via Migrationsbatch im Exchange Admin Center (EAC) in die Online-Organisation zu verschieben, schlägt der Versuch fehl. Es wird in den Details des Auftrages diese Fehlermeldung angezeigt:

'Error: MigrationPermanentException: Target user ‎'User‎' already has a primary mailbox.'.

Dieses Problem tritt auf, wenn die Attribute „HomeMDB“ und „HomeMTA“ für das Benutzerobjekt in lokalem Active Directory vorhanden sind (und der Inhalt nicht leer ist). Der Auftrag schlägt fehl.

Lösung

Man setzt die Attribute im lokalen AD einfach zurück …

Get-ADUser -Filter {userprincipalname -eq '<[email protected]>'} -properties homemdb,homemta | Set-ADObject -clear homemdb,homemta

… und startet den Auftrag einfach neu. Dann funktioniert das sofort ohne Fehler.