NTS.Tools.MSExchange.psm1
function Get-ExchangeCU { <# .Description downloads exchange cu from microsoft .Parameter Version version of the cu .Parameter Outpath path where the cu is stored .Example Get-ExchangeCU -Version 2019_CU12 -Outpath $Outpath .NOTES https://learn.microsoft.com/en-us/exchange/new-features/build-numbers-and-release-dates?view=exchserver-2019 #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateSet("2019_CU13", "2019_CU12", "2016_CU23")] [string] $Version, [Parameter(Mandatory = $true)] [string] $Outpath ) $ErrorActionPreference = 'Stop' if ($Outpath[-1] -eq "\") { $Outpath = $Outpath.Substring(0, $Outpath.Length - 1) } New-ItemIfNotExists -Path $Outpath -ItemType Directory $ExchangeCUFilePath = "$($Outpath)\Exchange-$($Version).iso" switch ($Version) { "2019_CU13" { $DownloadURL = "https://download.microsoft.com/download/7/5/f/75f4d77e-002c-419c-a03a-948e8eb019f2/ExchangeServer2019-x64-CU13.ISO" } "2019_CU12" { $DownloadURL = "https://download.microsoft.com/download/b/c/7/bc766694-8398-4258-8e1e-ce4ddb9b3f7d/ExchangeServer2019-x64-CU12.ISO" } "2016_CU23" { $DownloadURL = "https://download.microsoft.com/download/8/d/2/8d2d01b4-5bbb-4726-87da-0e331bc2b76f/ExchangeServer2016-x64-CU23.ISO" } Default { throw "no version was selected or not supported" } } try { Start-FileDownload -DownloadURL $DownloadURL -FileOutPath $ExchangeCUFilePath } catch { throw "error getting exchange cu files - $($PSItem.Exception.Message)" } Write-Verbose "finished download - check folder $($Outpath)" } function Install-ExchangePrerequisites { <# .Description use this function to install exchange windows feature prerequesits .Example Install-ExchangePrerequisites .NOTES https://learn.microsoft.com/en-us/exchange/plan-and-deploy/prerequisites?view=exchserver-2019 #> $Features = @( "Server-Media-Foundation" "NET-Framework-45-Features" "RPC-over-HTTP-proxy" "RSAT-Clustering" "RSAT-Clustering-CmdInterface" "RSAT-Clustering-Mgmt" "RSAT-Clustering-PowerShell" "WAS-Process-Model" "Web-Asp-Net45" "Web-Basic-Auth" "Web-Client-Auth" "Web-Digest-Auth" "Web-Dir-Browsing" "Web-Dyn-Compression" "Web-Http-Errors" "Web-Http-Logging" "Web-Http-Redirect" "Web-Http-Tracing" "Web-ISAPI-Ext" "Web-ISAPI-Filter" "Web-Lgcy-Mgmt-Console" "Web-Metabase" "Web-Mgmt-Console" "Web-Mgmt-Service" "Web-Net-Ext45" "Web-Request-Monitor" "Web-Server" "Web-Stat-Compression" "Web-Static-Content" "Web-Windows-Auth" "Web-WMI" "Windows-Identity-Foundation" "RSAT-ADDS" ) try { Write-Output "installing required features for exchange" Install-WindowsFeature -Name $Features | Out-Null } catch { throw $PSItem.Exception.Message } } function Initialize-ADForExchange { <# .Description used the exchange setup.exe to prepare ad for exchange installation or upgrade .Parameter SetupPath path to the exchange setup.exe .Parameter OrganizationName name of the exchange organization .Example Initialize-ADForExchange -SetupPath "$($Volume.DriveLetter):\Setup.exe" -OrganizationName "mw corp org" .NOTES #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string] $SetupPath, [Parameter(Mandatory = $true)] [string] $OrganizationName ) if (Test-Path -Path $SetupPath) { try { Write-Output "preparing ad - check logs at $($env:SystemDrive)\ExchangeSetupLogs for more details" if ($OrganizationName -eq "") { $Process = Start-Process -FilePath $SetupPath -ArgumentList "/PrepareAD /IAcceptExchangeServerLicenseTerms_DiagnosticDataOFF" -Wait -NoNewWindow -PassThru } else { $Process = Start-Process -FilePath $SetupPath -ArgumentList "/PrepareAD /IAcceptExchangeServerLicenseTerms_DiagnosticDataOFF /OrganizationName:`"$($OrganizationName)`"" -Wait -NoNewWindow -PassThru } if ($Process.ExitCode -ne 0) { $MessageCount = 5 $Content = Get-Content -Path "$($env:SystemDrive)\ExchangeSetupLogs\ExchangeSetup.log" $Message = ($Content | Select-String -Pattern "FAILED") | Select-Object -Last $MessageCount | ForEach-Object { $PSItem.ToString() } Write-Output "---" Write-Output "error preparing ad - last $($MessageCount) messages with 'failed':" Write-Output $Message throw "check logs at $($env:SystemDrive)\ExchangeSetupLogs for more details" } Write-Output "finished preparing ad" } catch { throw $PSItem.Exception.Message } } else { throw "cannot find $($SetupPath)" } } function Initialize-SchemaForExchange { <# .Description used the exchange setup.exe to prepare schema of ad for exchange installation or upgrade .Parameter SetupPath path to the exchange setup.exe .Example Initialize-SchemaForExchange -SetupPath "$($Volume.DriveLetter):\Setup.exe" .NOTES #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string] $SetupPath ) if (Test-Path -Path $SetupPath) { try { Write-Output "preparing schema - check logs at $($env:SystemDrive)\ExchangeSetupLogs for more details" $Process = Start-Process -FilePath $SetupPath -ArgumentList "/PrepareSchema /IAcceptExchangeServerLicenseTerms_DiagnosticDataOFF" -Wait -NoNewWindow -PassThru if ($Process.ExitCode -ne 0) { $MessageCount = 5 $Content = Get-Content -Path "$($env:SystemDrive)\ExchangeSetupLogs\ExchangeSetup.log" $Message = ($Content | Select-String -Pattern "FAILED") | Select-Object -Last $MessageCount | ForEach-Object { $PSItem.ToString() } Write-Output "---" Write-Output "error schema - last $($MessageCount) messages with 'failed':" Write-Output $Message throw "check logs at $($env:SystemDrive)\ExchangeSetupLogs for more details" } Write-Output "finished preparing schema" } catch { throw $PSItem.Exception.Message } } else { throw "cannot find $($SetupPath)" } } function Install-Exchange { <# .Description used the exchange setup.exe install exchange on the local server .Parameter SetupPath path to the exchange setup.exe .Example Install-Exchange -SetupPath "$($Volume.DriveLetter):\Setup.exe" .NOTES #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string] $SetupPath ) if (Test-Path -Path $SetupPath) { Write-Output "installing exchange - check logs at $($env:SystemDrive)\ExchangeSetupLogs for more details" Write-Output "this can take a while" $Process = Start-Process -FilePath $SetupPath -ArgumentList "/m:install /roles:mb /IAcceptExchangeServerLicenseTerms_DiagnosticDataOFF /InstallWindowsComponents" -Wait -NoNewWindow -PassThru if ($Process.ExitCode -ne 0) { $Content = Get-Content -Path "$($env:SystemDrive)\ExchangeSetupLogs\ExchangeSetup.log" $Message = ($Content | Select-String -Pattern "ERROR")[-1].ToString() throw "error installing exchange - $($Message)" } Write-Output "finished installing exchange" } else { throw "cannot find $($SetupPath)" } } |