Mailbox von Exchange Online zurück nach Exchange Server on Premises verschieben („Offboarding“)

Es gibtr zwar einen schicken Assistenten der beim Cloud-OnBoarding hilft, aber natürlich kein GUI das beim zurückverschieben von Mailboxen hilft.

Lösung

# Exchnage Online PowerShell Modul importieren
PS C:\> Import-Module ExchangeOnlineManagement

# Exchange Online Credentials angeben
PS C:\> $onlinecred = Get-Credential

# Exchange Online PowerShell Verbindug herstellen
PS C:\> Connect-ExchangeOnline -Credential $onlinecred

# On Premises (lokaler Exchange Server) Credentials angeben
PS C:\> $opcred = Get-Credential

# Neuen Move-Request erstellen
PS C:\> Get-Mailbox -Identity <MAILBOXNAME>| New-MoveRequest -Outbound -RemoteTargetDatabase "<LOKALE DATENBANK NAME>" -RemoteHostName <EXCHANGE SERVER FQDN> -RemoteCredential $opcred -TargetDeliveryDomain <DOMAIN>

Exchange OnPremises Ressourcen (Ressourcen-Postfächer wie Räume) nach Exchange Online migrieren

Benutzer-Postfächer kann man im Exchange Control Panel (ECP) durch einen schnellen Klick auf „Postfach verschieben > Zu Exchange Online“ recht einfach verschieben.

Leider hat Microsoft noch keine solche Funktion für Ressourcenmailboxen eingebaut. Also muss man Räume und Geräte manuell an der PowerShell verschieben. Das geht allerdings relativ problemlos.

Raum- oder Gerätepostfächer zu Exchange online verschieben

Zuerst eine Verbindung zur Exchange Online PowerShell herstellen:

PS C:\> Import-Module ExchangeOnlineManagement
PS C:\> Connect-ExchangeOnline

Dann ein Credential-Objekt für die lokale Domäne erstellen:

PS C:\> $OnPremCred = Get-Credential

Und schliesslich die Migrationsaufträge (MoveRequests) erstellen:

PS C:\> New-MoveRequest -Identity "<Name der Ressource>" -Remote -RemoteHostName <Name Exchange> -TargetDeliveryDomain <Tenant Name>.onmicrosoft.com -RemoteCredential $OnPremCred

Mit den üblichen Tools wie Get-MoveRequest lässt sich der Auftrag dann verfolgen. Im GUI sieht man diese allerdings leider nicht – dafür freifen Parameter wie das BadItemLimit und so weiter.

PowerShell installation von NuGet schlägt fehl („Es kann kein Download von URI…“)

Problem

Für viele Dinge in der PowerShell, beispielsweise auch das MSOnline Modul, wird der NuGet Paketmanager benötigt. Die Module wissen das normalerweise auch und wollen diesen gleich mitinstallieren. Dieser vorgang schlägt aber recht oft fehl:

PS C:> Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201
WARNUNG: Es kann kein Download von URI "https://go.microsoft.com/fwlink/?LinkID=627338&clcid=0x409" nach "" durchgeführt werden.
WARNUNG: Die Liste der verfügbaren Anbieter kann nicht heruntergeladen werden. Überprüfen Sie Ihre Internetverbindung.

Install-PackageProvider : Für die angegebenen Suchkriterien für Anbieter "NuGet" wurde keine Übereinstimmung gefunden. Der Paketanbieter erfordert das PackageManagement- und
Provider-Tag. Überprüfen Sie, ob das angegebene Paket über die Tags verfügt.
In Zeile:1 Zeichen:1
Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201
~~~~~~~~~~~~~ CategoryInfo : InvalidArgument: (Microsoft.Power…PackageProvider:InstallPackageProvider) [Install-PackageProvider], Exception
FullyQualifiedErrorId : NoMatchFoundForProvider,Microsoft.PowerShell.PackageManagement.Cmdlets.InstallPackageProvider

Lösung

Eine funktionierende Internetverbindung vorausgesetzt, liegt es vermutlich an dem „Upgrade“ des Azureedges, der den Lookup-Provider stellt (onegetcdn.azureedge.net/providers). Der Endpunkt lässt seit etwa April 2020 keine TLS1.0 Verbindungen mehr zu und wurde auf „TLS1.2 min“ konfiguriert. Die PowerShell (<14393.3474) spricht per Default aber nur TLS1.1.

Dieser PS-Befehl stellt die PowerShell ebenfalls auf 1.2 um:

[Net.ServicePointManager]::SecurityProtocol=[Net.SecurityProtocolType]::Tls12

Danach funktioniert sofort der Modulinstaller wieder – und alles andere auch.

Set-RDCertificate cert.PFX ist keine PFX-Datei

Problem

Ich hatte gerade bei einem RDS-Deployment einen interessanten WTF-Moment. Es wurde ein ganz frisches SSL-Zertifikat von einer öffentlichen CA bestellt und installiert. Blieb also nur noch, dieses in der RDS-Bereitstellung einzurichten. Sobald das Zertifikat als .PFX exportiert wurde, sollte das per Powershell auch ganz einfach gehen (z.B. für die Gateway-Rolle):

PS C:\> $pfxPassword = Read-Host -AsSecureString
*************
PS C:\> Set-RDCertificate -Role RDGateway -ImportPath C:\install\cert.PFX -Password $pfxPassword

Und schon begrüßt mich der rote Text auf schwarzem Hintergrund:

Set-RDCertificate : ImportPath-Wert "C:\install\cert.PFX" ist keine PFX-Datei.
In Zeile:1 Zeichen:1
...

Lösung

Scheinbar ist das Cmdlet bezüglich der PFX-Dateiendung Case-Sensitive:

PS C:\> Set-RDCertificate -Role RDGateway -ImportPath C:\install\cert.pfx -Password $pfxPassword

funktioniert sofort. Und ja, es reicht wenn man „pfx“ im Cmdlet-Aufruf klein schreibt – der eigentliche Dateiname ist hier nicht relevant (zumindest was Groß-Kleinschreibung angeht).

Dem Server-Manager ist das übrigens auch egal. Über die GUI klappt’s ebenfalls sofort.

Buchungsanfrage abgelehnt: „Die Ressource akzeptiert keine Besprechungen, die länger als 1440 Minuten dauern“

Problem

Eine Ressource lässt sich in Exchange 2016/2019 nicht länger als einen Tag lang (1440 Minuten) buchen. Für Autos oder Leihgeräte sind mehrere Tage oder Wochen aber notwendig.

Lösung

Das ist richtig, die maximale Standartzeit für gebuchte Ressourcen ist 24 Stunden.

Früher gab es mal das Cmdlet Get-MailboxCalendarSettings, mit dem man die Buchungszeit (MaximumDurationInMinutes) einstellen konnte. Dieser Befehl wurde aber (ganz ohne die übliche „Deprecated“ Meldung) abgelöst. Hier sind die neuen.

Einstellung (für die Ressource „Auto*“) anzeigen

[PS] C:\>Get-CalendarProcessing -Identity vw* | fl maximumd*

MaximumDurationInMinutes : 1440

Einstellung ändern

[PS] C:\>Set-CalendarProcessing -Identity vw* -MaximumDurationInMinutes 2147483647

Der Wert ist ein Int32, 2147483647 also das Maximum. Knapp 4000 Jahre reichen aber auch für langfristiges ausleihen aus.

VMware vSphere VCSA/vCenter Liste über VMs mit Betriebssystemen ausgeben

Manchmal braucht man eine schnelle Liste über die laufenden Gast-Betriebssysteme (und -Versionen) in einer vCenter-Instanz. In meinem speziellen Fall benötigte ich vor allem die konfigurierten Betriebssysteme und die tatsächlich laufenden Gäste, um nach einer Migration die Einstellungen für die ESXi-Hosts auz zu räumen.

Nach ein bisschen Bastelei nutze ich nun diesen PowerCLI Einzeiler. Das Script erstellt einfach eine Liste über Name, Konfiguriertes OS und das gemeldete OS aller Gastsysteme.

Lösung

Liste aller OS in einem vCenter via Powershell erstellen:

Get-VM | Get-View -Property @("Name", "Config.GuestFullName", "Guest.GuestFullName") | Select -Property Name, @{N="Eingestellt";E={$_.Config.GuestFullName}},  @{N="Läuft";E={$_.Guest.GuestFullName}} | Format-Table -AutoSize
So sieht die Ausgabe des Befehls aus.

Powershell Scripts starten in der Aufgabenplanung nicht (Ergebnis 0x1)

Problem

Im Taskplaner (Aufgabenplanung) angelegte Powershell-Scripte (*.ps1) starten trotz „richtigem“ Aufruf (%System32%\WindowsPowerShell\v1.0\powershell.exe …) nicht und geben das Ergebis 0x1 zurück

Lösung

Meistens ist die ExecutionPolicy schuld. Mal ist es der 32bit-Powershell-Interpreter, dann wieder 64bit. Die Aufgabenplanung startet per Default x64, aber beide Interpreter haben eigene Policys. Es kann auch eine lokale- oder nichtlokale Profileinstellung sein oder Policy-Changes nach einem Update Es gibt viele Ursachen. Es hat sich daher bewährt, die Policy pro Script zu umgehen:

powershell.exe -NoProfile -NoLogo -NonInteractive -ExecutionPolicy Bypass -File \\<SERVER>\<FREIGABE>\<SCRIPT>.ps1

-NoProfile Stell sicher, das das Script ohne ein lokales Profil ausgeführt wird und somit immer „kollisionsfrei“ bleibt. Außerdem vermeidet man so den langsamen Overhead sämtlichen Profilcodes/aliases/Snipplets/Imports.
-NoLogo Lässt das Startlogo weg. Hilfreich wenn man den vollständigen Output umleitet. Und total gut fürs Admin-Gefühl.
-NonInteractive Umgeht Wartezeiten für Benutzereingaben, indem es letztere weglässt; genauer: durch ein ‚exit 100‘ ersetzt. Das Script hängt also nicht mehr bei Prompts, sondern beendt siche selbst mit dem Fehler 0x100.
-ExecutionPolicy Bypass Umgehen die lokale Executionpolicy. ‚unrestricted‘ ist natürlich ebenfalls möglich. Wir empfehlen aber ‚Bypass‘, weil das Probleme mit globalen Konfigurationsänderungen der Policys (jetzt und in Zukunft) umgeht.