zoukankan      html  css  js  c++  java
  • aspnetcore进程内托管的坑-非常规方法解决Log4Net不写日志的问题

    问题描述:Log4Net,本地测试一切正常,发布后,无法自动创建文件夹和日志文件,无法写入文件。

    一、在项目中配置Log4Net

    请参考我的上一篇博客 《aspnetcore配置log4net并添加全局异常处理》,常规做法。

    二、Log4Net不写日志常规解决步骤

    一般讲来,Log4Net是非常成熟的框架,很难出现问题,出现不写日志这种情况,首先要做的是检查我们的代码、配置是否正确。

    1. 检查目录中是否包含 log4net.config ,如果文件不存在,手动复制一份即可。
    2. 检查  log4net.config 文件,主要是日志文件输出路径,一般日志保存目录是这样的  根目录/Logs/Errors/xxxx.log ,其他资料里一般写法为  <file value="Logs\Errors\" /> ,在这里个人推荐这样来写  <file value="Logs/Errors/" /> ,原因是曾经在  ubuntu > nginx  环境下部署时,第一种写法无法正常工作,改为第二种方法后正常。
    3. 检查文件夹权限,确保具有写权限。

    三、绝望的排查过程

    因为在本地测试完全正常,所以代码和配置文件应该没有问题,但保险起见,还是将网上常用的几种写法都尝试了一遍,然而,并没有什么卵用。

    接下来,查看文件夹权限,讲真,对于Server的文件系统我是真的了解很少,大部分时间遇到权限问题,就简单的给Everyone一个读写权限了事。不出意外的,折腾许久,还是失败了。

    重复以上步骤两个小时后...

     头昏脑涨中,想起之前的项目中使用Log4Net是正常的,写法和部署方式一样,为什么这次不行呢?

    于是对比之前的项目,把IIS中站点和应用程序池的配置项一条一条拿出来看,一个小时后...

    完全一样啊,啥情况,要不换NLog???虽然为了项目进度换成其他框架也说的过去,但作为程序员,明知道有bug却解决不了,总归过不去心里这一关不是。不甘心啊~

    四、灵光乍现

    就在准备把问题先放放,修改项目使用Nlog的时候,鬼使神差的,去看了眼任务管理器,咦~~还真发现了问题,之前的项目都是开了三个进程(w3wp.exe conhost.exe dotnet.exe),而新项目只有两个(w3wp.exe conhost.exe),精神立马振奋了一下,看来问题可能就在这里了。打开项目的  web.config  文件,发现多了点东西:

    有问题找度娘,搜索 InProcess ,大部分内容都一样,没看出啥问题,难道是我想错了,问题不在这里?说脏话会不会发布失败?咱也不知道咱也不敢问,还是憋回去吧!

    抱着最后一丝希望,跑到官方文档 《ASP.NET Core 模块》,不得不说啊,微软自动翻译的文档真的很考验中文水平,但是再烂也得看不是,这块内容之前也没说关注过,不管能不能解决问题,看看也好,当补课了。

    细细看下来,有这么一段

    在 ASP.NET Core 2.2.1 或早期版本中,GetCurrentDirectory 会返回 IIS 启动的进程的工作目录而非应用目录(例如,对于 w3wp.exe,是 C:WindowsSystem32inetsrv)。

    对于设置应用的当前目录的示例代码,请参阅 CurrentDirectoryHelpers 类。 调用 SetCurrentDirectory 方法。 后续 GetCurrentDirectory 调用提供应用的目录。

    醍醐灌顶,虽然外面已经是傍晚时分,但我眼前仿佛一道曙光升起,恍惚间似乎看到天女降临,嘿,嘿嘿~~

    五、填坑

     接下来就简单了,github上把CurrentDirectoryHelpers类搞下来,在  startup.cs  的构造函数中添加  CurrentDirectoryHelpers.SetCurrentDirectory(); ,重新发布、部署、启动站点,文件出现了。

    下面贴一下  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
                }
            }
        }
    }
    View Code
  • 相关阅读:
    Git合并
    Git对象
    Git储藏和引用日志
    小小c#算法题 4 子数组最大和
    小小c#算法题 2 求素数
    小小c#算法题 5 插入排序
    小小c#算法题 1 找出数组中满足条件的两个数
    [转] WPF – Editing Mode with Save and Cancel Capability
    小小c#算法题 0 单循环冒泡排序
    小小c#算法题 3 字符串语句反转
  • 原文地址:https://www.cnblogs.com/diwu0510/p/10901804.html
Copyright © 2011-2022 走看看