本文介绍了在 ASP.NET Core 2.2 中使用 InProcess 托管模型时,Serilog 不会将日志写入文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我在 ASP.NET Core 2.2 中使用新引入的 InProcess 托管模型,如下所示:

If I use newly introduced InProcess hosting model in ASP.NET Core 2.2 as follows:

<PropertyGroup>
  <TargetFramework>netcoreapp2.2</TargetFramework>
  <AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
</PropertyGroup>

Serilog 不会将日志写入文件.但是如果我从 .csproj 中删除 <AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel> 一切正常.

Serilog does not write log to file. but if I remove <AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel> from .csproj everything works as expected.

我在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
}

请高手给点意见!

推荐答案

正如对您的问题本身的评论中所建议的那样,当使用 InProcess 托管模型运行时,应用程序的当前目录是不同的到 OutOfProcess 托管模型.对于 InProcess,此目录是 IIS 本身的位置 - 例如C:Program FilesIIS Express,这意味着您的日志文件正在写入 C:Program FilesIIS ExpressLogslog-.txt(假设设置相关权限).

As suggested in the comments on your question itself, when running using the InProcess hosting model, the current directory for the application is different to the OutOfProcess hosting model. For InProcess, this directory is the location of IIS itself - e.g. C:Program FilesIIS Express, which means that your log files are being written to C:Program FilesIIS ExpressLogslog-.txt (assuming that the relevant permissions are set).

this GitHub issue 中详细介绍了一种解决方法,它提供了一个帮助程序类(CurrentDirectoryHelpers) 用于设置正确的当前目录.SetCurrentDirectory 静态方法使用 PInvoke,确定应用程序是否在 IIS 内运行,如果是,则根据完整的应用程序路径设置当前目录.使用这种方法看起来像这样:

A workaround for this is detailed in this GitHub issue, which provides a helper class (CurrentDirectoryHelpers) for setting the correct current directory. The SetCurrentDirectory static method uses PInvoke, determining whether or not the application is running from within IIS and if it is, it sets the current directory according to the full application path. Using this approach looks like this:

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:

Here's CurrentDirectoryHelpers for completeness:

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
            }
        }
    }
}

这篇关于在 ASP.NET Core 2.2 中使用 InProcess 托管模型时,Serilog 不会将日志写入文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

05-24 12:01