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 )