update, upgrade, board

Exchange Control Panel and OWA not working after CU installation

Some days ago, I had a strange Exchange issue. Because of Hafnium I installed the recent CU with all CVs. As a result, the ECP and OWA didn’t work anymore.

The update was installed as recommended by Microsoft and written down by the community in many blog articles (Maintenance Mode on Server 1 active – install patch – Maintenance Mode on Server 1 inactive – same procedure for Server 2). The error after the installation is the following:

The text of the error message:

Could not load file or assembly ‘Microsoft.Exchange.Common, Version=15.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35’ or one of its dependencies. The system cannot find the file specified.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.IO.FileNotFoundException: Could not load file or assembly ‘Microsoft.Exchange.Common, Version=15.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35’ or one of its dependencies. The system cannot find the file specified.
Source Error:
An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

Assembly Load Trace: The following information can be helpful to determine why the assembly ‘Microsoft.Exchange.Common, Version=15.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35’ could not be loaded.
WRN: Assembly binding logging is turned OFF.
To enable assembly bind failure logging, set the registry value HKLM\Software\Microsoft\Fusion!EnableLog to 1.

Note: There is some performance penalty associated with assembly bind failure logging.
To turn this feature off, remove the registry value [HKLM\Software\Microsoft\Fusion!EnableLog].

Stack Trace:

[FileNotFoundException: Could not load file or assembly ‘Microsoft.Exchange.Common, Version=15.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35’ or one of its dependencies. The system cannot find the file specified.]
System.RuntimeTypeHandle.GetTypeByName(String name, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMarkHandle stackMark, IntPtr pPrivHostBinder, Boolean loadTypeFromPartialName, ObjectHandleOnStack type) +0
System.RuntimeTypeHandle.GetTypeByName(String name, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean loadTypeFromPartialName) +100
System.RuntimeType.GetType(String typeName, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMark& stackMark) +47
System.Type.GetType(String typeName, Boolean throwOnError, Boolean ignoreCase) +44
System.Web.Compilation.BuildManager.GetType(String typeName, Boolean throwOnError, Boolean ignoreCase) +59
System.Web.Configuration.ConfigUtil.GetType(String typeName, String propertyName, ConfigurationElement configElement, XmlNode node, Boolean checkAptcaBit, Boolean ignoreCase) +49
[ConfigurationErrorsException: Could not load file or assembly ‘Microsoft.Exchange.Common, Version=15.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35’ or one of its dependencies. The system cannot find the file specified.]
System.Web.Configuration.ConfigUtil.GetType(String typeName, String propertyName, ConfigurationElement configElement, XmlNode node, Boolean checkAptcaBit, Boolean ignoreCase) +515
System.Web.Configuration.ConfigUtil.GetType(String typeName, String propertyName, ConfigurationElement configElement, Boolean checkAptcaBit) +29
System.Web.Configuration.Common.ModulesEntry.SecureGetType(String typeName, String propertyName, ConfigurationElement configElement) +60
System.Web.Configuration.Common.ModulesEntry..ctor(String name, String typeName, String propertyName, ConfigurationElement configElement) +68
System.Web.HttpApplication.BuildIntegratedModuleCollection(List`1 moduleList) +221
System.Web.HttpApplication.GetModuleCollection(IntPtr appContext) +1153
System.Web.HttpApplication.RegisterEventSubscriptionsWithIIS(IntPtr appContext, HttpContext context, MethodInfo[] handlers) +139
System.Web.HttpApplication.InitSpecial(HttpApplicationState state, MethodInfo[] handlers, IntPtr appContext, HttpContext context) +168
System.Web.HttpApplicationFactory.GetSpecialApplicationInstance(IntPtr appContext, HttpContext context) +277
System.Web.Hosting.PipelineRuntime.InitializeApplication(IntPtr appContext) +369
[HttpException (0x80004005): Could not load file or assembly ‘Microsoft.Exchange.Common, Version=15.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35’ or one of its dependencies. The system cannot find the file specified.]
System.Web.HttpRuntime.FirstRequestInit(HttpContext context) +532
System.Web.HttpRuntime.EnsureFirstRequestInit(HttpContext context) +114
System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context) +724

Weird error – reproducable on each Exchange server. PowerShell was still working, only the 2 websites ECP and OWA were affected. I’ve spent hours reading blogs and related articles but did not find one that led me to success. In the end the key to victory was a combination of blog article entries and documentation and a script that is hidden well inside the Exchange Script directory. Let me show you the details:

IIS Settings

First you need to go to the IIS on your Exchange Server (each one that is affected) and look at the Exchange Back End / ecp / Application Settings.

In the Application Settings, check the value for BinSearchFolders. In my case, there were totally wrong entries. The proclaimed system variable %ExchangeInstallDir% didn’t exist on the Exchange Servers. You should change that to the REAL installation path of your Exchange server, e.g. E:\Exchange. Please keep in mind that this value contains (in my case) 3 paths, you need to adjust them all and separate them with semicolon. Otherwise you cause new and more IIS errors. Working example:

After this is done, don’t forget to perform an IISreset in an elevated command prompt:

If you are lucky, that already solves you problem. There are several guys throughout the internet that were fine with that solution. For me, that was not all, so investigation continued.

Exchange CAS Update

After the IIS settings were adjusted, I got the website itself running, but it was terribly ugly – like there would be no CSS or style:

Further troubleshooting and investigation led me to the clue that the IIS components of the Exchange were not fully copied by the installation and there is a repair script delivered with Exchange. Luckily the Exchange Scripts folder is available via system variable so it can be started from anywhere:

The script then works for some time (in my case ~10 minutes on each server) and seems to do a lot:

There are some sines with Copying and Updating, so it sounds quite good. After the script finished I tried opening ECP and OWA again and see the result:

Of course, you can do another iisreset before re-opening ECP / OWA, in my case that was not necessary.

Published by Andreas

Founder of M365 Evangelists Cloud-Architect, Strategy Consultant, Consultant for Microsoft technologies, Graph API enthusiast, PowerShell enthusiast