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.

Does the /DoNotStartTransport persist? I want to install some servers BUT not have them route mail etc. i was planning on also adding some sections to net stop some other services. Have you looked into this, or have any pointers?
Thanks
LikeLike
Strangely enough for 1st server (read remark in help). For that purpose, I set transport to manual and only set them to automatic in last phase (disable this if you don’t want this to happen).
LikeLike
Hi ! Great Job Michel
But i’ve a little problem. The installation works fine, i had no errors during the installation.
But when i try to go on https://myserver.mydomain/ecp after log i have an Error 500
Have you got an idea ?
LikeLike
Are services up and running and healthy?
Try https://myserver.mydomain/ecp/healthcheck.htm
LikeLike
Hi! Nice script!
Trying to install using the Exchange 2013 CU10-installer and I get this error in the ExchangeSetup.log: [ERROR] Exchange organization name is required for this mode. To specify an organization name, use the /OrganizationName parameter.
The name I entered as organization didn’t validate and as such wasn’t processed.
I added the following line at line-position 200 (between the [paramater-definition and the [string]-line for $Organization):
[ValidatePattern(‘(?# Organization Name cannot contain special characters, only upper- or lowercase letters from A to Z, numbers 0 to 9, spaces but not at the beginning or end, a hyphen or a dash, and can be up to 64 characters, but not blank.)^[a-zA-Z0-9\-\–\—][a-zA-Z0-9\-\–\—\ ]{1,62}[a-zA-Z0-9\-\–\—]$’)]
It now looks like this:
[parameter( Mandatory=$false, ValueFromPipelineByPropertyName=$false, ParameterSetName=”NoSetup”)]
[ValidatePattern(‘(?# Organization Name cannot contain special characters, only upper- or lowercase letters from A to Z, numbers 0 to 9, spaces but not at the beginning or end, a hyphen or a dash, and can be up to 64 characters, but not blank.)^[a-zA-Z0-9\-\–\—][a-zA-Z0-9\-\–\—\ ]{1,62}[a-zA-Z0-9\-\–\—]$’)]
[string]$Organization,
After that, passing an invalid organization-name will trigger this error:
C:\Install\Install-Exchange15.ps1 : Cannot validate argument on parameter ‘Organization’. The argument “This is a very long name with more than 64 characters to show that it triggers an error onvalidation” does not match the “(?# Organization Name cannot caontain special characters, only upper- or lowercase letters from A to Z, numbers 0 to 9, spaces but not at the beginning or end, a hyphen or a dash, and can be up to 64 characters, but not blank.)^[a-zA-Z0-9\-\–\—][a-zA-Z0-9\-\–\—\ ]{1,62}[a-zA-Z0-9\-\–\—]$” pattern. Supply an argument that matches “(?# Organization Name cannot caontain special characters, only upper- or lowercase letters from A to Z, numbers 0 to 9, spaces but not at the beginning or end, a hyphen or a dash, and can be up to 64 characters, but not
blank.)^[a-zA-Z0-9\-\–\—][a-zA-Z0-9\-\–\—\ ]{1,62}[a-zA-Z0-9\-\–\—]$” and try the command again.
At line:1 char:58
+ .\Install-Exchange15.ps1 -InstallMultiRole -Organization $org -MDBName MDB01 -MD …
+ ~~~~
+ CategoryInfo : InvalidData: (:) [Install-Exchange15.ps1], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,Install-Exchange15.ps1
LikeLike
Nice enhancement, thanks!
LikeLike
Pingback: Installing Exchange 2013 prerequisites – Unified Communications Technologist
Tried to install Exchange on the drive which was formatted as ReSFS.
Setup just failed, found that in an Exchange setup log.
Something that the script is missing for the requirements check.
LikeLike
Thanks for the feedback. I can’t mimic all of Exchange setup’s prerequisite checks, but it tries to do the obvious ones. I’ll put this on the wish list. And as you found out, ReFS is not supported to store the binaries.
LikeLike
Hi Michel,
thx for this wonderful script!
I tried to install only pre-reqs in a New Lab for Exchange 2013 CU12 on a newly fresh server (WS2012R2), but it fails.
I looked at your code, and you give this example:
.EXAMPLE
.\Install-Exchange15.ps1 -NoSetup -Autopilot
But this is not working, and gives the following:
PS C:\ex2013lab> .\Install-Exchange15.ps1 -NoSetup -Autopilot
Script C:\ex2013lab\Install-Exchange15.ps1 called using [NoSetup, True] [AutoPilot, True]
Using parameterSet NoSetup
Running on OS build 6.3.9600
Performing sanity checks ..
Checking temporary installation folder ..
Checking running mode ..
Write-MyError : OrganizationName not specified and no Exchange Organization discovered
Also, that’s inside the install log:
2016-05-30 16:49:36Z: Performing sanity checks ..
2016-05-30 16:49:36Z: Checking temporary installation folder ..
2016-05-30 16:49:36Z: [VERBOSE] Checking Operating System .. 6.3.9600
2016-05-30 16:49:36Z: Checking running mode ..
2016-05-30 16:49:36Z: [VERBOSE] Can’t find Exchange Organization object
2016-05-30 16:49:36Z: [ERROR] OrganizationName not specified and no Exchange Organization discovered
Maybe the NoSetup mode is broken with your 2.31 script version ?
PS: I tried to add the Orginasation but then it asks for roles… and it seems roles parameter is not compatible with NoSetup parameter.
thx in advance.
LikeLike
Thanks for tthe feedback. NoSetup is intended for installing prereqs/preparation (w/Organization) only. I’ll have another look on the logic in there.
LikeLike
Thx for your reply Michel.
Yes I just would like to install prereqs. As this is a new test lab, no Organization is in place currently. But as I said, when addind the Organization parameter, then it asks for roles… and roles parameter is not compatible with NoSetup parameter.
LikeLike
Should be fixed in version 2.5
LikeLike
Hello,
I made a fork of this script with the following additions:
– Add validation for initial AutoPilot credentials
– Checks user for Enterprise-Admins and Schema-Admins group (starting at phase 3), because is user is not in Schema, then Exchange setup will fail, but script will start phase 4 anyway and re-fail…
Let me know if you want it.
LikeLike
Thanks for your script.
It is working fine when executed locally from Exchange box itself but is there any way to execute the same script along with all Arguments from remote machine.
Trying to execute below command but it is failing with error,
Invoke-Command -ComputerName autoex1 -ScriptBlock { C:\Utils\Install-Exchange15.ps1 -Organization DemoLab -InstallMultirole -MDBDBPath E:\Databases\MDB01 -MDBLogPath E:\Logs\MDB01 -MDBName MDB01 -InstallPath C:\Utils\ -AutoPilot -Credentials $Cred -SourcePath E:\Install\ -IncludeFixes -InstallFilterPack -Verbose}
PS C:\Users\Administrator>
Invoke-Command -ComputerName -ScriptBlock { C:\Utils\Install-Exchange15.ps1 -Organization DemoLab -InstallMultirole -MDBDBPath E:\Databases\MDB01 -MDBLogPath E:\Logs\MDB01 -MDBName MDB01 -InstallPath C:\Utils\ -AutoPilot -Credentials $Cred -SourcePath E:\Install\ -IncludeFixes -InstallFilterPack -Verbose} -credential donmainame\administrator
VERBOSE: No state file found at C:\Utils\\Install-Exchange15.ps1_state.xml
Script C:\Utils\Install-Exchange15.ps1 called using [Organization, DemoLab] [InstallMultiRole, True] [MDBDBPath, E:\Databases\MDB01] [MDBLogPath, E:\Logs\MDB01] [MDBName, MDB01] [In
stallPath, C:\Utils\] [AutoPilot, True] [Credentials, ] [SourcePath, E:\Install\] [IncludeFixes, True] [InstallFilterPack, True] [Verbose, True]
Using parameterSet CM
Running on OS build 6.3.9600
Performing sanity checks ..
Checking temporary installation folder ..
VERBOSE: Checking Operating System .. 6.3.9600
Checking running mode ..
VERBOSE: Can’t find Exchange Organization object
Exchange Organization will be: DemoLab
Checking if we can access Exchange setup ..
Exchange setup located at E:\Install\\setup.exe
ExSetup version: 15.00.0847.032 (Exchange Server 2013 Service Pack 1)
Checking roles to install
Checking domain membership status ..
Checking NIC configuration ..
Checking MDB log path ..
Checking MDB database path ..
Checking Exchange Forest Schema Version
Active Directory is not prepared
Checking Exchange Domain Version
Checking domain mode
Domain is in native mode
Checking Forest Functional Level
Can’t read Forest schema version, operator possible not member of Schema admin group
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Write-MyError
+ PSComputerName :
Forest is not Functional Level 2003 or later
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Write-MyError
+ PSComputerName :
LikeLike
To be honest, I’ve never tried it running in that manner. I’ll have a look later today.
LikeLike
Hi Michel
I needed to create your script as an function.
So i just wrapped the script from before the cmdletbindings to the end like this.
Function Install-Exchange15{
Script code….
}
I ran this command:
Install-Exchange15 -InstallMultiRole -SourcePath $CDRomPath -Organization “Tenant03” -MDBName “MDB1” -MDBDBPath “C:\MailboxData\MDB1\DB” -MDBLogPath “C:\MailboxData\MDB1\Log” -InstallPath “C:\Install” -AutoPilot -IncludeFixes -InstallFilterPack -Credentials $DomainCred -SCP “https://autodiscover.tenant03.com/autodiscover/autodiscover.xml”
But when i am using it, i get this error.
Install-Exchange15 : You cannot call a method on a null-valued expression.
At line:12 char:1
+ Install-Exchange15 -InstallMultiRole -SourcePath $CDRomPath -Organization “Tenan …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [Install-Exchange15], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull,Install-Exchange15
After debugging further, i got this error output.
Exception : System.Management.Automation.RuntimeException: You cannot call a method on a null-valued expression.
at System.Management.Automation.ExceptionHandlingOps.CheckActionPreference(FunctionContext funcContext, Excep
tion exception)
at System.Management.Automation.Interpreter.ActionCallInstruction`2.Run(InterpretedFrame frame)
at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
at System.Management.Automation.Interpreter.Interpreter.Run(InterpretedFrame frame)
at System.Management.Automation.Interpreter.LightLambda.RunVoid1[T0](T0 arg0)
at System.Management.Automation.PSScriptCmdlet.RunClause(Action`1 clause, Object dollarUnderbar, Object input
ToProcess)
at System.Management.Automation.PSScriptCmdlet.DoProcessRecord()
at System.Management.Automation.CommandProcessor.ProcessRecord()
TargetObject :
FullyQualifiedErrorId : InvokeMethodOnNull,Install-Exchange15
InvocationInfo : System.Management.Automation.InvocationInfo
ErrorCategory_Category : 7
ErrorCategory_Activity : Install-Exchange15
ErrorCategory_Reason : RuntimeException
ErrorCategory_TargetName :
ErrorCategory_TargetType :
ErrorCategory_Message : InvalidOperation: (:) [Install-Exchange15], RuntimeException
SerializeExtendedInfo : False
CategoryInfo : InvalidOperation: (:) [Install-Exchange15], RuntimeException
ErrorDetails :
ScriptStackTrace : at Install-Exchange15, : line 1519
at , : line 12
PipelineIterationInfo : {}
PSMessageDetails :
LikeLike
You wrapped it for SCOM and now it’s now working. Could it be one of the vars you provide is not set (DomainCred, CDROMPath)? What has become line 1519 in your customized script?
LikeLike
This is line 1519 in the function
Remove-Item $Statefile
In the function cleanup
LikeLike
Hi Michel
I think Powershell is having a bug.
I know says line 1520.
But find i do a search for the line in the function its really line 1631.
It is bugging in this line which make sense, duo to it is a function.
$ScriptName = $ScriptFullName.Split(“\”)[-1]
LikeLike
Nevermind this thread.
I did not think this through.
I cant make it as an functions, because i can see in the function Enable-RunOnce you are reusing the script. I cant do that with a function 🙂
In my office my coworkers would like to say “Buy us an screw up cake!”.
My plan is to use your perfect script for automatically deploying Exchange 2013 via Invoke commands with a remote PSSession.
I think I programatically needs to copy “Install-Exchange15.ps1” to the remote computer, and then script an invoke command, with the correct parameters.
How are you using this script in scripted rutines?
\Simon
LikeLike
Hi Michel
I succeded copying the script to the remote server and it is up and running.
Is they anyway i can get a status to know when the installation is completed?
\Simon
LikeLike
You could use a (writable) UNC path location for InstallPath – there, logging and the status file will be stored. You can monitor / follow the log file – being it on that UNC share location or locally (systemdrive c$ share) using a tool like tail or baretail.
LikeLike
Hi Michel
I’m in trouble again. I actually downloaded the latest available version of the script.
Script and parameters working fine when running the script manually on my other server.
But when running with an Invoke-Command i get this error.
C:\Scripts\Install-Exchange15.ps1 : Cannot index into a null array.
At line:22 char:21
+ . “C:\$ScriptsPathName\Install-Exchange15.ps1” -InstallMulti …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [Install-Exchange15.ps1], RuntimeException
+ FullyQualifiedErrorId : NullArray,Install-Exchange15.ps1
Exception : System.Management.Automation.RuntimeException: Cannot index into a null array.
at System.Management.Automation.ExceptionHandlingOps.CheckActionPreference(FunctionContext f
uncContext, Exception exception)
at System.Management.Automation.Interpreter.ActionCallInstruction`2.Run(InterpretedFrame fra
me)
at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedF
rame frame)
at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedF
rame frame)
at System.Management.Automation.Interpreter.Interpreter.Run(InterpretedFrame frame)
at System.Management.Automation.Interpreter.LightLambda.RunVoid1[T0](T0 arg0)
at System.Management.Automation.PSScriptCmdlet.RunClause(Action`1 clause, Object dollarUnder
bar, Object inputToProcess)
at System.Management.Automation.PSScriptCmdlet.DoProcessRecord()
at System.Management.Automation.CommandProcessor.ProcessRecord()
TargetObject :
CategoryInfo : InvalidOperation: (:) [Install-Exchange15.ps1], RuntimeException
FullyQualifiedErrorId : NullArray,Install-Exchange15.ps1
ErrorDetails :
InvocationInfo : System.Management.Automation.InvocationInfo
ScriptStackTrace : at Test-SchemaAdmin, C:\Scripts\Install-Exchange15.ps1: line 572
at Check-Sanity, C:\Scripts\Install-Exchange15.ps1: line 1319
at , C:\Scripts\Install-Exchange15.ps1: line 1716
at , : line 22
PipelineIterationInfo : {}
PSMessageDetails :
Cannot index into a null array.
Length
——
190
22
Before this error I printed my variables in an logfile on the remote server.
D: – Tenant03 – ExchangeInstall – tenant03.com\administrator – https://autodiscover.tenant03.com/autodiscover/autodiscover.xml
$SourcePath = “D:”
$Organization = “Tenant03”
$ExchangeInstallPath = “ExchangeInstall”
$DomainCred = tenant03\administrator #Printed credential username.
$SCP = “https://autodiscover.tenant03.com/autodiscover/autodiscover.xml”
LikeLike
In the log from the InstallPath this is the only output i get.
2016-08-12 21:10:45Z: Performing sanity checks ..
2016-08-12 21:10:45Z: Computer name is 003MS01.tenant03.com
2016-08-12 21:10:45Z: Checking temporary installation folder ..
2016-08-12 21:10:45Z: Operating System is 6.3.9600
2016-08-12 21:10:46Z: .NET Framework is 379893 (4.5.2)
2016-08-12 21:10:46Z: Script running in elevated mode
2016-08-12 21:11:15Z: Checking provided credentials
2016-08-12 21:11:15Z: Credentials seem valid
LikeLike
I can see the trail….
Via Check-Sanity -> Test-SchemaAdmin -> Get-ForestRootNC functions.
But if i manually copy paste your code to my remote server, it works…. Jus not via Invoke-Command….
LikeLike
Tested the Get-ForestRootNC function via Invoke-Command and the function have no trouble.
I think my debugging skills has reached an end, regarding your script VS Invoke-Command 😦
LikeLike
I removed my try catch and now i am getting this.
Script C:\Scripts\Install-Exchange15.ps1 called using [InstallMultiRole, True] [SourcePath, D:\] [Organization, Tenant03
] [MDBName, DB01] [MDBDBPath, C:\MailboxData\DB01\DB] [MDBLogPath, C:\MailboxData\DB01\Log] [InstallPath, c:\ExchangeIns
tall] [AutoPilot, True] [IncludeFixes, True] [InstallFilterPack, True] [Credentials, System.Management.Automation.PSCred
ential] [SCP, https://autodiscover.tenant03.com/autodiscover/autodiscover.xml%5D
Running on OS build 6.3.9600
Performing sanity checks ..
Computer name is 003MS01.tenant03.com
Checking temporary installation folder ..
Operating System is 6.3.9600
.NET Framework is 379893 (4.5.2)
Script running in elevated mode
Checking provided credentials
Credentials seem valid
Cannot index into a null array.
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : NullArray
+ PSComputerName : 192.168.0.131
Exception calling “.ctor” with “2” argument(s): “Value cannot be null.
Parameter name: binaryForm”
+ CategoryInfo : InvalidOperation: (:) [New-Object], MethodInvocationException
+ FullyQualifiedErrorId : ConstructorInvokedThrowException,Microsoft.PowerShell.Commands.NewObjectCommand
+ PSComputerName : 192.168.0.131
Current user is not member of Schema Administrators
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Write-MyError
+ PSComputerName : 192.168.0.131
LikeLike
And i just checked, that my domain credentials are member of Domain Admins, Enterprise Admins and Schema Admins.
LikeLike
It is something about the credential i believe….
Testet it OK locally on remote machine… Hmm….
Script C:\Scripts\Install-Exchange15.ps1 called using [InstallMultiRole, True] [SourcePath, D:\] [Organization, Tenant03
] [MDBName, DB01] [MDBDBPath, C:\MailboxData\DB01\DB] [MDBLogPath, C:\MailboxData\DB01\Log] [InstallPath, c:\ExchangeIns
tall] [AutoPilot, True] [IncludeFixes, True] [InstallFilterPack, True] [Credentials, System.Management.Automation.PSCred
ential] [SCP, https://autodiscover.tenant03.com/autodiscover/autodiscover.xml%5D
Running on OS build 6.3.9600
The requested operation cannot be completed. The computer must be trusted for delegation and the current user account m
ust be configured to allow delegation.
+ CategoryInfo : NotSpecified: (:) [ConvertFrom-SecureString], CryptographicException
+ FullyQualifiedErrorId : System.Security.Cryptography.CryptographicException,Microsoft.PowerShell.Commands.Conver
tFromSecureStringCommand
+ PSComputerName : 192.168.0.131
Performing sanity checks ..
Computer name is 003MS01.tenant03.com
Checking temporary installation folder ..
Operating System is 6.3.9600
.NET Framework is 379893 (4.5.2)
Script running in elevated mode
AutoPilot specified but no or improper credentials provided
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Write-MyError
+ PSComputerName : 192.168.0.131
LikeLike
Can you check if the instructions in this comment help:
http://stackoverflow.com/questions/8362057/what-security-setting-is-preventing-remote-powershell-2-0-from-accessing-unc-pat/8436654#8436654
LikeLike
I checked – to “double hop”, you have to enable CredSSP on the first computer (client) so it can pass creds to the other computer (server). Details of how to configure this are in help of Enable-WsmanCredSSP (as stated in the stackoverlow article as well), and it requires config changes on both systems. Be advised of the risks when enabling CredSSP: http://www.powershellmagazine.com/2014/03/06/accidental-sabotage-beware-of-credssp/
LikeLike
First off, awesome work! I really appreciate the contributions to the community. I think i may have come across a bug or possibly expected behavior. I am \launching the script with NoSetup option in which i am expecting to only install the prerequisites.
It appears that all prerequisites install with the exception of the .NET prerequisites for 4.6.1. it seems that the logic skips the .NET identification due to the MajorSetupVersion not being enumerated if NoSetup is run. this causes Install461 not to be set and the script follows the 4.5.2 branch which doesnt require the hotfixes, and it also adds the 4.6.1 blockade to a server that already has 4.6.1 installed 🙂
My notes:
Excerpt From Log (that apply to my testing)
.NET Framework is 394271 (4.6.1)
Exchange setup version (15.01.0466.034) doesn’t support .NET Framework 4.6.1
.NET Framework 4.5.2 or later detected
Set installation blockade for .NET Framework 4.6.1 (KB3133990)
*******************************************************************************
The last entry from above is inaccurate evaluation because EX2016_CU2 does support 4.6.1. with appropriate hotfixes
To debug this i first looked at where the 461 code for installing the updates was in the script:
If( @($WS2008R2_MAJOR, $WS2012_MAJOR, $WS2012R2_MAJOR) -contains $MajorOSVersion) {
$TempInstall461= $False
If( ($State[“MajorSetupVersion”] -ge $EX2016_MAJOR -and (is-MinimalBuild $State[“SetupVersion”] $EX2016SETUPEXE_CU2)) -or
($State[“MajorSetupVersion”] -eq $EX2013_MAJOR -and (is-MinimalBuild $State[“SetupVersion”] $EX2013SETUPEXE_CU13))) {
If( $State[“NoNet461”]) {
Write-MyOutput “.NET Framework 4.6.1 supported, but NoNet461 specified – will use .NET Framework 4.5.2”
}
**** Else {
Write-MyOutput “Exchange setup version ($($State[“SetupVersion”])) found, will use .NET Framework 4.6.1″
$State[“Install461”]= $True
}
}
Else {
If( $State[“NoNet461”]) {
Write-MyWarning “Ignoring NoNet461 switch: Exchange setup version ($($State[“SetupVersion”])) doesn’t support .NET Framework 4.6.1″
}
Else {
Write-MyOutput “Exchange setup version ($($State[“SetupVersion”])) doesn’t support .NET Framework 4.6.1″
}
My run should have followed the Else branch above (denoted with ****) and set $State[“Install461”]= $True, but it failed the condition because $State[“MajorSetupVersion” are only set when “NoSetup” is not being run and you are actually installing exchange.
I guess i would just think that the .NET hotfixes should be included as part of the pre-req run as they are pretty large downloads and nice to get out of the way prior to the actual exchange install.
I could be wrong as im not the greatest with powershell but thought i would forward along…
LikeLike
Ugh, thanks for catching that! – Check out 2.53
LikeLike
Nice! Thanks again for the contribution, it works great!
LikeLike
Hi Michel,
Nice script but having a slight problem with Phase 4 – the actual Exchange install on v2.7.
Invalid parameter.
Installer Log
2016-11-15 14:52:57Z: Installing Exchange
2016-11-15 14:52:57Z: Installing Microsoft Exchange Server (15.0)
2016-11-15 14:52:57Z: [VERBOSE] Executing C:\xch\xchbinaries\setup.exe /mode:install /roles:Mailbox,ClientAccess /IAcceptExchangeServerLicenseTerms /InstallWindowsComponents /MdbName:AC01DAGDB2 /DBFilePath:”M:\ExDB\AC01DAGDB2\AC01DAGDB2.edb” /LogFolderPath:”M:\EXDB\AC01DAGDB2\Log” /TargetDir:”e:\program files\Microsoft Exchange Server\” /DoNotStartTransport
2016-11-15 14:53:07Z: [VERBOSE] Process exited with code 1
2016-11-15 14:53:07Z: [ERROR] Problem installing Exchange. Please consult the Exchange setup log, i.e. C:\ExchangeSetupLogs\ExchangeSetup.log
Exchange Log
[11/15/2016 14:53:06.0147] [0] The registry key, HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\ExchangeServer\V15\Setup, wasn’t found.
[11/15/2016 14:53:06.0407] [0] RuntimeAssembly was started with the following command: ‘/mode:install /roles:Mailbox,ClientAccess /IAcceptExchangeServerLicenseTerms /InstallWindowsComponents /MdbName:AC01DAGDB2 /DBFilePath:M:\ExDB\AC01DAGDB2\AC01DAGDB2.edb /LogFolderPath:M:\EXDB\AC01DAGDB2\Log /TargetDir:e:\program files\Microsoft Exchange Server /DoNotStartTransport /sourcedir:C:\xch\xchbinaries’.
[11/15/2016 14:53:06.0422] [0] [ERROR] The parameter ‘donotstarttransport’ cannot have a value.
[11/15/2016 14:53:06.0422] [0] The registry key, HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Exchange\v8.0, wasn’t found.
[11/15/2016 14:53:06.0422] [0] The registry key, HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\ExchangeServer\v14, wasn’t found.
[11/15/2016 14:53:06.0422] [0] Setup checks failed: Invalid command line arguments.
I can see /DoNotStartTransport in the script but not where it adds the /sourcedir:C:\xch\xchbinaries at the end. And I can’t find anything from MS that states that /donotstarttransport has to be in a particular place.
Also I would have thought that the /TargetDir should have quotes since there are spaces. The installer log suggests that it has them but it doesn’t carry across to the setup command line according to the Exchange log. Maybe the log just doesn’t log them of course. 🙂
LikeLike
Pingback: Results Install-Exchange15 survey | EighTwOne (821)
Great effort Michel, Thanks a lot.
but according to my read, found somewhere written filter pack is not at all recquired in exchange 2016 CU5. then why its considering installing and that too mandatory. my setup failed on filterpack…
exchange got inbuilt features now so advise is to do not install filterpack additonally because you always have to care of filter pack updated and new versions releases too .. its like a dependency.
thaughts?
LikeLike
Thanks for the feedback. It was originally added to add and register OneNote and Publisher filter drivers for older versions of Exchange 2013.
Since then, support for those types was added in the product and installing the driver was deprecated (check supported file types using Get-SearchDocumentFormat).
Might be time to get rid of the switch 🙂
LikeLike
Seems that it is downloading cumulative update (KB3206632) to Server 2016 that is already updated with the latest CU (to date). After that the script just exits.
LikeLike
Thanks for the feedback, I’ll have a look how to properly deal with WS2016 CUs incorporating KBs
LikeLike
Check this from Keith Garner
LikeLike
It doesn’t install or check for .Net 4.6.2 (required) when installing version 2013 CU17. Install just stops with no messages.
LikeLike
New version with Ex2013CU17 support is coming
LikeLike
Pingback: Building an Ultra Secure Microsoft Exchange Server | Jonathan Hassell
Good Job, Michel!
What about to place your script to GitHub? I’m like to see change history and add the Pull Requests to improve your project.
===
Pavel
LikeLike
Putting stuff on GitHub is on the agenda
LikeLike
Hi Michel, first of all: Nice script! You added targetpath support for recover mode but using targetpath with recover is not valid: “Parameter set cannot be resolved using the specified named parameters.”. It seems that the parameterset is missing for the targetpath switch in script version 2.99.2. Could you please check that?
LikeLike
Thanks – I’ll have a look
LikeLike
I added the paramter set for testing and noticed that you removed the setup switch /InstallWindowsComponents when using the Recover switch. Is that intended? If yes, why?
LikeLike
Not intentional, omission – up for vNext, thanks !
LikeLike
Hi Michael,
Would it be possible to add a switch to NOT check for membership of Enterprise Admins and Schema Admins?
e.g. An AD team will do any schema updates etc. beforehand and won’t add the install account to those groups.
LikeLike
Makes sense. Noted for next release, thanks for your feedback.
LikeLike
Neill, Michel,
see my #PR at https://github.com/michelderooij/Install-Exchange15/pull/3
LikeLike
Thanks for this great script!! I used it without issue on an Exchange 2016 deplyment and the result was excellent. Getting ready to try the newly updated on another 2016 ddployment.
LikeLike
Hey, getting FilePath-Error for EX-Setup with EX19 preview on Server2016 Core. Did not had this error with older setups/script versions.
Write-MyError : Can’t find Exchange setup at C:\install\EX
At C:\install\Install-Exchange15.ps1:1766 char:13
+ Write-MyError “Can’t find Exchange setup at $($State[‘Sou …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Write-MyError
regards
LikeLike
seems, that backslash is missing in script before
If(! (Test-Path “$($State[‘SourcePath’])\setup.exe”)) {
Write-MyError “Can’t find Exchange setup at $($State[‘SourcePath’])”
Exit $ERR_MISSINGEXCHANGESETUP
}
LikeLike
What did you specify as source location?
LikeLike
hey,
UCMA 4 Setup from download does not work for Server core. so you have to use the setup included in the install media.
Can you build up a check for this an install from the apropriate source?
regards
LikeLike
What you mean? If OS is core, it installs UCMA provided with the Ex2019 iso
LikeLike
before installing the UCMA it is nessecary to install Media Foundation, seems, that your script does not do that before?!
regards
LikeLike
There is a typo in line 2616 as “{A749D8E6-B613-3BE3-8F5F-045C84EBA29B}” appears twice in this statement…
If ( $State[“VCRedist2013”] ) {
Package-Install “{A749D8E6-B613-3BE3-8F5F-045C84EBA29B}|{5740BD44-B58D-321A-AFC0-6D3D4556DD6C}|{CB0836EC-B072-368D-82B2-D3470BF95707}|{929FBD26-9020-399B-9A7A-751D61F0B942}|{A749D8E6-B613-3BE3-8F5F-045C84EBA29B}” “Visual C++ 2013 Redistributable” “vcredist_x64_2013.exe” “https://download.microsoft.com/download/2/E/6/2E61CFA4-993B-4DD4-91DA-3737CD5CD6E3/vcredist_x64.exe” (“/install”, “/quiet”, “/norestart”)
}
Also I’m having an issue as the install of vcredist_x64_2013 on my Windows 2016 Datacenter server. The install seems to work without errors but these two registry keys “{A749D8E6-B613-3BE3-8F5F-045C84EBA29B}” and {929FBD26-9020-399B-9A7A-751D61F0B942} are not created. Your script is looking for these keys and tries to reinstall this package and then fails.
2018-10-23 01:24:04Z: [VERBOSE] Checking if package {929FBD26-9020-399B-9A7A-751D61F0B942} is installed ..
2018-10-23 01:24:05Z: [ERROR] Problem installing Visual C++ 2013 Redistributable – For fixes, check C:\Windows\WindowsUpdate.log; For .NET Framework issues, check ‘Microsoft .NET Framework 4 Setup’ HTML document in C:\Users\username\AppData\Local\Temp
I’m reluctant to just create the registry files which is what this URL suggests… https://zzz.buzz/notes/vc-redist-packages-and-related-registry-entries/#x64-120305010
Please help
Brian
LikeLike
Thanks for catching the duplicate. VC++ comes in many forms, and every package has its own GUID. Therefor, I check on these GUIDs (which I know of). Only one of these should be present to indicate VC++2013 is there; if it’s not, it’s not installed (or as said, I don’t check for that GUID). The error with VC++ could be because it’s already installed. Still looking for a better way to detect VC++2013 (and 2012 and 2010 for that matter), as this becomes a bit messy 🙂
LikeLike
Pingback: Installing Exchange 2016 in the lab – Notes from MWhite
Can you check lines 1854 and 1859 and see if the part State[‘SourcePath’] is missing a $ before State?
LikeLike
It was, thanks for catching that
LikeLike
Also I don’t think the latest version properly detects Exchange 2013 CU21, it keeps saying its Exchange 2016.
LikeLike
Is that a localized version? English version of exsetup.exe reports 15.0.1395.4 (which is being matched on)
LikeLike
Version detection logic rewritten; should be OK in 3.1.0+
LikeLike
Hi Michel,
Hopefully just me but the Get-VCRuntime function in v3.00.3 is identifying the Visual C++ 2013 pre-req for CU21 as being already installed when it isn’t and obviously Exchange 2013 then refuses to install.
If I run this which I used for checking whether it was present for a CU21 update I get $null
$VisualCUpdatePresent = Get-WmiObject -Class win32_product|where-object {$_.identifyingnumber -eq “{929FBD26-9020-399B-9A7A-751D61F0B942}”}
Registry shows only v11.0 under the HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\ path
Regards
NT
LikeLike
Hi! I tried to use your script but sadly run into a error after the preparations:
Checking for pending reboot ..
Installing Exchange
Installing Microsoft Exchange Server (15.1)
Unhandled Exception: System.IO.FileNotFoundException: Could not load file or assembly ‘Microsoft.Exchange.Setup.Bootstrapper.Common, Version=15.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad
364e35’ or one of its dependencies. The system cannot find the file specified.
Write-MyError : Exchange Setup exited with non-zero value or Install info missing from registry: Please consult the Exchange setup log, i.e. C:\ExchangeSetupLogs\ExchangeSetup.log
At C:\install\Install-Exchange15.ps1:1186 char:17
+ … Write-MyError ‘Exchange Setup exited with non-zero value …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Write-MyError
I cant find the error. Am I missing something? Trying to install the latest 2016 cu 11 file on a patched windows server 2016.
LikeLike
Should be ok. How did you try running it; from UNC location, mounted ISO or by specifying the ISO file?
LikeLike
Hello Michel,
Thanks for this great script! I am facing a small issue with the script as following:
PS E:\> .\Install-Exchange15.ps1 -NoSetup -SourcePath ‘D:\’ -Verbose
VERBOSE: State information loaded from C:\Install\SERVER_Install-Exchange15.ps1_state.xml
Script E:\Install-Exchange15.ps1 v3.00.2 called using [NoSetup, True] [SourcePath, D:\] [Verbose, True]
VERBOSE: Using parameterSet NoSetup
Running on OS build 10.0.14393
VERBOSE: Loaded assemblies for configuring wallpaper
VERBOSE: Continuing from last successful phase 3
Performing sanity checks ..
Computer name is SERVER.NAME.COM
Checking temporary installation folder ..
Operating System is 10.0.14393
Server core mode: False
.NET Framework is 461814 (4.7.2)
Script running in elevated mode
User is member of Schema Administrators
User is member of Enterprise Administrators
Computer is located in AD site HQ
Exchange Organization is: Organization
Checking if we can access Exchange setup ..
Exchange setup located at D:\setup.exe
ExSetup version: Exchange Server 2019 RTM (build 15.01.1591.010)
Not checking roles (NoSetup, Recover or Upgrade mode)
Checking domain membership status ..
Checking NIC configuration ..
Checking Exchange Forest Schema Version
Exchange Forest Schema Version is 15332
Checking Exchange Domain Version
Exchange Domain Version is 13236
Checking domain mode
Domain is in native mode
Checking Forest Functional Level
Forest Functional Level is 2012 R2 or later
Checking for pending reboot ..
Installing Exchange
Installing Microsoft Exchange Server (15.1)
Microsoft Exchange Server 2016 Cumulative Update 11 Unattended Setup
An empty value is specified for parameter ‘roles’.
Setup checks failed: Invalid command line arguments.
Please type ‘setup.exe /help’ for more information.
Write-MyError : Exchange Setup exited with non-zero value or Install info missing from registry: Please consult the Exchange setup log, i.e. C:\ExchangeSetupLogs\ExchangeSetup.log
At E:\Install-Exchange15.ps1:1187 char:17
+ … Write-MyError ‘Exchange Setup exited with non-zero value …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Write-MyError
LikeLike
Odd- I’ll have a look but due to holidays can take a while
LikeLike
Thanks Michel for the quick response!
I just want to share my workaround that fixed my issue. So in the line # 1167
$Params= ‘/mode:install’, “/roles:$RolesParm”, ‘/IAcceptExchangeServerLicenseTerms’, ‘/DoNotStartTransport’, ‘/InstallWindowsComponents’
I changed the parameter /roles:$RolesParm to be /roles:Mailbox as following:
$Params= ‘/mode:install’, “/roles:Mailbox”, ‘/IAcceptExchangeServerLicenseTerms’, ‘/DoNotStartTransport’, ‘/InstallWindowsComponents’
Again, many thanks for this helpful tool you made.
Regards,
Waddah
LikeLike
Hi Michiel,
I’ve noticed that there is a url to one of the hotfixes broken.
Its for Windows 8.1 x64 Edition (KB3041832).
And i have been able to download it by changing it to this one:
http://download.windowsupdate.com/c/msdownload/update/software/htfx/2015/04/windows8.1-kb3041832-x64_67dff11777c5aca0f86f2b20862de4a7959fa2ea.msu
Regards,
Mark
LikeLike
I am trying to install CU15 for exchange 2016 and getting stuck on this patch, I have manually downloaded but it says it is not applicable for my version of windows, which is 2012 r2 with all patches installed? is there away to skip this check?
LikeLike
You should be able to install Ex2016CU15 on WS2012R2
https://docs.microsoft.com/en-us/exchange/plan-and-deploy/supportability-matrix?view=exchserver-2019#supported-operating-system-platforms
LikeLike
Hi Michel,
Unless I’m mistaken you don’t seem to have updated the script for Exchange 2013 CU22 etc?
Regards
Neill
LikeLike
Not yet, as I’m out of country – it’s on the todo
LikeLike
Hi Michel,
in the line: If( Get-Command -Cmdlet Add-MpPreference -ErrorAction SilentlyContinue) you have to check for -Name and not -CmdLet. In case a server does NOT have the Windows Defender binaries and you run Get-Command -Cmdlet Add-MpPreference you simply get a list of all cmdlets on the system and not an error so it simply assumes that Defender is present and will start to try and make exclusions.. that obviously fails.
When I change that line into:
If( Get-Command -Name Add-MpPreference -ErrorAction SilentlyContinue)
it correctly handles the absence of Defender.
Thanks for the script!
Regards,
Eric
LikeLike
Makes sense 🙂 Thanks for the feedback
LikeLike
Pingback: Useful PowerShell scripts – ITom Blog
Pingback: Dowst.Dev | PowerShell Weekly – September 20, 2019
Hi Michel,
I’m just about to upgrade my Exchange environment (which I originally set up with your script, too ;-)) and ran into an error when determining the Exchange Version (using your current version 3.2.2):
… A null key is not allowed in a hash literal.
At line:47 char:9…
… You cannot call a method on a null-valued expression.
At line:51 char:7…
After I checked the code I noticed that though you added the new build number for Exchange 2019 CU3 but you didn’t change corresponding variable. I also know copy/paste problems :-). After changing line 613 from $EX2019SETUPEXE_CU2 to $EX2019SETUPEXE_CU3 the script runs without error. Perhaps you want to fix that.
And again thanks for the script!
Daniel
LikeLike
Ugh, thanks for catching that!
LikeLike
I must be doing something wrong. The script ran through a few reboots, but then just quit. Never installed Exchange, and all I am left with is a background stating “Setup Exchange Server 2016 Cumulative Update 14, phase 4”
LikeLike
Ah. I get this…
Write-MyError : Exchange Setup exited with non-zero value or Install info missing from registry: Please consult the
Exchange setup log, i.e. C:\ExchangeSetupLogs\ExchangeSetup.log
At C:\temp\Install-Exchange15.ps1:1233 char:17
+ … Write-MyError ‘Exchange Setup exited with non-zero value …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Write-MyError
LikeLike
Derp. I figured it out. I have Windows Server 2019….Exchange 2016 doesn’t install on it.
LikeLike
Hi Michel,
I tryed your script but there is a problem with downloading a patch usin Bits.
2020-01-26 17:44:04Z: Package CPU usage is high when you use RPC over HTTP protocol in Windows 8.1 or Windows Server 2012 R2 not found, downloading to windows8.1-kb3041832-x64_67dff11777c5aca0f86f2b20862de4a7959fa2ea.msu
2020-01-26 17:44:04Z: [VERBOSE] Source: http://download.windowsupdate.com/c/msdownload/update/software/htfx/2015/04/windows8.1-kb3041832-x64_67dff11777c5aca0f86f2b20862de4a7959fa2ea.msu
2020-01-26 17:44:17Z: Installing CPU usage is high when you use RPC over HTTP protocol in Windows 8.1 or Windows Server 2012 R2 from C:\Install
2020-01-26 17:44:17Z: [WARNING] C:\Install\windows8.1-kb3041832-x64_67dff11777c5aca0f86f2b20862de4a7959fa2ea.msu not found
I can download and install it manualy. Just wanted to inform you.
LikeLike
Thanks for mentioning, might need to sanitize the current list of recommended hotfixes.
LikeLike
Hi Michel, the Exchange 2016 versions in lines 703 and 704 are incorrect. The CU14 key is mentioned twice and CU16 in missing. This results in the error: DuplicateKeyInHashLiteral.
Could you update those lines pls?
Thanks!
LikeLike
Already addressed in 3.2.5 – https://github.com/michelderooij/Install-Exchange15
LikeLike
Is it possible to run this script against 2nd, 3rd etc. servers in an organisation and have no databases installed?
LikeLike
All I really want to do is create extra servers to become DAG members
LikeLike
There will always be a database installed as part of the installation process; it’s not too much work to remove it in the post-configuration.
LikeLike
Thanks, I’ll adjust accordingly
LikeLike
Another thing, sorry.
Does the source path have to be local, or can it be a UNC path to a share?
I’ve tried “\\servername\sharename\folder” and ‘\\servername\sharename\folder’ within the command but both return the same error in the ExchangeSetup.log
“F:\TargetPath /sourcedir:\\servername\sharename\folder” is not an acceptable path. You must use an absolute, local, long file path, that does not contain ‘~’.
Parameter name: Path
Thanks
LikeLike
Hi Michel, the installation of Exchange 2019 also requires VCRuntime 2012. The script v3.2.5 line 2565 now says: ‘$State[“MajorSetupVersion”] -eq $EX2016_MAJOR’. I had to change that to ‘$State[“MajorSetupVersion”] -ge $EX2016_MAJOR’ to set ‘$State[“VCRedist2012”]= $True’. Now the installation continues.
Usually I manually install the prerequisites already before starting your script so didn’t run in to this issue before.
LikeLike
Oops, you’re right. Incorporated in 3.2.6.. Thanks.
LikeLike
Pingback: Exchange 2019 – Automated Install – Troublenet
Hi there!
Just posting my experience with the script so far:
Installing Exchange 2016 CU19
Here’s my parameter set:
.\Install-Exchange15.ps1 –InstallMailbox –SourcePath “F:\” -AutoPilot -MDBName “MDB01” -MDBDBPath “E:\DB” -MDBLogPath “E:\Logs” -Credentials $cred -IncludeFixes -Verbose
now to the conclusion:
– prerequisite check didn’t recognize that vc++ 2013 was installed and was failing to download via BITS. When i pasted the file in C:\Install it continued without problems
– The Autopilot parameter didn’t work at all. I had to reboot the server manually and had to restart the script after every phase
– Parameters MDBName, MDBDBPath and MDBLogPath didn’t work either. It just created a default database under C:\Program Files\Microsoft\Exchange Server\V15\Mailbox
In the end it seems there is no “finish” on the script, i’m just getting an error :
Current phase is 7 of 3
Write-MyError : Unknown phase (7)
In C:\_install\Install-Exchange15.ps1:2997 Zeichen:13
+ Write-MyError “Unknown phase ($($State[“InstallPhase”]))”
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Write-MyError
Other than that, the script finished the install
Any idea what might’ve gone wrong?
Regards,
Chris
LikeLike
Thanks for your feedback. Made a note re VC++2013. On installation, what do the logs say; aborting at step 3 = problem with ExSetup – see Exchange Setup log.
For AutoPilot to work, provided credentials need to be able to log on interactively, there is no GPO blocking automatic log on, source path (F) drive is available for the (domain) credentials you provided (and which are used to log on.. provided it can log on), amongst other things.
LikeLike