IIS ASP.NET 6 次启动抛出 System.IO.DirectoryNotFoundException: D:\agent\_work\s\IdentityServer\wwwroot\
IIS ASP.NET 6 startup throws System.IO.DirectoryNotFoundException: D:\agent\_work\38\s\IdentityServer\wwwroot\
我们正在将我们的一个应用程序(在本例中为 IdentityServer)从 .NET 5 更新到 .NET 6。它由 IIS 托管并由 Azure Devops Services 部署。我们看到的问题是,在我们的开发环境中,网站无法加载,但在我们的暂存环境中,它运行得很好。我们在开发中看到的错误是
12:45:37.519|Fatal|1||Host terminated unexpectedly.||
System.IO.DirectoryNotFoundException: D:\agent\_work\s\IdentityServer\wwwroot\
at Microsoft.Extensions.FileProviders.PhysicalFileProvider..ctor(String root, ExclusionFilters filters)
at Microsoft.Extensions.FileProviders.PhysicalFileProvider..ctor(String root)
at Microsoft.AspNetCore.Hosting.StaticWebAssets.StaticWebAssetsLoader.<>c.<UseStaticWebAssetsCore>b__1_0(String contentRoot)
at Microsoft.AspNetCore.StaticWebAssets.ManifestStaticWebAssetFileProvider..ctor(StaticWebAssetManifest manifest, Func`2 fileProviderFactory)
at Microsoft.AspNetCore.Hosting.StaticWebAssets.StaticWebAssetsLoader.UseStaticWebAssetsCore(IWebHostEnvironment environment, Stream manifest)
at Microsoft.AspNetCore.Hosting.StaticWebAssets.StaticWebAssetsLoader.UseStaticWebAssets(IWebHostEnvironment environment, IConfiguration configuration)
at Microsoft.AspNetCore.WebHost.<>c.<ConfigureWebDefaults>b__9_0(WebHostBuilderContext ctx, IConfigurationBuilder cb)
at Microsoft.AspNetCore.Hosting.GenericWebHostBuilder.<>c__DisplayClass9_0.<ConfigureAppConfiguration>b__0(HostBuilderContext context, IConfigurationBuilder builder)
at Microsoft.Extensions.Hosting.HostBuilder.BuildAppConfiguration()
at Microsoft.Extensions.Hosting.HostBuilder.Build()
at IdentityServer.Program.Main(String[] args) in D:\agent\_work\s\IdentityServer\Program.cs:line 23
它报告的路径 D:\agent\_work\s\IdentityServer\wwwroot\
很有趣,因为该路径与 DevOps 构建机器的路径相同。如果我们恢复到 .NET 5,我们就不会看到这个错误,而且我们在暂存计算机上也不会看到这个问题。
Program.cs
class定义为
using System;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using NewRelic.LogEnrichers.Serilog;
using Serilog;
using Serilog.Events;
namespace IdentityServer
{
public class Program
{
public static int Main(string[] args)
{
try
{
CreateLogger();
Log.Information("Starting host...");
CreateHostBuilder(args).Build().Run();
return 0;
}
catch (Exception ex)
{
Log.Fatal(ex, "Host terminated unexpectedly.");
return 1;
}
finally
{
Log.CloseAndFlush();
}
}
public static void CreateLogger()
{
var configuration = GetConfiguration();
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(configuration)
.Enrich.FromLogContext() // allows logging middleware to inject output values
.Enrich.WithThreadId()
.Enrich.WithNewRelicLogsInContext()
.CreateLogger();
}
public static IHostBuilder CreateHostBuilder(string[] args)
{
var configuration = GetConfiguration();
return Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(
webBuilder =>
{
webBuilder.UseConfiguration(configuration);
webBuilder.UseSerilog();
webBuilder.UseIIS();
webBuilder.CaptureStartupErrors(true);
webBuilder.UseStartup<Startup>();
});
}
private static IConfiguration GetConfiguration()
{
var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
var builder = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.AddJsonFile($"appsettings.{environment}.json", true, true);
var configuration = builder.Build();
return configuration;
}
}
}
我们确实有其他 .NET 6 Web 应用程序 运行 在此 IIS 实例上运行良好。我当时认为问题可能出在我们的发布管道中,但它们在环境之间的任务配置中是相同的。尝试在代码或配置中查找目录路径,但在任何地方都看不到。已尝试通过 Program.cs 中的 .UseWebRoot("path to folder")
和 .UseContentRoot("path to folder")
手动设置 WebRoot 和 ContentRoot 路径,但在日志或应用启动。
甚至更新了 web.config 文件以在 aspNetCore
元素中具有执行项目 dll 的确切路径,但仍然没有变化。
2022 年 2 月 10 日更新
向启动添加了调试输出以验证文件和文件夹路径。环境变量和执行文件路径中的所有内容看起来都是正确的。
ASPNETCORE_IIS_PHYSICAL_PATH - C:\inetpub\webapps\IdentityServer\
Executable Path: C:\inetpub\webapps\IdentityServer\IdentityServer.dll
问题最终变成了我们如何将更新从 DevOps 推送到服务器。我们的管道旨在从构建文件夹的 Release 目录中复制文件。这种方法的问题之一是站点 运行 不需要但在构建期间生成的文件也被复制到发布服务器。在这种情况下,.NET 6 中生成的新文件 .staticwebssets.runtime.json
被复制到我们的服务器。
.NET 6 的行为方式似乎是,如果环境设置为 Development
,那么它将查找此文件以确定静态 Web 资产的位置。如果该文件不存在,那么它将假定文件位于站点的 wwwroot sub-directory 中。这对于您从本地 Visual Studio 运行 宁项目的情况是有意义的。有关此文件的更多详细信息可在另一个 中找到,其中包含指向 GitHub 中源代码的链接。为了解决我们的问题,我们更改了发布管道以使用 publish.zip
文件,该文件是在您对解决方案执行 运行 publish
命令时生成的。 zip 文件仅包含 运行 站点所需的文件,因此包含 none 的无关文件,例如 .staticwebssets.runtime.json
。我们应该一直这样做...吸取教训。
我们现在解压缩 publish.zip
文件,应用任何文件转换,然后将解压缩的文件复制到网络服务器。
我们正在将我们的一个应用程序(在本例中为 IdentityServer)从 .NET 5 更新到 .NET 6。它由 IIS 托管并由 Azure Devops Services 部署。我们看到的问题是,在我们的开发环境中,网站无法加载,但在我们的暂存环境中,它运行得很好。我们在开发中看到的错误是
12:45:37.519|Fatal|1||Host terminated unexpectedly.||
System.IO.DirectoryNotFoundException: D:\agent\_work\s\IdentityServer\wwwroot\
at Microsoft.Extensions.FileProviders.PhysicalFileProvider..ctor(String root, ExclusionFilters filters)
at Microsoft.Extensions.FileProviders.PhysicalFileProvider..ctor(String root)
at Microsoft.AspNetCore.Hosting.StaticWebAssets.StaticWebAssetsLoader.<>c.<UseStaticWebAssetsCore>b__1_0(String contentRoot)
at Microsoft.AspNetCore.StaticWebAssets.ManifestStaticWebAssetFileProvider..ctor(StaticWebAssetManifest manifest, Func`2 fileProviderFactory)
at Microsoft.AspNetCore.Hosting.StaticWebAssets.StaticWebAssetsLoader.UseStaticWebAssetsCore(IWebHostEnvironment environment, Stream manifest)
at Microsoft.AspNetCore.Hosting.StaticWebAssets.StaticWebAssetsLoader.UseStaticWebAssets(IWebHostEnvironment environment, IConfiguration configuration)
at Microsoft.AspNetCore.WebHost.<>c.<ConfigureWebDefaults>b__9_0(WebHostBuilderContext ctx, IConfigurationBuilder cb)
at Microsoft.AspNetCore.Hosting.GenericWebHostBuilder.<>c__DisplayClass9_0.<ConfigureAppConfiguration>b__0(HostBuilderContext context, IConfigurationBuilder builder)
at Microsoft.Extensions.Hosting.HostBuilder.BuildAppConfiguration()
at Microsoft.Extensions.Hosting.HostBuilder.Build()
at IdentityServer.Program.Main(String[] args) in D:\agent\_work\s\IdentityServer\Program.cs:line 23
它报告的路径 D:\agent\_work\s\IdentityServer\wwwroot\
很有趣,因为该路径与 DevOps 构建机器的路径相同。如果我们恢复到 .NET 5,我们就不会看到这个错误,而且我们在暂存计算机上也不会看到这个问题。
Program.cs
class定义为
using System;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using NewRelic.LogEnrichers.Serilog;
using Serilog;
using Serilog.Events;
namespace IdentityServer
{
public class Program
{
public static int Main(string[] args)
{
try
{
CreateLogger();
Log.Information("Starting host...");
CreateHostBuilder(args).Build().Run();
return 0;
}
catch (Exception ex)
{
Log.Fatal(ex, "Host terminated unexpectedly.");
return 1;
}
finally
{
Log.CloseAndFlush();
}
}
public static void CreateLogger()
{
var configuration = GetConfiguration();
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(configuration)
.Enrich.FromLogContext() // allows logging middleware to inject output values
.Enrich.WithThreadId()
.Enrich.WithNewRelicLogsInContext()
.CreateLogger();
}
public static IHostBuilder CreateHostBuilder(string[] args)
{
var configuration = GetConfiguration();
return Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(
webBuilder =>
{
webBuilder.UseConfiguration(configuration);
webBuilder.UseSerilog();
webBuilder.UseIIS();
webBuilder.CaptureStartupErrors(true);
webBuilder.UseStartup<Startup>();
});
}
private static IConfiguration GetConfiguration()
{
var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
var builder = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.AddJsonFile($"appsettings.{environment}.json", true, true);
var configuration = builder.Build();
return configuration;
}
}
}
我们确实有其他 .NET 6 Web 应用程序 运行 在此 IIS 实例上运行良好。我当时认为问题可能出在我们的发布管道中,但它们在环境之间的任务配置中是相同的。尝试在代码或配置中查找目录路径,但在任何地方都看不到。已尝试通过 Program.cs 中的 .UseWebRoot("path to folder")
和 .UseContentRoot("path to folder")
手动设置 WebRoot 和 ContentRoot 路径,但在日志或应用启动。
甚至更新了 web.config 文件以在 aspNetCore
元素中具有执行项目 dll 的确切路径,但仍然没有变化。
2022 年 2 月 10 日更新
向启动添加了调试输出以验证文件和文件夹路径。环境变量和执行文件路径中的所有内容看起来都是正确的。
ASPNETCORE_IIS_PHYSICAL_PATH - C:\inetpub\webapps\IdentityServer\
Executable Path: C:\inetpub\webapps\IdentityServer\IdentityServer.dll
问题最终变成了我们如何将更新从 DevOps 推送到服务器。我们的管道旨在从构建文件夹的 Release 目录中复制文件。这种方法的问题之一是站点 运行 不需要但在构建期间生成的文件也被复制到发布服务器。在这种情况下,.NET 6 中生成的新文件 .staticwebssets.runtime.json
被复制到我们的服务器。
.NET 6 的行为方式似乎是,如果环境设置为 Development
,那么它将查找此文件以确定静态 Web 资产的位置。如果该文件不存在,那么它将假定文件位于站点的 wwwroot sub-directory 中。这对于您从本地 Visual Studio 运行 宁项目的情况是有意义的。有关此文件的更多详细信息可在另一个 publish.zip
文件,该文件是在您对解决方案执行 运行 publish
命令时生成的。 zip 文件仅包含 运行 站点所需的文件,因此包含 none 的无关文件,例如 .staticwebssets.runtime.json
。我们应该一直这样做...吸取教训。
我们现在解压缩 publish.zip
文件,应用任何文件转换,然后将解压缩的文件复制到网络服务器。