– Jan's Cloud – online Gedankenstütze ;)

1. August 2018

Exchange Server 2019 Preview verfügbar

Filed under: Exchange,PowerShell,Windows Server — Schlagwörter: , , , — Jan Mischo @ 14:37

Am 24.07.2018 wurde die Exchange Server 2019 Preview für die Allgemeinheit veröffentlicht

Da es grade sehr heiß ist und in der Ferienzeit scheinbar alle im Urlaub sind, habe ich meine riesige Exchange Demoumgebung doch direkt einmal auf die Exchange Server 2019 Preview upgedatet. 🙂

Bei der Installation in die bestehende Exchange Organisation hat sich im Vergleich zu den letzten beiden Exchange Versionen eigentlich wenig getan. Die Vorraussetzungen sind ebenfalls nahezu geich geblieben und wären namentlich:

Eine kleine (ggfs. wichtige) Änderung betrifft das Forest Functional Level der Gesamtstruktur. Dieses muss mindestens auf das Forest Functionality Level Server 2012 R2 angehoben werden!

Getreu dem Dinner for one Motto „The same procedure as every year“ sieht das GUI Setup dem der alten Versionen ziemlich ähnlich. Damit alle beruhigt sind, bei der Installation per Commandline hat sich auch nichts getan.

Nach der Installation geht es ebenfalls ziemlich genau so weiter wie bei einer Migration von Exchange 2013 auf 2016:

#Auslesen der Exchange Server
$Exch2016 = Get-ExchangeServer | ? AdminDisplayVersion -match "Version 15.1"
$Exch2019 = Get-ExchangeServer | ? AdminDisplayVersion -match "Version 15.2"
#Auslesen des konfigurierten SplitDNS FQDNs
$vDirHost = $(Get-OwaVirtualDirectory -Server $Exch2016).InternalURL.Host

#Mailboxdatenbanken auf dem Exchange 2019 trennen
Get-MailboxDatabase -Server $Exch2019 | Dismount-Database -Confirm:$false
#Mailboxdatenbanken umbenennen, verschieben und einbinden
foreach ($DB in $(Get-MailboxDatabase -Server $Exch2019)) { $i = $i + 1; Set-MailboxDatabase -Identity $DB -Name Exch2019DB0$i; Move-Databasepath -Identity $DB -edbfilepath "D:\ExchangeDB\Exch2019DB0$i\Exch2019DB0$i.edb" -logfolderpath "D:\ExchangeLOG\Exch2019DB0$i" -confirm:$false; Mount-Database -Identity Exch2019DB0$i -confirm:$false }

#Neuen Receiveconnector "Internet" erstellen und in meinem Fall der Firewall erlauben anonym Mails einzuliefern
New-ReceiveConnector -Name "Internet" -Usage Custom  -TransportRole FrontendTransport -PermissionGroups AnonymousUsers -Bindings 0.0.0.0:25 -RemoteIpRanges $((Get-NetRoute -ifIndex $(Get-NetIPAddress -InterfaceAlias "LAN" -AddressFamily "IPv4").ifIndex | ? DestinationPrefix -eq "0.0.0.0/0").NextHop)
#Dem Sendeconnector "Internet" den neuen Exchange hinzufügen
Get-SendConnector -Identity "Internet" | Set-SendConnector -SourceTransportServers $Exch2016, $Exch2019

#IMAP und POP Zertifikats CN anpassen, da ich ein Wildcard Zertifikat nutze
Set-ImapSettings -Server $Exch2019 -X509CertificateName $vDirHost
Set-PopSettings -Server $Exch2019 -X509CertificateName $vDirHost

# IMAP und POP Dienste neu starten
Restart-Service MSExchangeIMAP4BE
Restart-Service MSExchangeImap4
Restart-Service MSExchangeIMAP4BE
Restart-Service MSExchangePop3

#Virtuelle Verzeichnisse konfigurieren
Get-OwaVirtualDirectory -Server $Exch2019 | Set-OwaVirtualDirectory -InternalUrl "https://$vDirHost/owa" -ExternalUrl "https://$vDirHost/owa"
Get-EcpVirtualDirectory -Server $Exch2019 | Set-EcpVirtualDirectory -InternalUrl "https://$vDirHost/ecp" -ExternalUrl "https://$vDirHost/ecp"
Get-OABVirtualDirectory -Server $Exch2019 | Set-OABVirtualDirectory -InternalURL "https://$vDirHost/OAB" -ExternalURL "https://$vDirHost/OAB"
Get-ActiveSyncVirtualDirectory -Server $Exch2019 | Set-ActiveSyncVirtualDirectory -InternalURL "https://$vDirHost/Microsoft-Server-ActiveSync" -ExternalURL "https://$vDirHost/Microsoft-Server-ActiveSync"
Get-WEbServicesVirtualDirectory -Server $Exch2019 | Set-WEbServicesVirtualDirectory -InternalURL "https://$vDirHost/EWS/Exchange.asmx" -ExternalURL "https://$vDirHost/EWS/Exchange.asmx"
Get-MapiVirtualDirectory -Server $Exch2019 | Set-MapiVirtualDirectory -InternalURL "https://$vDirHost/mapi" -ExternalURL "https://$vDirHost/mapi"
Get-ClientAccessService -Identity $Exch2019.Name | Set-ClientAccessService -AutodiscoverServiceInternalUri https://$vDirHost/autodiscover/autodiscover.xml
Get-OutlookAnywhere -Server $Exch2019 | Set-OutlookAnywhere -ExternalHostname $vDirHost -InternalHostname $vDirHost -ExternalClientsRequireSsl:$true -InternalClientsRequireSsl:$true -ExternalClientAuthenticationMethod "Ntlm"

#Zertifikatskette und eigentliches Wildcard Zertifikat aus C:\Install\Zertifikate einlesen
$Zertifikat = (Get-ChildItem -Path C:\Install\Zertifikate\1Comodo_RootCA.crt)
$Zertifikat | Import-Certificate -CertStoreLocation Cert:\LocalMachine\Root | Out-Null
$Zertifikat = (Get-ChildItem -Path C:\Install\Zertifikate\2Comodo_Intermediate_1.crt)
$Zertifikat | Import-Certificate -CertStoreLocation Cert:\LocalMachine\CA | Out-Null
$Zertifikat = (Get-ChildItem -Path C:\Install\Zertifikate\3Comodo_Intermediate_2.crt)
$Zertifikat | Import-Certificate -CertStoreLocation Cert:\LocalMachine\CA | Out-Null
$Zertifikat = Import-pfxCertificate -FilePath "C:\Install\Zertifikate\04Wildcard.pfx" -CertStoreLocation Cert:\LocalMachine\My -Password $(ConvertTo-SecureString "Kennwort1" -AsPlainText -Force)
Enable-ExchangeCertificate -Thumbprint $Zertifikat.Thumbprint -Services IIS, IMAP, POP, SMTP -Force -Confirm:$false

#An dieser Stelle wäre es Zeit die IP Adresse im DNS von $vDirHost auf den neuen Exchange Server zu schwenken
#Sowie den DNS Cache am Server sowie Client zu löschen
#Sowie einen heißen, schwarzen Kaffee zu trinken!

#Migrations Mailbox verschieben
#https://technet.microsoft.com/en-us/library/mt441791(v=exchg.150)
Get-Mailbox -Identity Migration* -Arbitration | New-MoveRequest -TargetDatabase Exch2019DB01

#Test User verschieben
New-MoveRequest Toni.Test -TargetDatabase Exch2019DB01

#Outlook testen... Outlook kann während dem gesamten Verschiebevorgang offen sein. Nach Abschluss ist ebenfalls kein Neustart mehr notwendig

#Arbitration Postfächer, alle anderen Postfächer und die öffentlichen Ordner Postfächer verschieben
Get-Mailbox -Server $Exch2016 -Arbitration | New-MoveRequest -TargetDatabase Exch2019DB01
Get-Mailbox -Server $Exch2016 | New-MoveRequest -TargetDatabase Exch2019DB01
Get-Mailbox -PublicFolder | New-MoveRequest -TargetDatabase Exch2019DB01
Get-Mailbox -AuditLog | New-MoveRequest -TargetDatabase Exch2019DB01

#Aufräumen
Get-MoveRequest | Remove-MoveRequest -Confirm:$false

#Exchange 2016 deinstallieren

Aufgrund des Hinweises von Sebastian Röhner im Kommentar, habe ich die Umgebung noch einmal neu aufgebaut und die Mailbox eines Testusers direkt verschoben ohne vorher das Migrationspostfach (Migration Mailbox) zu verschieben. Was soll ich sagen, es hat erneut ohne Probleme funktionert. Dennoch werde ich in Zukunft wohl den Microsoft-Weg, wie in https://technet.microsoft.com/en-us/library/mt441791(v=exchg.150) beschrieben gehen. Daher ist das Script auch ein wenig ergänzt worden.

Nochmals ein „Danke“ an Sebastian Röhner für den Hinweis!

MoveRequest MigrationMailbox

MoveRequest MigrationMailbox

 

 

 

 

 

Da bleibt ja eigenltich nur die Frage nach den Änderungen oder Neuerungen… Auf den ersten Blick wären da:

  • Support von Windows Server 2016 (2019 vermutlich auch?) Core
  • Einem in der Preview nicht funktionierenden SSD Cache
  • Indexierung nicht mehr im Dateisystem sondern in der Datenbnak
  • Unterstützung von 48 Prozessoren und 256GB RAM
  • Es gibt keine UM (Unified Messaging) Rolle mehr mit Exchange 2019
halo i bims exchange server 2019 preview

halo i bims exchange server 2019 preview

 

18. Juli 2018

Unnötige Windows Server 2016 Dienste deaktivieren

Deaktivieren der nicht benötigten Windows Server 2016 Dienste (Manager für heruntergeladene Karten, Xbox Live Authentifizierungs-Manager, Xbox Live-Spiele speicher, usw.)

Kurz und schmerzlos:

$cred = Get-Credential
foreach ($Server in $(Get-ADComputer -SearchBase "OU=Meine OU,DC=Meine Domäne,DC=Meine TLD" -Filter 'OperatingSystem -like "Windows Server 2016*"')) {
    Write-Host "Verbinde mit Server:" $Server.DNSHostName
    Invoke-Command -ComputerName $Server.DNSHostName -Credential $cred -ScriptBlock {
        Write-Host "`tDeaktiviere Dienste..."
        Set-Service -Name "MapsBroker" -StartupType Disabled
        Set-Service -Name "XblAuthManager" -StartupType Disabled
        Set-Service -Name "XblGameSave" -StartupType Disabled

        Write-Host "`tDeaktiviere per User Dienste..."
        if(Test-Path -Path HKLM:\SYSTEM\CurrentControlSet\Services\OneSyncSvc_*) {
	        $TempSVC = (Get-ChildItem -Path HKLM:\SYSTEM\CurrentControlSet\Services\OneSyncSvc_*)
	        foreach ($SVC in $TempSVC) {
		        $SVC = "$($SVC.PSParentPath)\$($SVC.PSChildName)"
		        Set-ItemProperty -Path $SVC -Name "Start" -Value 4
	        }
        }
        Write-Host "`tDeaktiviere geplante Tasks..."
        Disable-ScheduledTask -TaskPath "\Microsoft\Windows\Maps\" -TaskName "MapsToastTask" | Out-Null
        Disable-ScheduledTask -TaskPath "\Microsoft\XblGameSave\" -TaskName "XblGameSaveTask" | Out-Null
        Disable-ScheduledTask -TaskPath "\Microsoft\XblGameSave\" -TaskName "XblGameSaveTaskLogon" | Out-Null
    }
}

Vor einiger Zeit hatte ich über das Citrix Optimizer Tool geschrieben. Das deaktiviert unterm Strich ebenfalls einige Dienste und nimmt weitere Einstellungen vor. Ebenfalls hat Microsoft eine Liste mit Diensten veröffentlicht die deaktiviert werden sollten / können:

Hier einmal das „volle Programm“ an überflüssigen / unnötigen Windows Server 2016 Diensten:

$cred = Get-Credential
foreach ($Server in $(Get-ADComputer -SearchBase "OU=Meine OU,DC=Meine Domäne,DC=Meine TLD" -Filter 'OperatingSystem -like "Windows Server 2016*"')) {
    Write-Host "Verbinde mit Server:" $Server.DNSHostName
    Invoke-Command -ComputerName $Server.DNSHostName -Credential $cred -ScriptBlock {
        Write-Host "`tDeaktiviere Dienste..."
        Set-Service -Name "Audiosrv" -StartupType Disabled
        Set-Service -Name "AudioEndpointBuilder" -StartupType Disabled
        Set-Service -Name "AxInstSV" -StartupType Disabled
        Set-Service -Name "bthserv" -StartupType Disabled
        Set-Service -Name "CDPUserSvc" -StartupType Disabled
        Set-Service -Name "dmwappushservice" -StartupType Disabled
        Set-Service -Name "FrameServer" -StartupType Disabled
        Set-Service -Name "icssvc" -StartupType Disabled
        Set-Service -Name "lltdsvc" -StartupType Disabled
        Set-Service -Name "lfsvc" -StartupType Disabled
        Set-Service -Name "MapsBroker" -StartupType Disabled
        Set-Service -Name "NcbService" -StartupType Disabled
        Set-Service -Name "PcaSvc" -StartupType Disabled
        Set-Service -Name "QWAVE" -StartupType Disabled
        Set-Service -Name "RmSvc" -StartupType Disabled
        Set-Service -Name "SensorDataService" -StartupType Disabled
        Set-Service -Name "SensorService" -StartupType Disabled
        Set-Service -Name "SensrSvc" -StartupType Disabled
        Set-Service -Name "SharedAccess" -StartupType Disabled
        Set-Service -Name "ShellHWDetection" -StartupType Disabled
        Set-Service -Name "SSDPSRV" -StartupType Disabled
        Set-Service -Name "stisvc" -StartupType Disabled
        Set-Service -Name "TabletInputService" -StartupType Disabled
        Set-Service -Name "upnphost" -StartupType Disabled
        Set-Service -Name "WalletService" -StartupType Disabled
        Set-Service -Name "WiaRpc" -StartupType Disabled
        Set-Service -Name "wisvc" -StartupType Disabled
        Set-Service -Name "wlidsvc" -StartupType Disabled
        Set-Service -Name "WpnService" -StartupType Disabled
        Set-Service -Name "XblAuthManager" -StartupType Disabled
        Set-Service -Name "XblGameSave" -StartupType Disabled

        Write-Host "`tDeaktiviere User Dienste..."
        if(Test-Path -Path HKLM:\SYSTEM\CurrentControlSet\Services\CDPUserSvc_*) {
	        $TempSVC = (Get-ChildItem -Path HKLM:\SYSTEM\CurrentControlSet\Services\CDPUserSvc_*)
	        foreach ($SVC in $TempSVC) {
		        $SVC = "$($SVC.PSParentPath)\$($SVC.PSChildName)"
		        Set-ItemProperty -Path $SVC -Name "Start" -Value 4
	        }
        }
        Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\NgcSvc" -Name "Start" -Value 4
        Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\OneSyncSvc" -Name "Start" -Value 4
        if(Test-Path -Path HKLM:\SYSTEM\CurrentControlSet\Services\OneSyncSvc_*) {
	        $TempSVC = (Get-ChildItem -Path HKLM:\SYSTEM\CurrentControlSet\Services\OneSyncSvc_*)
	        foreach ($SVC in $TempSVC) {
		        $SVC = "$($SVC.PSParentPath)\$($SVC.PSChildName)"
		        Set-ItemProperty -Path $SVC -Name "Start" -Value 4
	        }
        }
        Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\PimIndexMaintenanceSvc" -Name "Start" -Value 4
        if(Test-Path -Path HKLM:\SYSTEM\CurrentControlSet\Services\PimIndexMaintenanceSvc_*) {
	        $TempSVC = (Get-ChildItem -Path HKLM:\SYSTEM\CurrentControlSet\Services\PimIndexMaintenanceSvc_*)
	        foreach ($SVC in $TempSVC) {
		        $SVC = "$($SVC.PSParentPath)\$($SVC.PSChildName)"
		        Set-ItemProperty -Path $SVC -Name "Start" -Value 4
	        }
        }
        Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\UserDataSvc" -Name "Start" -Value 4
        Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\UnistoreSvc" -Name "Start" -Value 4
        if(Test-Path -Path HKLM:\SYSTEM\CurrentControlSet\Services\UnistoreSvc_*) {
	        $TempSVC = (Get-ChildItem -Path HKLM:\SYSTEM\CurrentControlSet\Services\UnistoreSvc_*)
	        foreach ($SVC in $TempSVC) {
		        $SVC = "$($SVC.PSParentPath)\$($SVC.PSChildName)"
		        Set-ItemProperty -Path $SVC -Name "Start" -Value 4
	        }
        }
        Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\WpnUserService" -Name "Start" -Value 4
        if(Test-Path -Path HKLM:\SYSTEM\CurrentControlSet\Services\WpnUserService_*) {
	        $TempSVC = (Get-ChildItem -Path HKLM:\SYSTEM\CurrentControlSet\Services\WpnUserService_*)
	        foreach ($SVC in $TempSVC) {
		        $SVC = "$($SVC.PSParentPath)\$($SVC.PSChildName)"
		        Set-ItemProperty -Path $SVC -Name "Start" -Value 4
	        }
        }

        Write-Host "`tDeaktiviere geplante Tasks..."
        Disable-ScheduledTask -TaskPath "\Microsoft\Windows\Application Experience\" -TaskName "Microsoft Compatibility Appraiser" | Out-Null
        Disable-ScheduledTask -TaskPath "\Microsoft\Windows\Application Experience\" -TaskName "ProgramDataUpdater" | Out-Null
        Disable-ScheduledTask -TaskPath "\Microsoft\Windows\AppID\" -TaskName "EDP Policy Manager" | Out-Null
        Disable-ScheduledTask -TaskPath "\Microsoft\Windows\AppID\" -TaskName "SmartScreenSpecific" | Out-Null
        Disable-ScheduledTask -TaskPath "\Microsoft\Windows\ApplicationData\" -TaskName "CleanupTemporaryState" | Out-Null
        Disable-ScheduledTask -TaskPath "\Microsoft\Windows\ApplicationData\" -TaskName "DsSvcCleanup" | Out-Null
        Disable-ScheduledTask -TaskPath "\Microsoft\Windows\Autochk\" -TaskName "Proxy" | Out-Null
        Disable-ScheduledTask -TaskPath "\Microsoft\Windows\Bluetooth\" -TaskName "UninstallDeviceTask" | Out-Null
        Disable-ScheduledTask -TaskPath "\Microsoft\Windows\CloudExperienceHost\" -TaskName "CreateObjectTask" | Out-Null
        Disable-ScheduledTask -TaskPath "\Microsoft\Windows\Customer Experience Improvement Program\" -TaskName "Consolidator" | Out-Null
        Disable-ScheduledTask -TaskPath "\Microsoft\Windows\Customer Experience Improvement Program\" -TaskName "KernelCeipTask" | Out-Null
        Disable-ScheduledTask -TaskPath "\Microsoft\Windows\Customer Experience Improvement Program\" -TaskName "UsbCeip" | Out-Null
        Disable-ScheduledTask -TaskPath "\Microsoft\Windows\Diagnosis\" -TaskName "Scheduled" | Out-Null
        Disable-ScheduledTask -TaskPath "\Microsoft\Windows\Location\" -TaskName "Notifications" | Out-Null
        Disable-ScheduledTask -TaskPath "\Microsoft\Windows\Location\" -TaskName "WindowsActionDialog" | Out-Null
        Disable-ScheduledTask -TaskPath "\Microsoft\Windows\Maintenance\" -TaskName "WinSAT" | Out-Null
        Disable-ScheduledTask -TaskPath "\Microsoft\Windows\Maps\" -TaskName "MapsToastTask" | Out-Null
        Disable-ScheduledTask -TaskPath "\Microsoft\Windows\Mobile Broadband Accounts\" -TaskName "MNO Metadata Parser" | Out-Null
        Disable-ScheduledTask -TaskPath "\Microsoft\Windows\NetTrace\" -TaskName "GatherNetworkInfo" | Out-Null
        Disable-ScheduledTask -TaskPath "\Microsoft\Windows\Power Efficiency Diagnostics\" -TaskName "AnalyzeSystem" | Out-Null
        Disable-ScheduledTask -TaskPath "\Microsoft\Windows\Ras\" -TaskName "MobilityManager" | Out-Null
        Disable-ScheduledTask -TaskPath "\Microsoft\Windows\SpacePort\" -TaskName "SpaceAgentTask" | Out-Null
        Disable-ScheduledTask -TaskPath "\Microsoft\Windows\SpacePort\" -TaskName "SpaceManagerTask" | Out-Null
        Disable-ScheduledTask -TaskPath "\Microsoft\Windows\Speech\" -TaskName "SpeechModelDownloadTask" | Out-Null
        Disable-ScheduledTask -TaskPath "\Microsoft\Windows\Storage Tiers Management\" -TaskName "Storage Tiers Management Initialization" | Out-Null
        Disable-ScheduledTask -TaskPath "\Microsoft\Windows\WDI\" -TaskName "ResolutionHost" | Out-Null
        Disable-ScheduledTask -TaskPath "\Microsoft\Windows\Workplace Join\" -TaskName "Automatic-Device-Join" | Out-Null
        Disable-ScheduledTask -TaskPath "\Microsoft\XblGameSave\" -TaskName "XblGameSaveTask" | Out-Null
        Disable-ScheduledTask -TaskPath "\Microsoft\XblGameSave\" -TaskName "XblGameSaveTaskLogon" | Out-Null
    }
}

Hier das Script als Textdatei zum Download: Windows Server 2016 Dienste deaktivieren

12. Juli 2018

Hyper-V GetSANPath Funktion

Filed under: Hyper-V,PowerShell,Windows Server — Schlagwörter: , , , , , — Jan Mischo @ 10:00

Eine kleine Funktion „GetSANPath“, um die Cluster Shared Volumes inkl. ein paar Infos in einem Grid View auszugeben und auszuwählen

Die PowerShell Funktion GetSANPath liest alle gemounteten Cluster Shared Volumes aus und holt sich Informationen zu Größe und freiem sowie genutztem Speicherplatz. Die Informationen werden dann ein wenig sortiert und in einem Grid View ausgegeben. Das ausgewählte CSV wird anschließend in eine Variable geschrieben, auf die gewünschten Infos „Name“ und „Pfad“ gekürzt und zurückgegeben.

GetSANPath Grid View

GetSANPath Grid View

GetSANPath Ausgabe

GetSANPath Ausgabe

Den größten bzw. wichtigsten Teil des Scriptes habe ich im Script Center des Technets gefunden: https://gallery.technet.microsoft.com/scriptcenter/Monitor-Cluster-Shared-21de7554

function GetSANPath {
    $Output = @()
    $csvs = Get-ClusterSharedVolume  
    foreach ( $csv in $csvs ) {  
        $csvinfos = $csv | select -Property Name -ExpandProperty SharedVolumeInfo  
        foreach ( $csvinfo in $csvinfos ) {  
            $temp_csv = New-Object PSObject -Property @{  
                Name = $csv.Name
                Size = $([math]::round((($csvinfo.Partition.Size) / 1GB), 2))
                FreeSpace = $([math]::round((($csvinfo.Partition.FreeSpace) / 1GB), 2))
                UsedSpace = $([math]::round((($csvinfo.Partition.UsedSpace) / 1GB), 2))
                PercentFree = $csvinfo.Partition.PercentFree
                Path = $csvinfo.FriendlyVolumeName
            }  
 
            $Output += $temp_csv
        }  
    }
do {
    $SAN = $Output | Select-Object Name, @{l="Größe in GB"; e={$_.Size}}, @{l="Freier Speicher in GB"; e={$_.FreeSpace}}, @{l="Benutzter Speicher in GB"; e={$_.UsedSpace}}, @{l="Freier Speicher in %"; e={$_.PercentFree}}, @{l="Pfad"; e={$_.Path}} | Out-GridView -PassThru
} until ($SAN)

$SAN = @{
            Name = $SAN.Name
            Path = $SAN.Pfad
        }

return $SAN
}

8. Juli 2018

Auf Active Directory Start in Hyper-V VM warten

Filed under: Hyper-V,PowerShell,Windows Server — Schlagwörter: , , , , — Jan Mischo @ 11:10

Den vollständigen Start des Active Directory in einer Hyper-V VM abwarten

Das gestern vorgestellt Script „RebootAndWaitForServer“ wartet nur „stumpf“ bis die Hyper-V VM gebootet ist und der Prozess „winlogon.exe“ sowie der Dienst „LSM“ läuft. Stellt man jetzt eine Umgebung auf der grünen Wiese bzw. einen PoC oder eine Demoumgebung bereit, benötigt man unter Umständen einen Domänen Controller. Ein DC sollte nicht nur automatisch ausgerollt, sondern auch noch entsprechend konfiguriert werden. Die Konfiguration ist allerdings, logischerweise, erst möglich wenn die Active Directory Dienste gestartet und betriebsbereit sind. Auch hier gab es auf GitHub (WaitFor-ActiveDirectory) bereits eine Funktion, die in verschiedenen Tests nicht zuverlässig lief. In prduktiven Umgebungen sollte es diese Problem natürlich gar nicht erst, da immer mindestens zwei Domain Controller betrieben werden sollten, von denen einer immer erreichbar ist.

Das folgende Script liest die Uptime der Hyper-V VM aus, zieht diese vom aktuellen Datum ab und durchsucht dann die Ereignisanzeige „Active Directory Web Services“ in der VM auf die Instanz-Id „1073743024“.

WaitForAD

WaitForAD

WaitForAD PowerShell

WaitForAD PowerShell

<# WaitForAD
Beispiel für die Variablen:
    [string]$VMName = "SERVER-VM01"
    [System.Management.Automation.PSCredential] $tempCred = new-object -typename System.Management.Automation.PSCredential ("Domain\Admin", (ConvertTo-SecureString P@ssw0rd! -AsPlainText -Force))

Oder ggfs. die Variablen abfragen:
    $VMName = Read-Host "Bitte den Namen des virtuellen Computers eingeben"
    $tempCred = Get-Credential
#>

function WaitForAD {
    param (
        [Parameter(Mandatory=$true)]
        [String]
        $VMName,

        [Parameter(Mandatory=$true)]
        [System.Management.Automation.PSCredential]
        $Credentials

    )
    $VM = Get-VM -Name $VMName
    $Uptime = $VM.Uptime.TotalSeconds
    $Date = $(Get-Date).AddSeconds(-($Uptime))
    Write-Host "[$($VMName)]:: Auf Active Directory warten" -ForegroundColor Yellow -NoNewline
    Invoke-Command -VMName $VMName -Credential $Credentials -ArgumentList $Date -ScriptBlock {
        param($Date)
        do {
            do {
                Write-Host "." -ForegroundColor Yellow -NoNewline
                Start-Sleep -Seconds 5
                $AD = get-service ADWS, DNS, KDC, NETLOGON, NTDS
            } until ($AD[0].Status -eq "running" -and $AD[1].Status -eq "running" -and $AD[2].Status -eq "running" -and $AD[3].Status -eq "running" -and $AD[4].Status -eq "running")
            Write-Host "." -ForegroundColor Yellow -NoNewline
            Start-Sleep -Seconds 5
            $Event = Get-EventLog -LogName "Active Directory Web Services" -Source ADWS -After $Date -InstanceId 1073743024 -Newest 1
        } until ($Event.Message -match "Die angegebene Verzeichnisinstanz wird nun von Active Directory-Webdiensten bedient" -or $Event.Message -match "Active Directory Web Services is now servicing the specified directory instance")
    }
    Write-Host " -> Ok!" -ForegroundColor Yellow
}

[string]$VMName = "SERVER-VM01"
[System.Management.Automation.PSCredential] $tempCred = new-object -typename System.Management.Automation.PSCredential ("Domain\Administrator", (ConvertTo-SecureString P@ssw0rd! -AsPlainText -Force))

WaitForAD $VMName $tempCred

Link zum Download: WaitForAD

Aint nobody got time for dat

Aint nobody got time for dat

Older Posts »

Powered by WordPress