准确来说,这个不算是 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;
}

更多的相关链接:

System.OverflowException in PresentationFramework.dll in System.Windows.Shell.WindowChromeWorker microsoft/dotnet#689

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

https://stackoverflow.com/questions/33287542/what-would-cause-wm-nchittest-lparam-to-overflow-a-32-bit-integer

WPF 已知问题 某些设备上的应用在 WindowChromeWorker 抛出 System.OverflowException 异常的更多相关文章

  1. WPF窗体视图中绑定Resources文件中字符串时,抛出:System.Windows.Markup.StaticExtension

    问题描述: 在Resources.resx定义了一个静态字符串字段Title,并在WPF窗体视图中绑定为窗体的标题: Title="{x:Static local:Resources.Tit ...

  2. 调用远程主机上的 RMI 服务时抛出 java.rmi.ConnectException: Connection refused to host: 127.0.0.1 异常原因及解决方案

    最近使用 jmx 遇到一个问题,client/server 同在一台机器上,jmx client能够成功连接 server,如果把 server 移植到另一台机器上192.168.134.128,抛出 ...

  3. Java13新特性 -- 新增 移除 废弃 已知问题等

    新增 添加FileSystems.newFileSystem(Path, Map<String, ?>) Method 新的java.nio.ByteBuffer Bulk get/put ...

  4. Java知多少(49)throw:异常的抛出

    到目前为止,你只是获取了被Java运行时系统抛出的异常.然而,程序可以用throw语句抛出明确的异常.Throw语句的通常形式如下:    throw ThrowableInstance;这里,Thr ...

  5. 记一次asp.net core 在iis上运行抛出502.5错误

    asp.net core 在iis上运行抛出502.5异常的部分原因以及解决方案 环境说明 已安装 .net core runtime 2.1.401 已安装 .net core windows ho ...

  6. c# throw抛出上一个异常

    catch(exception e) { throw; } 不仅抛出这次的异常,也抛出之前的异常. 用法示例:函数A调用函数B,A用到此throw时,B中发生的异常也会继承过来. catch(exce ...

  7. 已知圆上三个点坐标,求圆半径 r 和 圆心坐标

    问题: 已知圆上三个点坐标分别为(x1,y1).(x2,y2).(x3,y3) 求圆半径R和圆心坐标(X,Y) X,Y,R为未知数,x1,y1,x2,y2,x3,y3为常数 则由圆公式:(x1-X)² ...

  8. 已知空间两点组成的直线求线上某点的Z值

    已知空间两点组成的直线求线上某点的Z值,为什么会有这种看起来比较奇怪的求值需求呢?因为真正三维空间的几何计算是比较麻烦的,很多时候需要投影到二维,再反推到三维空间上去. 复习下空间直线方程:已知空间上 ...

  9. HoloLens开发手记 - Known issues 已知问题

    本文主要提及一份问题清单,这些问题都可能对我们开发HoloLens应用造成困扰. Visual Studio 在使用VS 2015 Update 1连接HoloLens时,可能会有些小问题.但是这些小 ...

  10. 实战分享:如何成功防护1.2T国内已知最大流量DDoS攻击

    作者:腾讯云宙斯盾安全团队&腾讯安全平台部 引言: DDoS攻击势头愈演愈烈,除了攻击手法的多样化发展之外,最直接的还是攻击流量的成倍增长.3月份国内的最大规模DDoS攻击纪录还停留在数百G规 ...

随机推荐

  1. 记录--记录用前端代替后端生成zip的过程,速度快了 57 倍!!!

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 业务场景: 产品有个功能是设置主题.类似手机自动切换壁纸,以及其他功能颜色,icon,字体等. 管理员需要在后端管理系统多次下载不同主题, ...

  2. Swift Structured Concurrency

    异步函数 异步函数概念 异步和并发是两个不同的概念,并发(Concurrency)是指多个任务同时执行,这里的同时不是严格意义上的同一时刻,而是在稍大时间粒度上,多个任务可以同时推进,并发的实现可以是 ...

  3. 记一次 .NET某防伪验证系统 崩溃分析

    一:背景 1. 讲故事 昨晚给训练营里面的一位朋友分析了一个程序崩溃的故障,因为看小伙子昨天在群里问了一天也没搞定,干脆自己亲自上阵吧,抓取的dump也是我极力推荐的用 procdump 注册 AED ...

  4. KingbaseES V8R6 备份恢复案例--异机备份ssh认证失败

    案例说明: 在生产环境,数据库服务被重启后,监控发现数据库物理备份的脚本无法执行,故障现象如下所示,从备份日志和sys_log中都出现了远程主机连接认证错误. 1)备份日志:(连接数据库服务器认证错误 ...

  5. (1,3,4,2,5)小和问题【Java】

    01[1,3,4,2,5]求小和 从右往左看:左边比右边小的加和到一起! 1 左边没有数 0 3 1 4 1+3 2 1 5 1+3+4+2 从左往右看:有几个数右边比左边大 1 4个数: 3 4 2 ...

  6. 【已解决】org.apache.thrift.transport.TTransportException: Could not create ServerSocket on address 0.0.0.0/0.0.0.0:9083.

    杀死这些进程 kill -9 进程号

  7. vector优化

    C++的stdvector使用优化 #include<iostream> #include<vector> using namespace std; class Vectex ...

  8. 深度剖析:Dubbo使用Nacos注册中心的坑

    2020年笔者在做微服务部件升级时,Dubbo的注册中心从Zookeeper切换到Nacos碰到个问题,最近刷Github又有网友提到类似的问题,就在这篇文章里做个梳理和总结. 1.问题描述 前几年我 ...

  9. AI云增强升级!还原生动人像,拍出质感照片

    近期不少细心用户发现,在用HUAWEI Mate 60 Pro手机拍照后,使用相册中的AI云增强功能,照片变得更加细腻有质感.这是因为AI云增强升级并更新支持了人像模式拍摄的照片,高清自然的人像细节还 ...

  10. 新手真的别再用过时的jenkins freestyle了,10分钟教你搞定快速编写jenksinfile,快速离线调试

    Pipeline是一套运行于jenkins上的工作流框架,将原本独立运行于单个或者多个节点的任务连接起来,实现单个任务难以完成的复杂流程编排与可视化.它通过Domain Specific Langua ...