WPF 加载诡异的字体无法布局
如果在系统里面存在诡异的字体,同时自己的 WPF 中有一个控件尝试使用这个字体放在界面中,那么将会在界面布局过程炸了,整个控件或者整个界面布局都无法继续
本文本来是由吕水大大发布的,但是他没空写,于是我就成为了写博客的工具人
有一个用户报告了软件在他的电脑上打不开列出本机字体列表,于是吕水大大就去远程他的设备,在用户的设备上找到了一个诡异的字体,加载这个字体的时候,将会在 MS.Internal.Text.TextInterface.Font.CreateFontFace 抛出异常。而且有趣的是 Win10 的 UWP 版的设置里面是找不到这个字体的,原因是 UWP 版本也会在读取此字体的时候炸了
复现的步骤如下,先从 https://github.com/walterlv/Walterlv.Demo.WpfBadFontCrash 下载代码,在代码仓库里面可以找到 不给糖就捣蛋的万圣节.TTF 这个字体,值得一说的是,诡异的字体有很多,这个字体只是一个例子。双击安装一下这个字体到你的系统上
然后新建一个 WPF 或 UWP 程序,在界面里面添加一个 TextBlock 然后在 TextBlock 里面采用此字体,如下面代码
<TextBlock Text="ABCDEFGH" FontFamily="不给糖就捣蛋的万圣节" />
参与运行此 WPF 程序,将会看到如下提示
System.IO.FileFormatException: Invalid file format.
at MS.Internal.Text.TextInterface.Native.Util.ConvertHresultToException(Int32 hr)
at MS.Internal.Text.TextInterface.Font.CreateFontFace()
at MS.Internal.Text.TextInterface.Font.AddFontFaceToCache()
at MS.Internal.Text.TextInterface.Font.GetFontFace()
at System.Windows.Media.GlyphTypeface..ctor(Font font)
at MS.Internal.FontFace.PhysicalFontFamily.GetGlyphTypeface(FontStyle style, FontWeight weight, FontStretch stretch)
at MS.Internal.FontFace.PhysicalFontFamily.MS.Internal.FontFace.IFontFamily.GetTypefaceMetrics(FontStyle style, FontWeight weight, FontStretch stretch)
at System.Windows.Media.Typeface.ConstructCachedTypeface()
at System.Windows.Media.Typeface.get_CachedTypeface()
at System.Windows.Media.Typeface.CheckFastPathNominalGlyphs(CharacterBufferRange charBufferRange, Double emSize, Single pixelsPerDip, Double scalingFactor, Double widthMax, Boolean keepAWord, Boolean numberSubstitution, CultureInfo cultureInfo, TextFormattingMode textFormattingMode, Boolean isSideways, Boolean breakOnTabs, Int32& stringLengthFit)
at MS.Internal.TextFormatting.SimpleRun.CreateSimpleTextRun(CharacterBufferRange charBufferRange, TextRun textRun, TextFormatterImp formatter, Int32 widthLeft, Boolean emergencyWrap, Boolean breakOnTabs, Double pixelsPerDip)
at MS.Internal.TextFormatting.SimpleRun.Create(FormatSettings settings, CharacterBufferRange charString, TextRun textRun, Int32 cp, Int32 cpFirst, Int32 runLength, Int32 widthLeft, Int32 idealRunOffsetUnRounded, Double pixelsPerDip)
at MS.Internal.TextFormatting.SimpleTextLine.Create(FormatSettings settings, Int32 cpFirst, Int32 paragraphWidth, Double pixelsPerDip)
at MS.Internal.TextFormatting.TextFormatterImp.FormatLineInternal(TextSource textSource, Int32 firstCharIndex, Int32 lineLength, Double paragraphWidth, TextParagraphProperties paragraphProperties, TextLineBreak previousLineBreak, TextRunCache textRunCache)
at MS.Internal.TextFormatting.TextFormatterImp.FormatLine(TextSource textSource, Int32 firstCharIndex, Double paragraphWidth, TextParagraphProperties paragraphProperties, TextLineBreak previousLineBreak, TextRunCache textRunCache)
at System.Windows.Controls.TextBlock.MeasureOverride(Size constraint)
at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
at System.Windows.UIElement.Measure(Size availableSize)
at System.Windows.Controls.Grid.MeasureOverride(Size constraint)
at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
at System.Windows.UIElement.Measure(Size availableSize)
at MS.Internal.Helper.MeasureElementWithSingleChild(UIElement element, Size constraint)
at System.Windows.Controls.ContentPresenter.MeasureOverride(Size constraint)
at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
at System.Windows.UIElement.Measure(Size availableSize)
at System.Windows.Controls.Decorator.MeasureOverride(Size constraint)
at System.Windows.Documents.AdornerDecorator.MeasureOverride(Size constraint)
at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
at System.Windows.UIElement.Measure(Size availableSize)
at System.Windows.Controls.Border.MeasureOverride(Size constraint)
at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
at System.Windows.UIElement.Measure(Size availableSize)
at System.Windows.Window.MeasureOverrideHelper(Size constraint)
at System.Windows.Window.MeasureOverride(Size availableSize)
at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
at System.Windows.UIElement.Measure(Size availableSize)
at System.Windows.Interop.HwndSource.SetLayoutSize()
at System.Windows.Interop.HwndSource.set_RootVisualInternal(Visual value)
at System.Windows.Interop.HwndSource.set_RootVisual(Visual value)
at System.Windows.Window.SetRootVisual()
at System.Windows.Window.SetRootVisualAndUpdateSTC()
at System.Windows.Window.SetupInitialState(Double requestedTop, Double requestedLeft, Double requestedWidth, Double requestedHeight)
at System.Windows.Window.CreateSourceWindow(Boolean duringShow)
at System.Windows.Window.CreateSourceWindowDuringShow()
at System.Windows.Window.SafeCreateWindowDuringShow()
at System.Windows.Window.ShowHelper(Object booleanBox)
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
如果上面的逻辑是放在 MainWindow 里面,那么意味着刚尝试创建窗口就凉凉了,可以看到窗口都创建失败。如果自己没有写 Dispatcher.UnhandledException 那么应用程序将会退出
代码请看 https://github.com/walterlv/Walterlv.Demo.WpfBadFontCrash
这个坑我报告给了 WPF 官方,请看 WPF can not handle special damaged font · Issue #4283 · dotnet/wpf
对于 UWP 来说也一样,尝试在界面中放和上面 WPF 相同的代码,可以看到设计器给出了提示

运行 UWP 应用,将可以看到进入了下面代码
#if DEBUG && !DISABLE_XAML_GENERATED_BREAK_ON_UNHANDLED_EXCEPTION
UnhandledException += (sender, e) =>
{
if (global::System.Diagnostics.Debugger.IsAttached) global::System.Diagnostics.Debugger.Break();
};
#endif
这里面的 e 的内容没有啥有用的信息,可以看到的代码如下
- Exception {"指示输入文件 (例如字体文件) 中的错误。\r\n\r\n指示输入文件 (例如字体文件) 中的错误。\r\n"} System.Exception {System.Runtime.InteropServices.COMException}
也就说 UWP 在调用到更底层的时候炸掉了,其实也看不到堆栈。同时在 UWP 如果是在第一个界面中添加以上代码,那么即使在 App.xaml.cs 使用下面代码尝试接住,应用也是继续退出
public App()
{
InitializeComponent();
Suspending += OnSuspending;
UnhandledException += App_UnhandledException;
}
private void App_UnhandledException(object sender, Windows.UI.Xaml.UnhandledExceptionEventArgs e)
{
e.Handled = true;
}
WPF 加载诡异的字体无法布局的更多相关文章
- WPF加载Winform窗体时 报错:子控件不能为顶级窗体
一.wpf项目中引用WindowsFormsIntegration和System.Windows.Forms 二.Form1.Designer.cs 的 partial class Form1 设置为 ...
- WPF加载HTML、WPF与JavaScript交互
目录 一.WebBrowser加载远程网页 二.WebBrowser加载本地网页,注:不可以加载本地样式CSS和脚本JS文件 三.WebBrowser隐藏网页的JavaScript错误 四.网页屏蔽鼠 ...
- ASP.net 加载不了字体Failed to load resource: the server responded with a status of 404 (Not Found)
在bootstrap下加载不了字体内容.出现下列错误. 1.打开IIS找到部署的网站,点击MIME类型,把.woff和.woff2两个类型分别添加到新类型中,重启网站即可.
- WPF 加载等待动画
原文:WPF 加载等待动画 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/qq_29844879/article/details/80216587 ...
- WPF加载等待动画
原文:WPF加载等待动画 原文地址:https://www.codeproject.com/Articles/57984/WPF-Loading-Wait-Adorner 界面遮罩 <UserC ...
- iOS加载动态自定义字体
iOS加载动态自定义字体 NSString *cachePath = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDom ...
- uiwebview 加载html时字体变小 加载前或加载后改变字体大小
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; color: #6122ae } p.p2 { margin: 0.0px 0. ...
- WPF加载程序集中字符串资源
WPF资源 WPF资源使用其实的也是resources格式嵌入资源,默认的资源名称为"应用程序名.g.resources",不过WPF资源使用的pack URI来访问资源. 添加图 ...
- WPF 加载 WINFORM控件 异常: 调度程序进程已挂起,但消息仍在处理中
在加载TradeAtServer的统计中的 单个合约盈亏情况 异常:,调度程序进程已挂起,但消息仍在处理中 发现可能是属性设置引发的问题 比如DateTimePikcer.Value+= set, g ...
- wpf 加载项目图片的几种写法
new System.Windows.Media.Imaging.BitmapImage( new Uri("pack://application:,,,/TeacherAssistant. ...
随机推荐
- 三维模型3DTile格式轻量化压缩的遇到常见问题与处理方法分析
三维模型3DTile格式轻量化压缩的遇到常见问题与处理方法分析 三维模型的轻量化压缩是一项技术挑战,特别是在处理复杂的3DTile格式时.下面列举了一些处理过程中可能遇到的常见问题以及相应的处理方法: ...
- 数据好合: Argilla 和 Hugging Face Spaces 携手赋能社区合力构建更好的数据集
最近,Argilla 和 Hugging Face 共同 推出 了 Data is Better Together 计划,旨在凝聚社区力量协力构建一个对提示进行排名的偏好数据集.仅用几天,我们就吸引了 ...
- 《2020年IT行业项目管理调查报告》重磅发布
近年来,IT行业迅速发展,物联网.敏捷.DevOps等已成为行业的热门话题.为更好地了解行业现状,禅道项目管理软件联合各合作伙伴于2021年1月开展了针对IT行业的问卷调查,并推出了<2020年 ...
- 如何拿到接口返回的消耗token
SemanticKernel 以下引用自官方案例 Text模型 使用Kernel FunctionResult functionResult = await kernel.InvokePromptAs ...
- cloudflare认识2(picgo结合使用)
参考:https://zhuanlan.zhihu.com/p/658058503 https://blog.csdn.net/CCCChris001122/article/details/13585 ...
- #树状数组#CF461C Appleman and a Sheet of Paper
题目传送门 分析 可以发现往左翻太多相当于往右翻一点,所以如果翻的位置超过一半那么打一个取反标记再另一边翻转, 用树状数组维护当前厚度,时间复杂度 \(O(n\log^2 n)\) 代码 #inclu ...
- netty系列之:在netty中实现线程和CPU绑定
目录 简介 引入affinity AffinityThreadFactory 在netty中使用AffinityThreadFactory 总结 简介 之前我们介绍了一个非常优秀的细粒度控制JAVA线 ...
- C 语言函数完全指南:创建、调用、参数传递、返回值解析
C 语言中的函数 函数是一段代码块,只有在被调用时才会运行. 您可以将数据(称为参数)传递给函数. 函数用于执行某些操作,它们对于重用代码很重要:定义一次代码,并多次使用. 预定义函数 事实证明,您已 ...
- 解析 Go 编程语言数据类型:bool、整数、浮点数和字符串详细介绍
数据类型 数据类型是编程中的重要概念.数据类型指定了变量值的大小和类型.Go是静态类型的,这意味着一旦变量类型被定义,它只能存储该类型的数据. 基本数据类型 Go 有三种基本数据类型: bool:表示 ...
- Python 集合(Sets)3
Python - 合并集合 在 Python 中,有几种方法可以合并两个或多个集合.您可以使用union()方法,该方法返回一个包含两个集合中所有项的新集合,或使用update()方法,将一个集合中的 ...