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