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_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts 中存的是字体名称及其文件位置的列表。但这些文件位置中有非法字符中有非法字符。在执行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_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Fonts";

        public const string FontsLocalMachineRegistryPath =

                  @"Software\Microsoft\Windows NT\CurrentVersion\Fonts";



        /// <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

你可能感兴趣的:(character)