web-dev-qa-db-ja.com

ASP.NET Core 2.2でInProcessホスティングモデルを使用している間、Serilogはログをファイルに書き込みません

新しく導入されたInProcessホスティングモデルをASP.NET Core 2.2で次のように使用する場合:

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

Serilogはログをファイルに書き込みません。しかし、<AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>から.csprojを削除すると、すべてが期待どおりに機能します。

SerilogクラスのProgram構成は次のとおりです。

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 
}

専門家からの考えをお願いします!

6
TanvirArjel

質問自体のコメントで示唆されているように、InProcessホスティングモデルを使用して実行している場合、アプリケーションの現在のディレクトリはOutOfProcessホスティングモデルとは異なります。 InProcessの場合、このディレクトリはIIS自体-たとえばC:\Program Files\IIS Expressの場所です。これは、ログファイルがC:\Program Files\IIS Express\Logs\log-.txtに書き込まれていることを意味します(関連する権限が設定されていること)。

この回避策については、 このGitHubの問題 で詳しく説明されています。これは、正しい現在のディレクトリを設定するためのヘルパークラス( CurrentDirectoryHelpers )を提供します。 SetCurrentDirectory staticメソッドは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
            }
        }
    }
}
12
Kirk Larkin

.NetCoreバージョンをアップグレードしてみてください。この問題は2.2.3で修正されたようです。

2
Popa Andrei