使用进程内托管的 Dotnet Core 多重启动 类
Dotnet Core Multiple Startup Classes with In-Process Hosting
我有一个 dotnet 核心 v.2.1 应用程序,它利用 "startup-class-by-environment-name-convention" 为不同的环境使用不同的 Startup
类,例如开发,分期和生产。 Program.Main.CreateWebHost
方法类似于:
public static IWebHostBuilder CreateWebHostBuilder(string[] args)
{
var startupAssembly = Assembly.GetExecutingAssembly();
var webHostBuilder = WebHost.CreateDefaultBuilder(args)
.UseStartup(startupAssembly.FullName);
return webHostBuilder;
}
但是,在升级到 dotnet core v.2.2 之后(并且启动切换仍然很好用)我想尝试进程内托管功能。当切换到进程内托管模型,并且 运行 在本地使用 Visual Studio 2017 更新和 IIS Express 时,我收到此错误 运行 应用程序:
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
我检查了所有的日志,我能找到的只有这个:
<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>
我阅读了所有 dotnet core in-hosting migrate 2.1 -> 2.2,无论我能找到什么 MSDN 文章,并尝试了一堆不同的设置,但除了使用默认设置外找不到任何解决方案:
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
... 这不行 - 我想将启动切换 与进程内托管一起 使用。有谁知道如何实现这一点,或者对如何进行故障排除有任何建议?
编辑: 我从@cilerler 那里得到了我需要的答案。为了完整起见,以下是我的情况:
加载我的自定义配置文件失败,因为此过程依赖于对 Directory.GetCurrentDirectory()
的调用,其结果在切换到进程内托管时发生变化。这是该部分的原始代码(为简洁起见缩短):
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);
关键部分再次是对 GetCurrentDirectory()
的调用,因此,为了解决这个问题,我根据接受的答案中的建议将上面的内容更改为:
var currentDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
var basePath = $"{currentDirectory}\ConfigurationFiles";
builder.SetBasePath(basePath);
有关详细信息,请参阅已接受的答案;)
根据 aspnet-core-module 文章,它说
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).
这意味着配置加载器将无法找到 appsettings.*
文件,或 任何其他文件,例如自定义配置文件,这取决于 GetCurrentDirectory
称呼。为了在 Program.cs 中解决它,请在 public static void Main(string[] args) {
之后添加以下行
Directory.SetCurrentDirectory(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));
此外,在项目文件中 (例如 MyProject.csproj) 确保您具有以下行和 appsettings.*
存在于输出文件夹中。
<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>
我有同样的问题,不同的故事。
Visual Studio 2017 - asp.net 核心 mvc (sdk 2.2.104)。
- 运行 应用程序。 (是的,它会再次给你错误)
- 在 VS 中转到异常设置并启用 C++ 异常、CLR 异常、Win32 异常
- 重启你的调试进程,看看是否抛出异常。
在我的例子中:我通过 .AddScoped 在 Startup.cs 中注册了一个服务,其中具体的 serviceType 参数实际上是一个抽象的 class(重构后忘记更改它)。
否则转到 Windows 事件查看器并尝试在日志中找到线索。
我有一个 dotnet 核心 v.2.1 应用程序,它利用 "startup-class-by-environment-name-convention" 为不同的环境使用不同的 Startup
类,例如开发,分期和生产。 Program.Main.CreateWebHost
方法类似于:
public static IWebHostBuilder CreateWebHostBuilder(string[] args)
{
var startupAssembly = Assembly.GetExecutingAssembly();
var webHostBuilder = WebHost.CreateDefaultBuilder(args)
.UseStartup(startupAssembly.FullName);
return webHostBuilder;
}
但是,在升级到 dotnet core v.2.2 之后(并且启动切换仍然很好用)我想尝试进程内托管功能。当切换到进程内托管模型,并且 运行 在本地使用 Visual Studio 2017 更新和 IIS Express 时,我收到此错误 运行 应用程序:
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
我检查了所有的日志,我能找到的只有这个:
<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>
我阅读了所有 dotnet core in-hosting migrate 2.1 -> 2.2,无论我能找到什么 MSDN 文章,并尝试了一堆不同的设置,但除了使用默认设置外找不到任何解决方案:
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
... 这不行 - 我想将启动切换 与进程内托管一起 使用。有谁知道如何实现这一点,或者对如何进行故障排除有任何建议?
编辑: 我从@cilerler 那里得到了我需要的答案。为了完整起见,以下是我的情况:
加载我的自定义配置文件失败,因为此过程依赖于对 Directory.GetCurrentDirectory()
的调用,其结果在切换到进程内托管时发生变化。这是该部分的原始代码(为简洁起见缩短):
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);
关键部分再次是对 GetCurrentDirectory()
的调用,因此,为了解决这个问题,我根据接受的答案中的建议将上面的内容更改为:
var currentDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
var basePath = $"{currentDirectory}\ConfigurationFiles";
builder.SetBasePath(basePath);
有关详细信息,请参阅已接受的答案;)
根据 aspnet-core-module 文章,它说
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).
这意味着配置加载器将无法找到 appsettings.*
文件,或 任何其他文件,例如自定义配置文件,这取决于 GetCurrentDirectory
称呼。为了在 Program.cs 中解决它,请在 public static void Main(string[] args) {
之后添加以下行
Directory.SetCurrentDirectory(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));
此外,在项目文件中 (例如 MyProject.csproj) 确保您具有以下行和 appsettings.*
存在于输出文件夹中。
<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>
我有同样的问题,不同的故事。
Visual Studio 2017 - asp.net 核心 mvc (sdk 2.2.104)。
- 运行 应用程序。 (是的,它会再次给你错误)
- 在 VS 中转到异常设置并启用 C++ 异常、CLR 异常、Win32 异常
- 重启你的调试进程,看看是否抛出异常。
在我的例子中:我通过 .AddScoped 在 Startup.cs 中注册了一个服务,其中具体的 serviceType 参数实际上是一个抽象的 class(重构后忘记更改它)。
否则转到 Windows 事件查看器并尝试在日志中找到线索。