WPF 已知问题 某些设备上的应用在 WindowChromeWorker 抛出 System.OverflowException 异常
准确来说,这个不算是 WPF 的问题,而是系统等的问题。在某些设备上的使用了 WindowChrome 功能的 WPF 应用,将在运行过程,在 WindowChromeWorker 类里面抛出 System.OverflowException 异常。核心原因是这些设备是 x64 设备,运行的 x64 的 WPF 应用程序,在消息循环里面传入的 lParam 是一个 x64 的指针,但在 WPF 里面使用 ToInt32 方法进行转换,刚好此 x64 的指针超过 int 的范围,从而抛出异常
这是一个上古就存在的问题,有人报告说安装了某些驱动就会存在此异常,但是我没有调查到在符合什么情况下就会抛出此异常。此异常的调用堆栈大概如下
System.OverflowException
HResult=0x80131516
Message=Arithmetic operation resulted in an overflow.
Source=PresentationFramework
StackTrace:
at System.Windows.Shell.WindowChromeWorker._HandleNCHitTest(WM uMsg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at System.Windows.Shell.WindowChromeWorker._WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at System.Windows.Interop.HwndSource.PublicHooksFilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
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)
at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
异常的中文描述是 算术运算导致溢出
通过阅读代码可以了解到是在 WindowChromeWorker._WndProc 方法里面接收到 Windows 消息,在 _HandleNCHitTest 转换 lParam 参数读取时抛出异常,以下是此方法的有删减的代码
private IntPtr _HandleNCHitTest(WM uMsg, IntPtr wParam, IntPtr lParam, out bool handled)
{
DpiScale dpi = _window.GetDpi();
// Let the system know if we consider the mouse to be in our effective non-client area.
var mousePosScreen = new Point(Utility.GET_X_LPARAM(lParam), Utility.GET_Y_LPARAM(lParam));
Rect windowPosition = _GetWindowRect();
// 忽略代码
}
现在的 WPF 是基于最友好的 MIT 协议开源的,所有的源代码都可以从 https://github.com/dotnet/wpf 下载到。如果对以上的 _HandleNCHitTest 方法感兴趣,想要阅读完全的代码,还请到官方开源仓库获取
通过以上代码可以看到,使用 Utility 的 GET_X_LPARAM 方法从 lParam 参数获取一个点的 x 参数。从业务分析上,实际上 lParam 转换的 x 参数是作为屏幕的坐标点,而屏幕的坐标点在 2022 时还是一个 Int16 范围的值。换句话说,如果 lParam 转换出一个 Int64 的长度,那一定是不符合预期的
在 GET_X_LPARAM 方法里面,将会通过 ToInt32 的方法进行转换,且取其低位。在 GET_Y_LPARAM 里,将会转换 lParam 为 Int32 取高位。而抛出的异常就是 ToInt32 这个方法
如果传入了一个 IntPtr 是一个 long 的值,那将会在 ToInt32 方法抛出 OverflowException 异常
我将此问题报告给 WPF 官方,请看 System.OverflowException in PresentationFramework.dll in System.Windows.Shell.WindowChromeWorker · Issue #6777 · dotnet/wpf
然而有趣的是我就是 WPF 官方开发者,于是我就自己修复了这个问题,请看 Fix System.OverflowException in WindowChromeWorker._HandleNCHitTest by lindexi · Pull Request #6779 · dotnet/wpf
我的修复的方法是转换为 Long 再进行裁剪,这个做法我认为是对的,我也阅读了一些相关的对 NCHitTest 消息处理的博客,例如 当无边框窗口被子窗口遮挡导致难以调节窗口大小时,可通过处理 NCHITTEST 消息重新支持调节窗口大小 - walterlv 也都是如此处理
不过在我的代码还没被合入之前,可以先采用以下代码减少抛出异常
protected override void OnSourceInitialized( EventArgs e )
{
base.OnSourceInitialized( e );
( (HwndSource)PresentationSource.FromVisual( this ) ).AddHook( HookProc );
}
private IntPtr HookProc( IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled )
{
if ( msg == 0x0084 /*WM_NCHITTEST*/ )
{
// 如果尝试转换失败,那就吃掉这个消息
// This prevents a crash in WindowChromeWorker._HandleNCHitTest
try
{
lParam.ToInt32();
}
catch ( OverflowException )
{
handled = true;
}
}
return IntPtr.Zero;
}
更多的相关链接:
OverflowException when converting 64-bit IntPtr to Int32 ControlzEx/ControlzEx#30
Arithmetic operation resulted in an overflow. MahApps/MahApps.Metro#3301
Exception:算术运算导致溢出。 HandyOrg/HandyControl#886
https://developercommunity.visualstudio.com/t/overflow-exception-in-windowchrome/167357
WPF 已知问题 某些设备上的应用在 WindowChromeWorker 抛出 System.OverflowException 异常的更多相关文章
- WPF窗体视图中绑定Resources文件中字符串时,抛出:System.Windows.Markup.StaticExtension
问题描述: 在Resources.resx定义了一个静态字符串字段Title,并在WPF窗体视图中绑定为窗体的标题: Title="{x:Static local:Resources.Tit ...
- 调用远程主机上的 RMI 服务时抛出 java.rmi.ConnectException: Connection refused to host: 127.0.0.1 异常原因及解决方案
最近使用 jmx 遇到一个问题,client/server 同在一台机器上,jmx client能够成功连接 server,如果把 server 移植到另一台机器上192.168.134.128,抛出 ...
- Java13新特性 -- 新增 移除 废弃 已知问题等
新增 添加FileSystems.newFileSystem(Path, Map<String, ?>) Method 新的java.nio.ByteBuffer Bulk get/put ...
- Java知多少(49)throw:异常的抛出
到目前为止,你只是获取了被Java运行时系统抛出的异常.然而,程序可以用throw语句抛出明确的异常.Throw语句的通常形式如下: throw ThrowableInstance;这里,Thr ...
- 记一次asp.net core 在iis上运行抛出502.5错误
asp.net core 在iis上运行抛出502.5异常的部分原因以及解决方案 环境说明 已安装 .net core runtime 2.1.401 已安装 .net core windows ho ...
- c# throw抛出上一个异常
catch(exception e) { throw; } 不仅抛出这次的异常,也抛出之前的异常. 用法示例:函数A调用函数B,A用到此throw时,B中发生的异常也会继承过来. catch(exce ...
- 已知圆上三个点坐标,求圆半径 r 和 圆心坐标
问题: 已知圆上三个点坐标分别为(x1,y1).(x2,y2).(x3,y3) 求圆半径R和圆心坐标(X,Y) X,Y,R为未知数,x1,y1,x2,y2,x3,y3为常数 则由圆公式:(x1-X)² ...
- 已知空间两点组成的直线求线上某点的Z值
已知空间两点组成的直线求线上某点的Z值,为什么会有这种看起来比较奇怪的求值需求呢?因为真正三维空间的几何计算是比较麻烦的,很多时候需要投影到二维,再反推到三维空间上去. 复习下空间直线方程:已知空间上 ...
- HoloLens开发手记 - Known issues 已知问题
本文主要提及一份问题清单,这些问题都可能对我们开发HoloLens应用造成困扰. Visual Studio 在使用VS 2015 Update 1连接HoloLens时,可能会有些小问题.但是这些小 ...
- 实战分享:如何成功防护1.2T国内已知最大流量DDoS攻击
作者:腾讯云宙斯盾安全团队&腾讯安全平台部 引言: DDoS攻击势头愈演愈烈,除了攻击手法的多样化发展之外,最直接的还是攻击流量的成倍增长.3月份国内的最大规模DDoS攻击纪录还停留在数百G规 ...
随机推荐
- SSR解决了什么问题?有做过SSR吗?你是怎么做的?
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 一.是什么 Server-Side Rendering 我们称其为SSR,意为服务端渲染 指由服务侧完成页面的 HTML 结构拼接的页面处 ...
- JQ实现音乐插件并自动播放
这里分享我最近写出来的一个小东西,基于jq的音乐播放器,可以嵌套到网站 效果截图: 具体首页代码如下: <!DOCTYPE html> <html> <head> ...
- CentOS7.5安装JDK8
1.下载地址 https://www.oracle.com/java/technologies/javase-jdk8-downloads.html 2.创建文件夹 mkdir /usr/java 3 ...
- 如何使用文件传输协议ftp,教你使用文件传输协议命令行
FTP是文件传输协议的缩写.顾名思义,FTP用于在网络上的计算机之间传输文件.您可以使用文件传输协议在计算机帐户之间交换文件,在帐户和台式计算机之间传输文件或访问在线软件档案.但是请记住,许多文件传输 ...
- 为什么SOTA网络在你的数据集上不行?来看看Imagnet结果的迁移能力研究
论文通过实验证明,ImageNet上的模型并不总能泛化到其他数据集中,甚至可能是相反的,而模型的深度和宽度也会影响迁移的效果. 如果需要参考,可选择类别数与当前任务相似的数据集上的模型性能.论文通 ...
- KingbaseES V8R3集群运维案例---进程内核参数配置集群启动故障
案例说明: KingbaseES V8R3集群在部署时需要配置与进程间通讯(IPC)相关的内核参数,如果缺失配置或配置错误,kingbasecluster服务在启动过程中将因为内核参数配置错误导致启动 ...
- 性能对比 Go、Python、Perl、Ruby、Rust、C/C++、PHP、Node.js、Java.. 等多编
1. 有人说 Python 性能没那么 Low? 这个我用 pypy 2.7 确认了下,确实没那么差, 如果用 NumPy 或 其它版本 Python 的话,性能更快.但 pypy 还不完善,pypy ...
- #线段树#LOJ 6029「雅礼集训 2017 Day1」市场
题目 在长度为\(n(n\leq 10^5)\)的数列中, 需要满足区间加,区间下取整的操作 以及能够查询区间和以及区间最小值 除数\(d\)满足\(2\leq d\leq 10^9\) 加数\(c\ ...
- 深入理解 C++ 右值引用和移动语义:全面解析
C++11引入了右值引用,它也是C++11最重要的新特性之一.原因在于它解决了C++的一大历史遗留问题,即消除了很多场景下的不必要的额外开销.即使你的代码中并不直接使用右值引用,也可以通过标准库,间接 ...
- JVM—垃圾收集器
JVM-垃圾收集器 什么是垃圾 没有被引用的对象就是垃圾. 怎么找到垃圾 引用计数法 当对象引用消失,对象就称为垃圾. 对象消失一个引用,计数减去一,当引用都消失了,计数就会变为0.此时这个对象就会变 ...