Latest version: 3.9, February 15th, 2024
I’m pleased to announce the availability of Install-Exchange15.ps1, a PowerShell script to perform a fully automated unattended setup of Exchange Server 2013, Exchange Server 2016, or Exchange Server 2019 (Desktop and Core) is supported).
The script takes care of:
- Installing requires Windows Server features
- Install Exchange Server prerequisites, e.g., .NET Framework 4.5.2/4.6.1/4.6.2/4.7.1/4.7.2/4.8/4.8.1 and Visual C++ Runtime 2012 or 2013, depending on roles, OS, and Exchange version to install.
- Install additional prerequisites and prepare Active Directory.
- Optionally install Exchange Server 2013 / 2016 / 2019.
- Optionally, install required fixes and perform post configuration, like setting your Power Plan to High Performance, reconfiguring the pagefile to best practices (memory + 10MB with a maximum of 32GB+10MB) if it is system managed, and performing .NET framework optimizations. Custom post-configuration is possible by modifying the script.
- On Windows Server 2016 and later, it will configure Windows Defender exclusions when present.
- For Exchange 2016 CU22 and Exchange 2019 CU11 and later, will install the required URL Rewrite 2 module.
- Finally, the script will clean things up, like removing the state file and setting the startup of Transport Service back to Automatic.
Usage
This script version requires a domain-joined Windows Server, an account to perform the installation (and optionally prepare Active Directory), and the location where the Exchange Server 2013/2016/2019 installation files are stored (e.g., a UNC path).
The syntax is as follows:
Install-Exchange15.ps1 -[InstallMultiRole|InstallMailbox|InstallEdge|InstallCAS|NoSetup|Recover] [-Organization <string>] [-MDBName <string>] [-MDBDBPath <string>] [-MDBLogPath <string>] [-InstallPath <string>] [-SourcePath <string>] [-TargetPath <string>] [-Credentials <pscredential>] [-IncludeFixes] [-NoNet461] [-NoNet471] [-NoNet472] [-NoNet48] [-NoNet481] [-DoNotEnableEP] [-DoNotEnableEP_FEEWS] [-UseWMF3] [-DisableSSL3] [-DisableRC4] [-DiagnosticData] [-SCP <string>] [-EdgeDNSSuffix <string>] [-Lock] [-SkipRolesCheck] [-AutoPilot] [<CommonParameters>]
Install-Exchange15.ps1 -InstallMultiRole -SourcePath <string> [-Organization <string>] [-InstallPath <string>] [-TargetPath <string>] [-AutoPilot] [-Credentials <pscredential>] [-IncludeFixes] [-NoNet461] [-NoNet471] [-NoNet472] [-NoNet48] [-NoNet481] [-DoNotEnableEP] [-DoNotEnableEP_FEEWS] [-UseWMF3] [-DisableSSL3] [-DisableRC4] [-DiagnosticData] [-Lock] [-SkipRolesCheck] [-Phase <int>] [<CommonParameters>]
A short description of the parameters:
- Organization (optional): Specifies the name of the Exchange organization to create. When omitted, the step to prepare Active Directory (PrepareAD) will be skipped.
- InstallMailbox: Specifies you want to install the Mailbox server role. This applies to Exchange 2013 as well as Exchange 2016.
- InstallCAS: Specifies you want to install the CAS role. This applies to Exchange 2013 only, ignored when installing Exchange 2016.
- InstallMultiRole: Specifies you want to install both Mailbox server and CAS roles. Applies to Exchange 2013 only.
- InstallEdge: Specifies to install the Edge Transport rule (Exchange 2013/2016).
- MDBName (optional): Specifies the name of the initially created database.
- MDBDBPath (optional): Specifies the database path of the initially created database (requires MDBName).
- MDBLogPath (optional): Specifies the log path of the initially created database (requires MDBName).
- InstallPath (optional): Specifies (temporary) location of where to locate – and when downloaded store – prerequisite files, the state file, and log files. The default location is C:\Install. You can also use a UNC path to use a central location, given the credentials have sufficient permissions to write at this location. This is ideal when you want the script to use previously downloaded hotfix files, for example, as some required hotfixes are quite large (e.g. KB3206632 for WS2016 ~ 1GB, KB2919355 for WS2012R2 ~ 700MB).
- NoSetup (optional): Specifies you only want to install prerequisites (and optionally prepare the Exchange organization), Exchange setup and post-configuration steps are not performed. You still need to specify SourcePath because the Exchange version will determine the prerequisites to install.
- Recover: Specifies you want to install this server in Recovery mode. The script will check if an Exchange server object is already defined.
- SourcePath: Specifies the location of the Exchange 2013 installation files. This can point to the location of setup.exe, or you can specify the Exchange ISO file.
- TargetPath: Specifies the location where to install the Exchange 2013.
- AutoPilot (switch): Specifies you want to automatically restart, log on using the credentials specified, and continue the installation. When not specified, you will need to restart, log on, and start the script manually each time (without parameters).
- Credentials (optional): Specifies credentials to use for automatic logon. Use DOMAIN\User or user@domain. When not specified, you will be prompted to enter credentials.
- IncludeFixes (optional): Depending on the operating system and detected Exchange version to install, will download and install recommended hotfixes.
- DiagnosticData (optional): This switch determines the initial Data Collection mode for deploying Exchange 2019 CU11, Exchange 2016 CU22, or later builds.
- DoNotEnableEP Do not enable Extended Protection on Exchange 2019 CU14+
- DoNotEnableEP_FEEWS Do not enable Extended Protection on the Front-End EWS virtual directory on Exchange 2019 CU14+
- SCP (optional) allows you to reconfigure the Service Connection Point record for Autodiscover after the Exchange setup has finished. Specify the full URI, e.g. https://autodiscover.contoso.com/autodiscover/autodiscover.xml. Use ‘-‘ to clear the SCP entries of the server.
- Lock (optional) locks the system when running script.
- NoNet481 (optional) prevents installing .NET Framework 4.8.1 and uses 4.8 when deploying Exchange 2019 CU14+
- NoNet48 (optional) to use .NET Framework 4.7.2, even when installing an Exchange version that is supported with .NET Framework 4.8.
- NoNET471 (optional) to use .NET Framework 4.6.2, even when installing an Exchange version which is supported with .NET Framework 4.7.1.
- NoNET472 (optional) to use .NET Framework 4.7.1, even when installing an Exchange version which is supported with .NET Framework 4.7.2.
- NoNET461 (optional) to use .NET Framework 4.5.2, even when installing an Exchange version which is supported with .NET Framework 4.6.1 or higher.
- DisableSSL3 (optional) to disable SSL3 protocol as per KB187498.
- DisableRC4 (optional) to disable RC4 cipher as per KB2868725.
- SkipRolesCheck (optional) to bypass membership checks for Schema Admin and Enterprise Admin roles.
- EdgeDNSSuffix specifies the DNS suffix to configure on the primary NIC.
Note that the script uses an XML file to store the (original) parameters used to start the script but also to keep track of the the process. Of course, if required, you can use predefined XML files to run the script without parameters.
Note that when not present, the script will try to download the prerequisites from the internet. When that isn’t possible or to save bandwidth, you can put them in the location defined by InstallPath and the script will detect and use them.
The post-configuration is currently adding IFilters for OneNote and Publisher (Mailbox) only. There are comments in the script where to add your own additional post-configuration steps.
For example, assume we want to start a fully unattended install of an Exchange Server 2013 Client Access server, using a network location for the Exchange Server 2013 source files. After setting the Execution Policy to Unrestricted and storing the script locally, we start the script using:
.\Install-Exchange15.ps1 –InstallCAS –SourcePath
'\\server\share\isos\Microsoft\Exchange2013\mu_exchange_server_2013_x64_dvd_1112105'
–AutoPilot –Verbose
The script will perform some checks and since AutoPilot was specified without using the Credentials parameter, the script will ask for credentials.

After entering the credentials, the required features will be installed. Since OrganizationName wasn’t specified, Active Directory preparation will be skipped.

After rebooting, the system will automatically log on using the credentials specified earlier and start the script (RunOnce registry key is utilized for this purpose). It will read the last known state from the XML file and will continue with the next phase, which is downloading (when not present) and installing the Exchange prerequisites.

Next, after rebooting and the automatic logon, Exchange will be installed from the source location.

When done, the system will perform post-configuration and finalization steps.
When running in AutoPilot mode, the system will automatically perform reboots and logons between the steps. Note that it may seem like a lot of reboots, but rebooting after installing Windows features and Exchange prerequisites is required anyway, so I also put reboots after the other milestones.
Customization
If you want to perform post-setup configuration of Exchange running Exchange cmdlets from the script, you need to tailor it to your needs. Locate the line which reads:
#Load-ExchangeModule
Uncomment this line so a proper Exchange Management Shell session will be set up to the local Exchange server. You can insert Exchange-related cmdlets after the Load-ExchangeModule line to configure your server. Be advised that you need to port modifications to new versions of the installation script.
Recovery
The script also supports recovery mode (/mode:RecoverServer). After checking the Exchange server object is present in Active Directory, installation will proceed as normal, with the exception of running setup in recovery mode. For example:
.\Install-Exchange15.ps1 -Recover -Autopilot -SourcePath \server1\sources\ex2019cu13.iso
Update
The script also supports update mode (/mode:Update). After checking the Exchange server object is present in Active Directory, and checking for presence of Exchange installation, installation will proceed as normal, with the exception of running setup in Update mode.
Feedback
Feedback is welcomed through the comments. If you have scripting suggestions or questions, do not hesitate to use the contact form.
Download
You can download Install-Exchange15.ps1 from TechNet or GitHub.
Revision History
See Technet Gallery page.

Hi,
Looks like a great script! Couple of quick questions:
With the update mode, will the script go through and place the server into maintenance mode etc prior to completing the upgrade?
Also, when running the script to install as a new server in existing DAG, will it mark the server as off-line/maintenance mode at end to allow post installation work e.g SSL certs receive connectors etc.
I am assuming that these sorts of task could be added manually to the script within “Customisation”?
LikeLike
1) No. that is actually a good point.
2) Yes. What the script can do is set the Autodiscover SCP record post-installation; any custom code can be put in the customization section, or call an external script to run for configuration etc. Since that is often very specific, I’ll leave that up to you.
LikeLike
Hi Michel!
The latest script (v3.8) doesn’t recognize the exchange version correctly. For Ex2016 CU23 I’m getting “ExSetup version: Exchange Server 2019 Public Preview (build 15.01.2507.006)” and for Ex2019 CU13 its “ExSetup version: Unknown version (build 15.02.1258.012)”
I’m using the localized DE version of Exchange Setup on localized Win2016 and Win2019, both DE as well.
The script omits the installation of the Rewrite-Module and starts Exchange Setup with the deprecated “/IAcceptExchangeServerLicenseTerms”.
LikeLike
Hi Michel!
I’ve found my problem. I accidentally called an old version of your script that was still buried in an old directory.
LikeLike
Great script, any new updates for it coming soon?
Thanks
LikeLike
Nothing yet, but might do a refresh when I have time.
LikeLike
I used the script several times and the only issue I have is that when using the credential switch it never auto logs into the server. I have to manually login, and then the script continues where it left off but I cant seem to get it to login after reboots. I’m using server 2022 with exchange 2019.
Thanks
LikeLike
Perhaps a policy configured that clears the automatic logon related registry keys?
https://learn.microsoft.com/en-us/troubleshoot/windows-server/user-profiles-and-logon/turn-on-automatic-logon
LikeLike
I caught my issue, i did not have the installpath switch in my command line. On another note I am trying to figure out a way to incorporate the ConfigureExchangeURLs.ps1 script with the install script but cant see a way to do it. Any thoughts that could help? Thanks
LikeLike
Odd. That parameter defaults to C:\Install. In the script, there’s a section for customizations. Uncomment the “Import-ExchangeModule” line if you need to load the EMS first, and then insert your own cmdlets or calls to external scripts in the mailbox, edge or common section, eg
& “$PSScriptRoot\ConfigureExchangeURLs.ps1” -InternalUrl outlook.contoso.com -ExternalUrl mail.contoso.com
LikeLike
Thanks Michael! It worked like a charm, just had to include the server switch for the ConfigureExchangeURLs.ps1 script. Is their a way to add the output of the script to the install exchange log? Unfortunately it doesn’t even show when the install script kicks off the configureURL script.
Thanks again, you’ve been amazing.
LikeLike
Depends on how that script returns output, but you might try with a simple
| Out-File $State[‘TranscriptFile’] -Append -ErrorAction SilentlyContinue
LikeLike
Hi Michael, I can see the configureurl script working when watching the install process but it does not write out the verbose to the install log.
On a another note, for the exchange 2019 install you don’t need to install the windows msmq feature as a prerequisite anymore. You can remove it from the script. Thanks for writing this script what a time saver!!
LikeLike
Calling external scripts does not catch their output and depends on which stream they send output to. “Old skool” redirection might work to catch everything, e.g.
& “.\ConfigureURLS.ps1” … 2>>&1 >> $State[‘TranscriptFile’]
(2 is the error stream and appends its output to the success stream (1), and the last appends success output (thus including errors) to the file indicated.
Thanks for the msmq notice- I’m aware, and a major version update with other changes is imminent.
LikeLike
Thanks so much Michael, cant wait for new script.
LikeLike
What are your thoughts on also adding import and enable SSL cert commands to the script?
LikeLike
If there is sufficient demand, things can always get added. Do wonder why you are not using GPOs to distribute the cert, and then in the post-config enable the cert for IIS,SMTP etc.
LikeLike
Hi Michael,
I tried using the updated script on 2025 server core and it errors and stops on configuring the windows features section at rsat clustering mgmt.
[ERROR] Feature RSAT-Clustering-Mgmt appears not to be installed
I dont doubt it could be an issue on my end. Any thoughts?
Thanks
LikeLike
FYI – I spun up a new windows 2025 server core ent and got the same results “[ERROR] Feature RSAT-Clustering-Mgmt appears not to be installed”. I also tried using the script after manually installing failover clustering to no avail.
LikeLiked by 1 person
I think I found the issue, the script keeps trying to install the windows features:
RSAT-Clustering-Mgmt
Windows-Identity-Foundation
even though I am using server core and it cant get past them.
LikeLike
FYI – Also seem to be having an issue with the -nosetup switch.
Thanks
LikeLike