AspNetCoreHostingModel

AspNetCoreHostingModel

本文介绍了在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 Files\IIS Express,这意味着您的日志文件正在写入C:\Program Files\IIS Express\Logs\log-.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 Files\IIS Express, which means that your log files are being written to C:\Program Files\IIS Express\Logs\log-.txt (assuming that the relevant permissions are set).

有关此问题的解决方法,请参见此GitHub问题,其中提供了帮助程序类( 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:

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不会将日志写入文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-15 07:51