Hi, folks!
There is a good example of Exchange installation inside of help files for xExchange module but it’s actually not valid for Exchange 2016:
- no installation for server roles and features = configuration fails
- Exchange 2016 does not have separate client access role anymore = wrong installation parameters and setup fails
- UCMA is required to be installed = errors during prerequisite check up
- not optimal LCM parameters
- no certificate management
- there is no variables passing via command line = not suitable for unattended setup
- …
So here is the fixed version of one .
/Has been tested on VM with up-to-date domain joined 2012 R2 guest machine.
//If you are not yet familiar with PowerShell DSC it’s recommended to review some facts before setting up and then do some additional steps:
0) Step for lazy persons
. Download link for all-in-one zip file
1) Install the following update (only for PowerShell v3 and v4.0) :
PackageManagement PowerShell Modules Preview – March 2016
2) Import or verify that the required modules are available :
- xExchange . It’s a custom module for installation and configuration Exchange environment (installation, DAG, settings and more)
- WindowsFeature . Built-in DSC resource that ensures and installs windows server roles/features
- Package . Built-in DSC resource to install program packages (msi,exe and etc)
- xPendingReboot. Custom module that reboots system if it is in the “pending reboot” status.
- To list installed custom DSC resources:
Get-DscResource|? {$_.ModuleName -NotMatch "PSDesired"} - To install custom DSC (internet connectivity is required):
Install-Module xExchange
- I prefer to save module for the further usage and then install or just copy to one of the PS module’s path
#save module to pre-created folder Save-Module xExchange -Path C:\DSC\Modules #Copy module to the one of the following folders (../Program Files/.. is recommended) $env:PSModulePath C:\Users\username\Documents\WindowsPowerShell\Modules; C:\Program Files\WindowsPowerShell\Modules; C:\Windows\system32\WindowsPowerShell\v1.0\Modules
3) Prepare folders. Script uses the following paths:
- “C:\Exch” – Exchange binaries,
- “C:\ExchInstall\Cert” – required files for import certificate
- “C:\UCMA” – UCMA installation files
4) Download Exchange media and copy setup files (C:\Exch in my case)
5) Extract UCMA package to another folder (script uses C:\UCMA)
6) (optional) Prepare certificate for securing MOF files. I use this module to create one and then export PFX and CER-files to “C:\ExchInstall\Cert”.
Note: If you don’t want to secure your MOF files you can comment out related strings in the main script (step 6, see comment blocks)
. .\New-SelfSignedCertificateEx.ps1
New-SelfsignedCertificateEx `
-Subject 'CN=localhost' `
-EKU 'Document Encryption' `
-KeyUsage 'KeyEncipherment, DataEncipherment' `
-SAN localhost `
-FriendlyName 'DSC certificate' `
-Exportable `
-StoreLocation 'LocalMachine' `
-StoreName 'My' `
-KeyLength 2048 `
-ProviderName 'Microsoft Enhanced Cryptographic Provider v1.0' `
-AlgorithmName 'RSA' `
-SignatureAlgorithm 'SHA256'
6) Create the new script (ps1) which contains the following strings
Note: RebootNodeIfNeeded has been set to “True” so LCM have rights to reboot your machine automatically.
<#
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|w|w|w|.|r|l|e|v|c|h|e|n|k|o|.|c|o|m|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
::Exchange 2016 Installation (DSC)
::Required modules: xExchange and xPendingReboot
#>
#Variables
param ()
#Domain and Netbios Names
$domainname=$args[0] #or get-domain if domain is existed.
$netbios=$DomainName.split(“.”)[0]
#Creds for Exchange install acoount
$pwd = ConvertTo-SecureString "Pass123" -AsPlainText -Force
$Creds = New-Object System.Management.Automation.PSCredential ("$netbios\Administrator", $pwd)
#Import the certificate for securing MOF (optional. related strings can be just commented out)
$CertPW=ConvertTo-SecureString “Pass123” -AsPlainText -Force
Import-PfxCertificate -Password $certpw -CertStoreLocation Cert:\LocalMachine\My -FilePath C:\ExchInstall\cert\publickey.pfx
#DSC starts here
Configuration InstallExchange
{
Import-DscResource -Module xExchange
Import-DscResource -Module xPendingReboot
Node $AllNodes.NodeName
{
#Sets certificate for LCM on every node
LocalConfigurationManager
{
CertificateId = $AllNodes.Thumbprint
RebootNodeIfNeeded = $true
ConfigurationMode = 'ApplyOnly'
}
#Installs Required Components for Exchange (note: there is 1 planned automatic reboot)
WindowsFeature ASHTTP
{
Ensure = 'Present'
Name = 'AS-HTTP-Activation'
}
WindowsFeature DesktopExp
{
Ensure = 'Present'
Name = 'Desktop-Experience'
}
WindowsFeature NetFW45
{
Ensure = 'Present'
Name = 'NET-Framework-45-Features'
}
WindowsFeature RPCProxy
{
Ensure = 'Present'
Name = 'RPC-over-HTTP-proxy'
}
WindowsFeature RSATClus
{
Ensure = 'Present'
Name = 'RSAT-Clustering'
}
WindowsFeature RSATClusCmd
{
Ensure = 'Present'
Name = 'RSAT-Clustering-CmdInterface'
}
WindowsFeature RSATClusMgmt
{
Ensure = 'Present'
Name = 'RSAT-Clustering-Mgmt'
}
WindowsFeature RSATClusPS
{
Ensure = 'Present'
Name = 'RSAT-Clustering-PowerShell'
}
WindowsFeature WebConsole
{
Ensure = 'Present'
Name = 'Web-Mgmt-Console'
}
WindowsFeature WAS
{
Ensure = 'Present'
Name = 'WAS-Process-Model'
}
WindowsFeature WebAsp
{
Ensure = 'Present'
Name = 'Web-Asp-Net45'
}
WindowsFeature WBA
{
Ensure = 'Present'
Name = 'Web-Basic-Auth'
}
WindowsFeature WCA
{
Ensure = 'Present'
Name = 'Web-Client-Auth'
}
WindowsFeature WDA
{
Ensure = 'Present'
Name = 'Web-Digest-Auth'
}
WindowsFeature WDB
{
Ensure = 'Present'
Name = 'Web-Dir-Browsing'
}
WindowsFeature WDC
{
Ensure = 'Present'
Name = 'Web-Dyn-Compression'
}
WindowsFeature WebHttp
{
Ensure = 'Present'
Name = 'Web-Http-Errors'
}
WindowsFeature WebHttpLog
{
Ensure = 'Present'
Name = 'Web-Http-Logging'
}
WindowsFeature WebHttpRed
{
Ensure = 'Present'
Name = 'Web-Http-Redirect'
}
WindowsFeature WebHttpTrac
{
Ensure = 'Present'
Name = 'Web-Http-Tracing'
}
WindowsFeature WebISAPI
{
Ensure = 'Present'
Name = 'Web-ISAPI-Ext'
}
WindowsFeature WebISAPIFilt
{
Ensure = 'Present'
Name = 'Web-ISAPI-Filter'
}
WindowsFeature WebLgcyMgmt
{
Ensure = 'Present'
Name = 'Web-Lgcy-Mgmt-Console'
}
WindowsFeature WebMetaDB
{
Ensure = 'Present'
Name = 'Web-Metabase'
}
WindowsFeature WebMgmtSvc
{
Ensure = 'Present'
Name = 'Web-Mgmt-Service'
}
WindowsFeature WebNet45
{
Ensure = 'Present'
Name = 'Web-Net-Ext45'
}
WindowsFeature WebReq
{
Ensure = 'Present'
Name = 'Web-Request-Monitor'
}
WindowsFeature WebSrv
{
Ensure = 'Present'
Name = 'Web-Server'
}
WindowsFeature WebStat
{
Ensure = 'Present'
Name = 'Web-Stat-Compression'
}
WindowsFeature WebStatCont
{
Ensure = 'Present'
Name = 'Web-Static-Content'
}
WindowsFeature WebWindAuth
{
Ensure = 'Present'
Name = 'Web-Windows-Auth'
}
WindowsFeature WebWMI
{
Ensure = 'Present'
Name = 'Web-WMI'
}
WindowsFeature WebIF
{
Ensure = 'Present'
Name = 'Windows-Identity-Foundation'
}
WindowsFeature RSATADDS
{
Ensure = 'Present'
Name = 'RSAT-ADDS'
}
#Installs UCMA. Don't forget to change path it if it is required
Package UCMA
{
Ensure= 'Present'
Name = 'Microsoft Unified Communications Managed API 4.0, Core
Runtime 64-bit'
Path= 'c:\UCMA\UcmaRuntimeSetup\ironmansetup.exe'
ProductID= 'ED98ABF5-B6BF-47ED-92AB-1CDCAB964447'
Arguments= '/q'
}
#Checks Exchange Setup Directory (can be changed it's necessary). No recurse.
File ExchangeBinaries
{
Ensure = 'Present'
Type = 'Directory'
Recurse = $false
SourcePath = 'C:\Exch'
DestinationPath = 'C:\Exch'
}
#Checks if a reboot is needed before installing Exchange
xPendingReboot BeforeExchangeInstall
{
Name = "BeforeExchangeInstall"
DependsOn = '[File]ExchangeBinaries'
}
#Does the Exchange install. Verify directory with exchange binaries
xExchInstall InstallExchange
{
Path = "C:\Exch\Setup.exe"
Arguments = "/mode:Install /role:Mailbox /OrganizationName:""$netbios"" /Iacceptexchangeserverlicenseterms"
Credential = $Creds
DependsOn = '[xPendingReboot]BeforeExchangeInstall'
}
#Sees if a reboot is required after installing Exchange
xPendingReboot AfterExchangeInstall
{
Name = "AfterExchangeInstall"
DependsOn = '[xExchInstall]InstallExchange'
}
}
}
#DSC Configuration data
$ConfigData=@{
AllNodes = @(
@{
NodeName = "*"
#Replace thumbprint with yours or use precreated cert
CertificateFile = "C:\ExchInstall\cert\publickey.cer"
Thumbprint = "FF0693E72BD283298323DF34B2A848F0F1B48E67"
PSDscAllowPlainTextPassword = $true
}
@{
NodeName = "localhost"
}
);
}
if ($Creds -eq $null)
{
#if creds are empty -> write to log Application/mozno udalit')
New-EventLog –LogName Application –Source “Exchange Installation”
Write-EventLog –LogName Application –Source “Exchange Installation” –EntryType Error –EventID 1 –Message “Credentials are empty”
}
#Compiles the example
InstallExchange -ConfigurationData $ConfigData -Creds $Creds
#Sets up LCM on target computers to decrypt credentials, and to allow reboot during resource execution
Set-DscLocalConfigurationManager -Path .\InstallExchange -Verbose
#Pushes configuration and waits for execution
Start-DscConfiguration -Path .\InstallExchange -Verbose -Wait
7) Run the script with the mandatory <domainname> parameter
Example: .\InstallExchange.ps1 contoso.com
8) Wait while LCM applies DSC configuration.
To retrieve the the current status use:
Get-DSCLocalConfigurationManager
and
- read logs (Applications and Services Logs – Microsoft – Windows – Desired State Configuration)
- Exchange creates it’s own setup logs on your system drive . check them in case of unexpected errors.
Until then,
have a nice weekend!
P.S. I have updated this script with DAG configuration and etc.. I’ll publish a new post later. Be in touch.
Good job, good post 🙂
Nice article! Where in the configuration script do you specify the installation path for Exchange? We do not use the default: C:\Program Files\Microsoft….Our install path is D:\Program Files\Microsoft….
find “Arguments” in the “InstallExchange” section and add /TargetDir:”D:\yourpath”
Thanks rlevchenko
Firstly, thank you for creating this, it’s IMMENSELY helpful!
But… How do I send this to multiple servers? If I want to install Exchange on Server1, Server2 and Server3 at the same time, using this same script, how do I make it applicable to multiple targer servers?
Have you seen the “second” part? (https://rlevchenko.com/2016/10/31/automate-exchange-2016-installation-and-dag-configuration-with-powershell-dsc/) + you can use a variable for NodeName or describe DSC configuration section for each node.
Yes, I have seen that, and I requested the scripts via the Contact Me page a few weeks ago, though I never received an email. However, I still do not understand how to configure multiple servers with this.
I’m sorry. I was extremely busy . Please drop me email again.
Nah, mate, no need to apologize. I wasn’t trying to be rude or anything. I was just pointing out that I still don’t understand how to make this apply to multiple servers. Are you saying that the node section is what does it?
@{
NodeName = ‘Server02’
}
@{
NodeName = ‘Server01’
}
Is that what I need? Will that generate the .mof files? (I think the answer is “no” but I’m not sure)
You have my email and I hope it helped. Let’s continue the discussion there. (however, I’m still busy..something special will be published in 1-2 weeks)
Excellent article, I feel you should make a detailed youtube video on this. Can this same technique be used for Exchange 2019?
keep up the great work 🙂
I think yes..it can be used for Exchange 2019 (you may need to install add.requirements thoug h + check this https://docs.microsoft.com/en-us/exchange/new-features/new-features?view=exchserver-2019 )