1

Closed

RollingFileTraceListener fails in .NET Framework 4.6.2

description

In console app, it crashes when trying to locate directory.

In Web app, it crashes on Windows 7 failing respective Web functions; and in Windows Server 2016, respective Web functions still work, however, not output to the file.

I think this may be related to some https://support.microsoft.com/en-us/help/3151796/known-issues-for-the-.net-framework-4.6.2.
and
https://support.microsoft.com/en-us/help/3181958

The problems could be replicated with Essential.Diagnostics 1.2.3 and 2.0.2.
Closed Jun 10 at 1:56 AM by zijianhuang

comments

zijianhuang wrote Feb 14 at 8:28 AM

The problem is in Path.GetDirectoryName(filePath) in public static RollingTextWriter Create(string filePathTemplate). filePath could contain template valuables. In .NET Frameworks before 4.6https://essentialdiagnostics.codeplex.com/workitem/49/edit#.2, GetDirectoryName apparently tolerate symbols of template variables, but .NET Framework 4.6.2 will throw exception complaining invalid format.

The fix could be like this:
        public static RollingTextWriter Create(string filePathTemplate)
        {
            var segments = filePathTemplate.Split('%');
            if (segments.Length > 3)
            {
                throw new ArgumentException("InitializeData should contain maximum 1 environment variable.", "filePathTemplate");
            }
            else if (segments.Length == 3)
            {
                var variableName = segments[1];
                var rootFolder = Environment.GetEnvironmentVariable(variableName);
                if (String.IsNullOrEmpty(rootFolder))
                {
                    if (variableName.Equals("ProgramData", StringComparison.CurrentCultureIgnoreCase) && (Environment.OSVersion.Version.Major <= 5))//XP or below: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724832%28v=vs.85%29.aspx
                    {//So the host program could run well in XP and Windows 7 without changing the config file.
                        rootFolder = Path.Combine(Environment.GetEnvironmentVariable("AllUsersProfile"), "Application Data");
                    }
                    else
                    {
                        throw new ArgumentException("Environment variable is not recognized in InitializeData.", "filePathTemplate");
                    }
                }
                var filePath = rootFolder + segments[2];
                return new RollingTextWriter(filePath);
            }

            return new RollingTextWriter(filePathTemplate);

        }
So this will call GetDirectoryName no more, getting around the breaking change in .NET Framework. Though this fix will lost the feature of creating the directory not existing, however, the overall logic may be more consistent, because in EnsureCurrentWriter(), DirectoryNotFoundException could be thrown.