• WPF 打印崩溃问题( 异常:Illegal characters in path/路径中有非法字符)


    现象:

      打印时候程序直接崩溃。调试时出现下列异常。

    异常信息:

      中文:System.ArgumentException : 路径中有非法字符。

      英文: System.ArgumentException' occurred in mscorlib.dll  Additional information: Illegal characters in path 

    堆栈信息:

    Stack Trace:=
       at System.IO.Path.CheckInvalidPathChars(String path)
       at System.IO.Path.Combine(String path1, String path2)
       at Microsoft.Internal.GDIExporter.BuildFontList(String fontdir)
       at Microsoft.Internal.GDIExporter.CGDIDevice.CheckFont(GlyphTypeface typeface, String name)
       at Microsoft.Internal.GDIExporter.CGDIRenderTarget.CreateFontW(GlyphRun pGlyphRun, Double fontSize, Double scaleY)
       at Microsoft.Internal.GDIExporter.CGDIRenderTarget.RenderTextThroughGDI(GlyphRun pGlyphRun, Brush pBrush)
       at Microsoft.Internal.GDIExporter.CGDIRenderTarget.DrawGlyphRun(Brush pBrush, GlyphRun glyphRun)
       at Microsoft.Internal.AlphaFlattener.BrushProxyDecomposer.Microsoft.Internal..AlphaFlattener.IProxyDrawingContext.DrawGlyphs(GlyphRun glyphrun, Geometry clip, Matrix trans, BrushProxy foreground)
       at Microsoft.Internal.AlphaFlattener.PrimitiveRenderer.DrawGlyphs(GlyphRun glyphrun, Rect bounds, Matrix trans, String desp)
       at Microsoft.Internal.AlphaFlattener.Flattener.AlphaRender(Primitive primitive, List`1 overlapping, Int32 overlapHasTransparency, Boolean disjoint, String desp)
       at Microsoft.Internal.AlphaFlattener.Flattener.AlphaFlatten(IProxyDrawingContext dc, Boolean disjoint)
       at Microsoft.Internal.AlphaFlattener.Flattener.Convert(Primitive tree, ILegacyDevice dc, Double width, Double height, Double dpix, Double dpiy, Nullable`1 quality)
       at Microsoft.Internal.AlphaFlattener.MetroDevice0.FlushPage(ILegacyDevice sink, Double width, Double height, Nullable`1 outputQuality)
       at Microsoft.Internal.AlphaFlattener.MetroToGdiConverter.FlushPage()
       at System.Windows.Xps.Serialization.NgcSerializationManager.EndPage()
       at System.Windows.Xps.Serialization.NgcFixedPageSerializer.SerializeObject(Object serializedObject)
       at System.Windows.Xps.Serialization.NgcDocumentPageSerializer.SerializeObject(Object serializedObject)
       at System.Windows.Xps.Serialization.NgcDocumentPaginatorSerializer.SerializeObject(Object serializedObject)
       at System.Windows.Xps.Serialization.NgcSerializationManager.SaveAsXaml(Object serializedObject)
       at System.Windows.Xps.XpsDocumentWriter.SaveAsXaml(Object serializedObject, Boolean isSync)
       at System.Windows.Xps.XpsDocumentWriter.Write(DocumentPaginator documentPaginator)
       at System.Windows.Controls.PrintDialog.PrintDocument(DocumentPaginator documentPaginator, String description)

    原因:

      在注册表 HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindows NTCurrentVersionFonts 中存的是字体名称及其文件位置的列表。但这些文件位置中有非法字符中有非法字符。在执行Path.Combine方法时,出现异常。

    解决方案:

      重新处理注册表。

    代码:

        public class FontsClearup
        {
            /// <summary>
            /// 获取系统文件位置
            /// </summary>
            [MethodImpl(MethodImplOptions.ForwardRef), SecurityCritical, SuppressUnmanagedCodeSecurity, DllImport("shell32.dll", CharSet = CharSet.Unicode)]
            internal static extern int SHGetSpecialFolderPathW(IntPtr hwndOwner, StringBuilder lpszPath, int nFolder, int fCreate);
    
            /// <summary>
            /// 获取字体文件夹
            /// </summary>
            /// <returns></returns>
            private static string GetFontDir()
            {
                var lpszPath = new StringBuilder(260);
                return SHGetSpecialFolderPathW(IntPtr.Zero, lpszPath, 20, 0) != 0 ? lpszPath.ToString().ToUpperInvariant() : null;
            }
    
            public const string FontsRegistryPath =
                      @"HKEY_LOCAL_MACHINESoftwareMicrosoftWindows NTCurrentVersionFonts";
            public const string FontsLocalMachineRegistryPath =
                      @"SoftwareMicrosoftWindows NTCurrentVersionFonts";
    
            /// <summary>
            /// 获取所有字体信息
            /// </summary>
            /// <returns></returns>
            public static IEnumerable<FontInfo> ScanAllRegistryFonts()
            {
                var fontNames = new List<FontInfo>();
                new RegistryPermission(RegistryPermissionAccess.Read, FontsRegistryPath).Assert();
                try
                {
                    var fontDirPath = GetFontDir();
                    using (var key = Registry.LocalMachine.OpenSubKey(FontsLocalMachineRegistryPath))
                    {
                        if (key == null)
                        {
                            return Enumerable.Empty<FontInfo>();
                        }
                        var valueNames = key.GetValueNames();
                        foreach (var valueName in valueNames)
                        {
                            var fontName = key.GetValue(valueName).ToString();
                            var fontInfo = new FontInfo
                                               {
                                                   Name = valueName,
                                                   RegistryKeyPath = key.ToString(),
                                                   Value = fontName
                                               };
                            try
                            {
                                var systemFontUri = new Uri(fontName, UriKind.RelativeOrAbsolute);
                                if (!systemFontUri.IsAbsoluteUri)
                                {
                                    new Uri(Path.Combine(fontDirPath, fontName));
                                }
                            }
                            catch
                            {
                                fontInfo.IsCorrupt = true;
                            }
                            fontNames.Add(fontInfo);
                        }
                        key.Close();
                        key.Flush();
                    }
                }
                catch (Exception exception)
                {
                    Console.WriteLine(exception);
                }
                finally
                {
                    CodeAccessPermission.RevertAssert();
                }
                return fontNames;
            }
    
            /// <summary>
            /// 获取所有异常字体信息
            /// </summary>
            /// <returns></returns>
            public static IEnumerable<FontInfo> GetAllCorruptFonts()
            {
                var fonts = ScanAllRegistryFonts();
                return fonts.Where(f => f.IsCorrupt);
             }
    
            /// <summary>
            /// 整理字体信息
            /// </summary>
            /// <param name="p_corruptFonts"></param>
            public static void FixRegistryFonts(IEnumerable<FontInfo> p_corruptFonts = null)
            {
                IEnumerable<FontInfo> corruptFonts = p_corruptFonts;
                if (corruptFonts == null)
                {
                    corruptFonts = GetAllCorruptFonts();
                }
    
                new RegistryPermission(RegistryPermissionAccess.Write, FontsRegistryPath).Assert();
                try
                {
                    using (var key = Registry.LocalMachine.OpenSubKey(FontsLocalMachineRegistryPath, true))
                    {
                        if (key == null) return;
                        foreach (var corruptFont in corruptFonts)
                        {
                            if (!corruptFont.IsCorrupt) continue;
                            var fixedFontName = RemoveInvalidCharsFormFontName(corruptFont.Value);
                            key.SetValue(corruptFont.Name, fixedFontName, RegistryValueKind.String);
                        }
                        key.Close();
                        key.Flush();
                    }
                }
                catch (Exception exception)
                {
                    Console.WriteLine(exception.Message);
                }
                finally
                {
                    CodeAccessPermission.RevertAssert();
                    ScanAllRegistryFonts();
                }
            }
    
            private static string RemoveInvalidCharsFormFontName(string fontName)
            {
                var invalidChars = Path.GetInvalidPathChars();
                var fontCharList = fontName.ToCharArray().ToList();
                fontCharList.RemoveAll(c => invalidChars.Contains(c));
                return new string(fontCharList.ToArray());
            }
        }
    
        public class FontInfo
        {
            public string RegistryKeyPath { get; set; }
            public bool IsCorrupt { get; set; }
            public string Name { get; set; }
            public string Value { get; set; }
    
        }

    执行:FontsClearup.FixRegistryFonts();

    其实方法的用法见注释。

    参考:http://www.dnsingh.com/MyBlog/?tag=/GDIExporter.BuildFontList

    本文原创手打,转载请注明出处。
  • 相关阅读:
    新世纪五笔字根实例
    7 天学会新世纪五笔——原来五笔是个拼字游戏
    Ubuntu 上安装使用 ibus-rime(超实用)
    Linux 上安装最新版 Brave Browser
    安装使用 GoldenDict 查词神器 (Windows/Mac/Linux)
    1.2-Physical Ergonomics
    Django
    前端
    python一些简单的入门知识
    触发器、函数、存储过程、视图
  • 原文地址:https://www.cnblogs.com/gaoshang212/p/3180969.html
Copyright © 2020-2023  润新知