在 ASP.NET Core 2.2 中使用 InProcess 托管模型时,Serilog 不会将日志写入文件
Posted
技术标签:
【中文标题】在 ASP.NET Core 2.2 中使用 InProcess 托管模型时,Serilog 不会将日志写入文件【英文标题】:Serilog does not write log to file while using InProcess hosting model in ASP.NET Core 2.2 【发布时间】:2019-05-19 15:45:06 【问题描述】:如果我在ASP.NET Core 2.2
中使用新引入的InProcess
托管模型如下:
<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
<AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
</PropertyGroup>
Serilog
不将日志写入文件。但如果我从.csproj
中删除<AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
,一切都会按预期进行。
我在Program
类中的Serilog
配置如下:
public class Program
public static void Main(string[] args)
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Information() // Set the minimun log level
.WriteTo.File("Logs\\log-.txt", rollingInterval: RollingInterval.Day, retainedFileCountLimit: 7) // this is for logging into file system
.CreateLogger();
try
Log.Information("Starting web host");
CreateWebHostBuilder(args).Build().Run();
catch (Exception ex)
Log.Fatal(ex, "Host terminated unexpectedly");
finally
Log.CloseAndFlush();
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureLogging(logging => logging.ClearProviders(); ) // clearing all other logging providers
.UseSerilog(); // Using serilog
请高手给点意见!
【问题讨论】:
请记住,托管进程的默认目录与自托管进程不同。所以您可能需要在启动期间设置它或使用绝对路径(通过 appsettings.json、环境变量等) 【参考方案1】:正如您问题本身的 cmets 中所建议的,当使用 InProcess
托管模型运行时,应用程序的当前目录与 OutOfProcess
托管模型不同。对于InProcess
,此目录是 IIS 本身的位置 - 例如C:\Program Files\IIS Express
,表示你的日志文件正在写入C:\Program Files\IIS Express\Logs\log-.txt
(假设设置了相关权限)。
this GitHub issue 中详细介绍了解决此问题的方法,它提供了一个帮助程序类 (CurrentDirectoryHelpers
) 用于设置正确的当前目录。 SetCurrentDirectory
静态方法使用 PInvoke,确定应用程序是否在 IIS 中运行,如果是,则根据完整的应用程序路径设置当前目录。使用这种方法看起来像这样:
public class Program
public static void Main(string[] args)
CurrentDirectoryHelpers.SetCurrentDirectory();
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Information() // Set the minimun log level
.WriteTo.File("Logs\\log-.txt", rollingInterval: RollingInterval.Day, retainedFileCountLimit: 7) // this is for logging into file system
.CreateLogger();
...
为了完整起见,这里是CurrentDirectoryHelpers
:
using System;
namespace SampleApp
internal class CurrentDirectoryHelpers
internal const string AspNetCoreModuleDll = "aspnetcorev2_inprocess.dll";
[System.Runtime.InteropServices.DllImport("kernel32.dll")]
private static extern IntPtr GetModuleHandle(string lpModuleName);
[System.Runtime.InteropServices.DllImport(AspNetCoreModuleDll)]
private static extern int http_get_application_properties(ref IISConfigurationData iiConfigData);
[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
private struct IISConfigurationData
public IntPtr pNativeApplication;
[System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.BStr)]
public string pwzFullApplicationPath;
[System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.BStr)]
public string pwzVirtualApplicationPath;
public bool fWindowsAuthEnabled;
public bool fBasicAuthEnabled;
public bool fAnonymousAuthEnable;
public static void SetCurrentDirectory()
try
// Check if physical path was provided by ANCM
var sitePhysicalPath = Environment.GetEnvironmentVariable("ASPNETCORE_IIS_PHYSICAL_PATH");
if (string.IsNullOrEmpty(sitePhysicalPath))
// Skip if not running ANCM InProcess
if (GetModuleHandle(AspNetCoreModuleDll) == IntPtr.Zero)
return;
IISConfigurationData configurationData = default(IISConfigurationData);
if (http_get_application_properties(ref configurationData) != 0)
return;
sitePhysicalPath = configurationData.pwzFullApplicationPath;
Environment.CurrentDirectory = sitePhysicalPath;
catch
// ignore
【讨论】:
【参考方案2】:尝试升级 .Net Core 版本。这个问题似乎在 2.2.3 中得到修复。
【讨论】:
以上是关于在 ASP.NET Core 2.2 中使用 InProcess 托管模型时,Serilog 不会将日志写入文件的主要内容,如果未能解决你的问题,请参考以下文章
如何在启用 ASP.NET Core 2.2 EndpointRouting 的情况下使用 RouteDataRequestCultureProvider?
PetaPoco在ASP.NET Core 2.2中使用注入方式访问数据库
在 ASP.NET Core 2.2 中使用 InProcess 托管模型时,Serilog 不会将日志写入文件
ASP.NET Core Identity UserManager.IsInRole 调用在 2.2 中有效,但在 3.0 中引发 InvalidOperation