I had an issue with a broken Exchange Server 2016 CU23. Or rather it was not fully installed. It was just a test environment, but I thought it would be useful or interesting to drill down on that issue.
I’ll guide you through my troubleshooting steps / thought process.
Try to continue Setup
The error message in detail:
Okay, so the setup tried to execute
ServiceControl.ps1. Where is that script located…? I don’t know right now, but I’ll find out later.
Check Exchange Server Setup Log
Let’s first check the Exchange Server Setup Log, at
In the log there is some more context of the previously failed command. So the variable
$RoleRoles (nice name) is certainly not empty:
The Setup also created a script to replicate that command. Neat! I navigated to the file at
I had to comment out one line which was just plaintext with the date/time (above
$roleList = [...]). I then tried to manually run that script.
And surely I got the same error as the setup before, but with slightly more details. The error occurs in line 302 of
ServiceControl.ps1. And now I also know where that
ServiceControl.ps1 script actually resided. Nice.
ServiceControl.ps1 resides in the Exchange Server
Bin-directory. Well that’s easy. Let’s look at that script. Line 301/302 are:
So the reversing of
$services fails. The error message from before told us the issue already:
Value cannot be null. So is it really null? I’ve set a PowerShell Debugging Breakpoint with the PowerShell ISE to see for myself.
OKAY, it is empty. What did I even expect here?
Then I looked at the definition of the function
Get-ServiceToControl, which starts at line 105.
That function is using the variable
$script:servicesToControl. That again is defined starting at line 56.
Ah okay, these are the actual Windows Service names for each Exchange Server Role. But that doesn’t really help now. So one step back to
Oh yeah wait. So if
$Active is set, only Windows Services that are not in the
Stopped are getting returned. Because of the failed Setup, most Exchange Services are
Disabled and surely none are running.
So… Could it be that easy? I imagine: If atleast ONE Exchange Service was running,
Get-ServiceToControl would NOT return an empty response, so the
[array]::Reverse($services) would NOT fail. Then the procedure of “Stopping Exchange Services” should be deemed successful - right?
Manually starting an Exchange Service
services.msc to enable and start the
Microsoft Exchange Active Directory Topology Service (
I tried to re-run
Start-PreFileCopy-20220622-0720250331374206211.ps1. It actually failed now with a different error. But that looks like missing dependencies/functions from the setup environment. Nothing too concerning.
Re-run Exchange Server Setup
So it just might work now, if running from within the Setup context. So I tried. Already looked promising after a bit, because it’s now at Step 2. I went to take break.
When I came back, there was no Exchange Setup running anymore. Weird. Did it crash? I checked the
C:\ExchangeSetupLogs\ExchangeSetup.log file again. Looks good now:
First I looked if the Services are now enabled and running as they should. Looks good.
Then I ran the Exchange Management Shell to run
Get-ExchangeServer. Looks good aswell.
Really weird how that check is implemented. IMO Microsoft could improve the Setup Experience here, if the Setup checks if there are any Services that are running and actually need to get stopped. Instead it crashes now, if there are no running Exchange Services.
I mean afterwards it always seems easy and obvious. But maybe I could’ve gotten to the goal faster if I had drawn a direct conclusion of the facts
- Setup fails at the step “Stopping Services”
- No Exchange Services are running
- = Thus no Services can get stopped
In the Microsoft Exchange context
Cafe stands for “Client Access Front End”. I was somehow not aware of that abbreviation.