13

I have a dotnet core v.2.1 application that utilizes the "startup-class-by-environment-name-convention" to use different Startup classes for different environment, e.g. development, staging and production. The Program.Main.CreateWebHost method looks similar to this:

public static IWebHostBuilder CreateWebHostBuilder(string[] args)
{
    var startupAssembly = Assembly.GetExecutingAssembly();
    var webHostBuilder = WebHost.CreateDefaultBuilder(args)
                                .UseStartup(startupAssembly.FullName);
    return webHostBuilder;
}

However, after upgrading to dotnet core v.2.2 (and the startup-switching still works great) I wanted to try out the in-process hosting capabilities. When switching to the in-process hosting model, and running locally with Visual Studio 2017 updated and IIS Express, I get this error running the application:

HTTP Error 500.30 - ANCM In-Process Start Failure

Common causes of this issue:

  • The application failed to start
  • The application started but then stopped
  • The application started but threw an exception during startup

Troubleshooting steps:

  • Check the system event log for error messages
  • Enable logging the application process' stdout messages
  • Attach a debugger to the application process and inspect

For more information visit: https://go.microsoft.com/fwlink/?LinkID=2028265

I checked all the logs, and all I could find was this:

<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
  <System>
    <Provider Name="IIS Express AspNetCore Module V2" /> 
    <EventID Qualifiers="0">1007</EventID> 
    <Level>2</Level> 
    <Task>0</Task> 
    <Keywords>0x80000000000000</Keywords> 
    <TimeCreated SystemTime="2018-12-14T10:37:48.327935100Z" /> 
    <EventRecordID>3693</EventRecordID> 
    <Channel>Application</Channel> 
    <Computer>[whatever]</Computer> 
    <Security /> 
  </System>
  <EventData>
    <Data>Application '/LM/W3SVC/2/ROOT' with physical root '[whatever again]' failed to load clr and managed application. CLR worker thread exited prematurely</Data> 
    <Data>Process Id: 29836.</Data> 
    <Data>File Version: 12.2.18316.0. Description: IIS ASP.NET Core Module V2 Request Handler. Commit: ce8cf65589734f82b0536c543aba5bd60d0a5a98</Data> 
  </EventData>
</Event>

I read all the dotnet core in-hosting migrate 2.1 -> 2.2 whatever MSDN articles I could find, and tried a bunch of different set-ups, but could find no solution apart from using the default:

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
           .UseStartup<Startup>();

... Which will not do - I want to use the startup-switching together with the in-process hosting. Does anyone know how to achieve this, or have any suggestions on how to proceed with the troubleshooting?

EDIT: I got the answer I needed from @cilerler. For the sake of completeness, here's what was going on in my case:

The loading of my custom configuration files failed because this process depended on a call to Directory.GetCurrentDirectory(), the result of which changes when switching to in-process hosting. Here's my original code for that part (shortened for brevity):

var basePath = $"{Directory.GetCurrentDirectory()}\\ConfigurationFiles";
builder.SetBasePath(basePath);

builder.AddJsonFile("some.config.json", false, true);
builder.AddJsonFile($"some.config.{context.HostingEnvironment.EnvironmentName}.json", true, true);

The crucial part is - again - the call to GetCurrentDirectory(), so, to fix the issue, I changed the above as per the recommendation in the accepted answer, to:

var currentDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
var basePath = $"{currentDirectory}\\ConfigurationFiles";
builder.SetBasePath(basePath);

For further details, see the accepted answer ;)

Oskar Lindberg
  • 2,255
  • 2
  • 16
  • 36

2 Answers2

13

According to aspnet-core-module article it says

GetCurrentDirectory returns the worker directory of the process started by IIS rather than the app's directory (for example, C:\Windows\System32\inetsrv for w3wp.exe).

which means config loader will not be able to find appsettings.* files, or any other files such as custom config files, that depend on a GetCurrentDirectory call. In order to solve it in your Program.cs right after public static void Main(string[] args) { add the following line

Directory.SetCurrentDirectory(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));

Also, in project file (e.g. MyProject.csproj) make sure that you have the following lines and appsettings.* exists in output folder.

<ItemGroup>
  <Content Update="appsettings.json">
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
  </Content>
  <Content Update="appsettings.Development.json">
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
  </Content>
  <Content Update="appsettings.Production.json">
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
  </Content>
</ItemGroup>
Daniel Congrove
  • 3,519
  • 2
  • 35
  • 59
cilerler
  • 9,010
  • 10
  • 56
  • 91
  • This got me one step further. I got some errors that a I was able to solve. but then I got stuck again :( the log looks good, stating that application has started, but web api is not responding, and in the windows application log I have: failed to load clr and managed application. Managed server didn't initialize after 120000 ms. If I start the dll outside of IIS everything works. :( I have installed the .net core module for IIS, (v2) – Magnus Gudmundsson Dec 17 '18 at 10:04
  • Thank you for replying. Your answer might be even more helpful if you were to explain _why_ you think that your suggestions might help, and how they relate to the in-process hosting scenario. In my case, I have no issues with the config files, so these additions to the code that you've proposed does not have any effect on the issue at hand, I'm sorry to say. – Oskar Lindberg Dec 17 '18 at 15:32
  • @OskarLindberg updated the answer, Your setup may differ but I'm pretty sure it is the issue since I got the exactly the same error message as yours. Therefore if you may create a repo with the simplified version of your code base that throws the error, I can look into it for you – cilerler Dec 17 '18 at 16:10
  • You're 100 percent right! I just _thought_ I'd already checked that the configuration files were loaded correctly. I was also completely thrown off-track by the fact that the application starts up just fine using the "default" `CreateWebHostBuilder` code. I load some other config files too though, besides the ``, and that loading indeed fails due to the new result calling `Directory.GetCurrentDirectory()`, so that piece of information was crucial for me to understand the issue. Thank you :) – Oskar Lindberg Dec 18 '18 at 10:31
0

I had the same issue, different story.

Visual Studio 2017 - asp.net core mvc (sdk 2.2.104).

  1. Run the application. (yes it will give you the error again)
  2. in VS go to Exception Settings and enable C++ Exceptions, CLR Exceptions, Win32 Exceptions
  3. Restart your debugging progress and see if an exception is thrown.

In my case: I registered a service in Startup.cs via .AddScoped where the concrete serviceType parameter was actually an abstract class (forgot to change this after refactoring).

Else go to Windows Event Viewer and try to find a clue in the logs.

juFo
  • 17,849
  • 10
  • 105
  • 142