December 3, 2008

Exchange 2003 installed on a domain controller – services fail to start…

Consider the following scenario – you have an Exchange 2003 server installed on your Domain Controller – when you reboot the server you find that your Exchange services will not start automatically. When you review the Application Event log you see a number of errors mainly from the DSAccess and DSProxy services complaining that the Topology Discovery Failed -or– that all domain controllers are not responding – below is an example of one of the errors that you may see:

This is a common problem when Exchange 2003 is installed on a DC – this is one of the many reasons why normally Exchange should not be deployed in this manner, but, there are scenarios where companies have little choice but to adopt this model (money and resources for example).

What causes the issue:

Ok, when you install Exchange on a Domain controller the DSAccess and DSProxy services will not load balance or fail-over to another DC (I believe that this is due to the DSAccess process always electing to use the Nearest DC and GC (if you install Exchange on a Domain Controller it must also be a Global Catalog). Of course, when you reboot a Domain Controller, the Active Directory Service (LSASS.exe) also needs to startup – if the Exchange Services begin to start BEFORE the AD Service has started you will get the above errors (as Exchange has a total dependency on AD).

Has Microsoft Addressed This?

I think that some provision for this scenario might have been made in Exchange 2003 Service Pack 1 or 2 – however the provision it would seem was to allow for the Exchange services to wait longer for the LSASS service to start which means that Exchange will come online automatically but you will still get the errors in the event log as per above.

Ok how can I fix this – I don’t like errors in the Event Log!

The following is a script that I have designed to specifically get around the above scenario – essentially my script will complete the following tasks on your Exchange Server / Domain Controller:

  • Set the IIS Admin Service, World Wide Web Publishing Service, Microsoft Exchange System Attendant Service, Microsoft Exchange Information Store Service, Microsoft MTA Stacks Service, and Microsoft Routing Engine service to “Manual” startup.
  • When run the script will check to see if the services are configured correctly (e.g. ensure that the startup state is set to “Manual” then wait 15 seconds before beginning to start the services – each service is started in order to dependency (e.g. services that are parents to other are started first and there is a 20 second wait configured between each service start request.

You can download the Script from HERE

At the top of the script you will find two constants:

Const ServiceWaitTimeOut = 20000 ‘ 20 Seconds
Const ArbitWaitTime = 15000 ‘15 Seconds

The ServiceWaitTimeOut constant controls the amount of time to wait between starting each Exchange related service, where the ArbitWaitTime controls the amount of time that the script will wait after the service configuration has take place before then beginning the service startup commands.

These values are configurable and should be adjusted to fit in with your own Exchange environment.

The following is a overview of the script – you are advised, however to download the code from the link above prior to installation:

Const ServiceWaitTimeOut = 20000
Const ArbitWaitTime = 15000

CheckServices
Wscript.Sleep ArbitWaitTime
StartServices

Sub ConfigureServices

strComputer = “.”

Set objWMIService = GetObject(”winmgmts:” & “{impersonationLevel=impersonate}!\\” & strComputer & “\root\cimv2″)

Set colServiceList = objWMIService.ExecQuery (”Select * from Win32_Service where DisplayName = ‘Microsoft Exchange Information Store’”)

For Each objService in colServiceList
errReturnCode = objService.Change( , , , , “Manual”)
Next

Set colServiceList = objWMIService.ExecQuery (”Select * from Win32_Service where DisplayName = ‘Microsoft Exchange MTA Stacks’”)

For Each objService in colServiceList
errReturnCode = objService.Change( , , , , “Manual”)
Next

Set colServiceList = objWMIService.ExecQuery (”Select * from Win32_Service where DisplayName = ‘Microsoft Exchange Routing Engine’”)

For Each objService in colServiceList
errReturnCode = objService.Change( , , , , “Manual”)
Next

Set colServiceList = objWMIService.ExecQuery (”Select * from Win32_Service where DisplayName = ‘Microsoft Exchange System Attendant’”)

For Each objService in colServiceList
errReturnCode = objService.Change( , , , , “Manual”)
Next

Set colServiceList = objWMIService.ExecQuery (”Select * from Win32_Service where DisplayName = ‘IIS Admin Service’”)

For Each objService in colServiceList
errReturnCode = objService.Change( , , , , “Manual”)
Next

Set colServiceList = objWMIService.ExecQuery (”Select * from Win32_Service where DisplayName = ‘World Wide Web Publishing Service’”)

For Each objService in colServiceList
errReturnCode = objService.Change( , , , , “Manual”)
Next

Set objWMIService = Nothing
Set colServiceList = Nothing

End Sub

Sub CheckServices

strComputer = “.”

Set objWMIService = GetObject(”winmgmts:” & “{impersonationLevel=impersonate}!\\” & strComputer & “\root\cimv2″)

Set colServiceList = objWMIService.ExecQuery (”Select StartMode from Win32_Service where DisplayName = ‘Microsoft Exchange Information Store’”)

For Each objService in colServiceList
strMode = objService.StartMode
If StrMode = “Auto” Then
Call ConfigureServices
End If
Next

Set colServiceList = objWMIService.ExecQuery (”Select StartMode from Win32_Service where DisplayName = ‘Microsoft Exchange MTA Stacks’”)

For Each objService in colServiceList
strMode = objService.StartMode
If StrMode = “Auto” Then
Call ConfigureServices
End if
Next

Set colServiceList = objWMIService.ExecQuery (”Select StartMode from Win32_Service where DisplayName = ‘Microsoft Exchange Routing Engine’”)

For Each objService in colServiceList
strMode = objService.StartMode
If StrMode = “Auto” Then
Call ConfigureServices
End if
Next

Set colServiceList = objWMIService.ExecQuery (”Select StartMode from Win32_Service where DisplayName = ‘Microsoft Exchange System Attendant’”)

For Each objService in colServiceList
strMode = objService.StartMode
If StrMode = “Auto” Then
Call ConfigureServices
End if
Next

Set colServiceList = objWMIService.ExecQuery (”Select StartMode from Win32_Service where DisplayName = ‘IIS Admin Service’”)

For Each objService in colServiceList
strMode = objService.StartMode
If StrMode = “Auto” Then
Call ConfigureServices
End if
Next

Set colServiceList = objWMIService.ExecQuery (”Select StartMode from Win32_Service where DisplayName = ‘World Wide Web Publishing Service’”)

For Each objService in colServiceList
strMode = objService.StartMode
If StrMode = “Auto” Then
Call ConfigureServices
End if
Next

Set objWMIService = Nothing
Set colServiceList = Nothing
Set strMode = Nothing

End Sub

Sub StartServices

strComputer = “.”

Set objWMIService = GetObject(”winmgmts:” & “{impersonationLevel=impersonate}!\\” & strComputer & “\root\cimv2″)

Set colServiceList = objWMIService.ExecQuery (”Select * from Win32_Service where DisplayName =’IIS Admin Service’”)

For each objService in colServiceList
errReturn = objService.StartService()
Next

Wscript.Sleep ServiceWaitTimeOut

Set colServiceList = objWMIService.ExecQuery (”Select * from Win32_Service where DisplayName =’World Wide Web Publishing Service’”)

For each objService in colServiceList
errReturn = objService.StartService()
Next

Wscript.Sleep ServiceWaitTimeOut

Set colServiceList = objWMIService.ExecQuery (”Select * from Win32_Service where DisplayName =’Microsoft Exchange System Attendant’”)

For each objService in colServiceList
errReturn = objService.StartService()
Next

Wscript.Sleep ServiceWaitTimeOut

Set colServiceList = objWMIService.ExecQuery (”Select * from Win32_Service where DisplayName =’Microsoft Exchange Information Store’”)

For each objService in colServiceList
errReturn = objService.StartService()
Next

Wscript.Sleep ServiceWaitTimeOut

Set colServiceList = objWMIService.ExecQuery (”Select * from Win32_Service where DisplayName =’Microsoft Exchange MTA Stacks’”)

For each objService in colServiceList
errReturn = objService.StartService()
Next

Set colServices = objWMIService.ExecQuery (”SELECT * FROM win32_Service WHERE DisplayName = ‘Microsoft Exchange Routing Engine’”)

For Each objService in colServices
errReturnCode = objService.StartService()
Next

Set objWMIService = Nothing
Set colServiceList = Nothing

End Sub

Script Installation

  • Download the script to your domain controller / Exchange server and place it in the Directory called c:\ExchStart
  • Go to Active Directory Users and Computers – the navigate to the “Domain Controllers” OU – right click on it and then select “Properties”:
  • From the dialog box that appears select the “Group Policy” tab, then select the “Default Domain Controllers Policy” and click on the “Edit” button:

  • This will then bring up the Group Policy management console – navigate to the “Computer Configuration->Windows Settings->Scripts” you will see the the right hand window change to display “Startup” and “Shutdown” – right click on the “Startup” scripts and select “Properties”:

  • This will bring up the Startup scripts configuration dialog box (see below):

  • Click on the “Add” button – this will bring up the “Add a script” dialog which should be configured as follows:

When you have finished click on “OK”, then “OK” again and then exit the GPO management console.

Navigate to the C:\ExchStart\ folder and then run the SVCCNF.vbs script (this will set the initial states of the services for the next reboot).

This should now stop the errors in the application event log – bear in mind though that you might have to adjust some of the timeout settings to get best results for your domain.

SHARE:
Exchange 2003 Articles 0 Replies to “Exchange 2003 installed on a domain controller – services fail to start…”