首页 > 其他分享 >UWP WinUI3 传入 AddHandler 的 RoutedEventHandler 类型与事件所需不匹配将抛出参数异常

UWP WinUI3 传入 AddHandler 的 RoutedEventHandler 类型与事件所需不匹配将抛出参数异常

时间:2024-09-12 08:54:11浏览次数:1  
标签:WinUI3 代码 UWP System AddHandler handler 参数 git

本文记录一个 UWP 或 WinUI3 的开发过程中的问题,当开发者调用 AddHandler 时,所需的 Handler 参数类型为 RoutedEventHandler 类型,然而实际上正确类型是需要与所监听事件匹配才能符合预期工作,否则将抛出缺乏信息的参数异常

开始之前先惯例吐槽一下,我从 2015 开始开发 UWP 应用,然而到 2024 的时候,依然没有看到开发体验上的优化。且在 WinUI3 的技术底层设计上就存在无解问题,那就是许多错误只依靠 COM 的 HR 错误号信息,开发者难以了解真正意义上的调错信息和具体的错误原因。比如说本文所记录的问题

以下是最短复现问题的代码

    public MainPage()
    {
        this.InitializeComponent();
        RoutedEventHandler handler = (_, _) =>
        {
            System.Diagnostics.Debug.WriteLine("PointerPressed");
        };

        AddHandler(PointerPressedEvent, handler, true);
    }

以上代码是能够通过构建的,原因是 AddHandler 里面的 Handler 参数就是 object 类型的。然而在运行中将会抛出参数异常,异常信息如下

System.ArgumentException: Value does not fall within the expected range.
   at WinRT.ExceptionHelpers.<ThrowExceptionForHR>g__Throw|39_0(Int32 hr)

异常里面还有 HResult 是 -2147024809 的值。其实这个 -2147024809 需要使用 16 进制去看,结果是有名的 0x80070057 错误号。通过 Error 工具可以看到这表示的是 COM 的通用错误信息,名为 E_INVALIDARG 的错误,意思就是参数错误

# for hex 0x80070057 / decimal -2147024809
  COR_E_ARGUMENT                                                 corerror.h
# An argument does not meet the contract of the method.
  DDERR_INVALIDPARAMS                                            ddraw.h
  DIERR_INVALIDPARAM                                             dinput.h
  DSERR_INVALIDPARAM                                             dsound.h
  STIERR_INVALID_PARAM                                           stierr.h
  DRM_E_INVALIDARG                                               windowsplayready.h
  E_INVALIDARG                                                   winerror.h
# One or more arguments are invalid
# as an HRESULT: Severity: FAILURE (1), FACILITY_WIN32 (0x7), Code 0x57
# for hex 0x57 / decimal 87
  ERROR_INVALID_PARAMETER                                        winerror.h
# The parameter is incorrect.
# 8 matches found for "0x80070057"

这就是 WinUI3 的一个无解设计问题,通过 HResult 返回错误信息,所包含的信息量太少了,且很多时候距离实际错误点又十分远。应用开发者又不知道 WinUI3 底层投了哪些毒,难以知道所说的参数错误具体指的是什么错误。这一点也是制约了 WinUI 3 的生态,但这一点又是属于 WinUI 3 的基础设计的问题,预估难以更改

这一次的错误信息里面在 Data 里面还包含几条看似没有用,实际也没有用的信息,分别如下

+		[0]	{[Description, 不支持此接口
]}	object {System.Collections.DictionaryEntry}
+		[1]	{[RestrictedDescription, 不支持此接口
]}	object {System.Collections.DictionaryEntry}
+		[2]	{[RestrictedErrorReference, ]}	object {System.Collections.DictionaryEntry}
+		[3]	{[RestrictedCapabilitySid, ]}	object {System.Collections.DictionaryEntry}
+		[4]	{[__RestrictedErrorObjectReference, WinRT.ExceptionHelpers+__RestrictedErrorObject]}	object {System.Collections.DictionaryEntry}
+		[5]	{[__HasRestrictedLanguageErrorObject, False]}	object {System.Collections.DictionaryEntry}

也就是描述信息里面说的是 不支持此接口 的描述信息,合起来就是:遇到参数错误了,因为底层不支持参数传进来的此接口

但是就是不告诉大家,具体错误的是哪个参数,且错在哪里了。要是能够明白说明 handler 参数的类型不符合预期之类的,那开发者的调试效率将会高出许多

本文记录的错误问题原因是 PointerPressedEvent 所对应的是 PointerEventHandler 类型,而不是 RoutedEventHandler 类型,修复的代码如下

        PointerEventHandler handler = (_, _) =>
        {
            System.Diagnostics.Debug.WriteLine("PointerPressed");
        };

        AddHandler(PointerPressedEvent, handler, true);

那日常开发过程中,如何知道 AddHandler 里面的 handler 参数应该传入什么类型的委托呢?其实方法很简单,只需要使用对应的事件,看看对应的事件定义是什么。比如 PointerPressedEvent 对应的就是 PointerPressed 事件,按照通用命名法就是对应的事件就是对应路由事件定义去掉 Event 后缀。通过查阅文档或者是在 VisualStudio 里面点点看,就可以看到对应的事件的定义,如下面代码就是 PointerPressed 的定义,可以看到事件是 PointerEventHandler 类型的委托

public event PointerEventHandler PointerPressed { add; remove; }

通过此方式即可知道传入 AddHandler 的 handler 应该使用什么样的类型,解决运行时失败的原因。常见的错误都在于更改代码的时候,忘记同步更改对应的委托类型

额外补充一点,以上的代码的 handler 局部变量是安全的,不会被回收,原因是虽然在以上代码里面看起来 handler 局部变量没被引用,然而在 AddHandler 底层里面已经做好了引用,不会导致 handler 被回收,从而导致 COM 层访问被回收的内存而炸掉的问题。但是此问题在古老的 UWP 是存在的。一个推荐的优化方法就是将 handler 存放在字段里面,手动防止被回收

本文代码放在 githubgitee 上,可以使用如下命令行拉取代码

先创建一个空文件夹,接着使用命令行 cd 命令进入此空文件夹,在命令行里面输入以下代码,即可获取到本文的代码

git init
git remote add origin https://gitee.com/lindexi/lindexi_gd.git
git pull origin d43a62536b449ef337160f9931265a0db482ed12

以上使用的是 gitee 的源,如果 gitee 不能访问,请替换为 github 的源。请在命令行继续输入以下代码,将 gitee 源换成 github 源进行拉取代码

git remote remove origin
git remote add origin https://github.com/lindexi/lindexi_gd.git
git pull origin d43a62536b449ef337160f9931265a0db482ed12

获取代码之后,进入 FelawchechadaGeqedaihallnela 文件夹,即可获取到源代码

标签:WinUI3,代码,UWP,System,AddHandler,handler,参数,git
From: https://www.cnblogs.com/lindexi/p/18049575

相关文章

  • windows C++ 并行编程-并发和UWP(三)
    控制执行线程Windows运行时使用COM线程模型。在此模型中,根据对象处理其同步的方式,对象被托管在不同的单元中。线程安全对象托管在多线程单元(MTA)中。必须通过单个线程访问的对象托管在单线程单元(STA)中。在具有UI的应用程序中,ASTA(应用程序STA)线程负责发送窗......
  • windows C++ 并行编程-并发和UWP(一)
    本文介绍当在通用Windows运行时(UWP)应用中使用任务类生成基于Windows线程池的异步操作时要谨记的一些要点。异步编程的使用是Windows运行时应用模型中的关键组成部分,因为它能使应用保持对用户输入的响应。可以启动长期运行的任务,而不必阻止UI线程,并且可以在以后接......
  • Windows UWP应用无法联网 微软商店怎么不能联网了?
    因为日常需要在谷歌学术查阅一些文献以及上Github,因此梯子总是保持默认开启的状体。于是就发现一个问题是,Windows商城始终是无法联网的,翻了翻网上大家的记录,国内按理说是可以连上的,于是进行的相关搜索,最终发现了解决方法:如何为Windows10UWP应用设置代理-知乎(zhihu.c......
  • WPF 模拟UWP原生窗口样式——亚克力|云母材质、自定义标题栏样式、原生DWM动画 (附我封
    先看一下最终效果,左图为使用亚克力材质并添加组合颜色的效果;右图为MicaAlt材质的效果。两者都自定义了标题栏并且最大限度地保留了DWM提供的原生窗口效果(最大化最小化、关闭出现的动画、窗口阴影、拖拽布局器等)。接下来把各部分的实现一个个拆开来讲讲。一、使用窗口材质特......
  • 1、.Net UI框架:UWP - .Net宣传系列文章
    UWP(UniversalWindowsPlatform)是微软推出的一种应用程序开发平台,它允许开发者创建能够在各种Windows10设备上运行的应用程序,包括PC、平板、手机、Xbox、HoloLens等。UWP是Windows10操作系统的核心组件之一,它提供了统一的API和开发工具,使得开发者能够编写一次代码,然后在多个......
  • dotnet WinUI3 Win2D 翻转图片
    本文将告诉大家如何在WinUI3里面使用Win2D进行图片的翻转,本文的方法也适用于UWP框架图片的翻转在Win2D里面,可以使用Transform2DEffect特效来辅助实现,核心逻辑就是通过缩放矩阵当成2D翻转矩阵,将缩放的X和Y传入负数即可分别实现对应方向的翻转。比如左右水平翻转可将......
  • UWP WinUI 制作一个路径矢量图标按钮样式入门
    本文将告诉大家如何在UWP或WinUI3或UNO里,如何制作一个路径按钮。路径按钮就是使用几何路径轮廓表示内容的按钮,常见于各种图标按钮,或svg系贴图矢量图按钮在网上有非常多矢量图库,其中免费的图库也非常多,比如https://www.iconfont.cn/等等。在咱的应用程序里面,可以使用这......
  • wpf 动画显示隐藏_[UWP]用Win2D和CompositionAPI实现文字的发光效果,并制作动画
    weixin_39880899于2020-12-1109:26:23发布阅读量521 收藏点赞数文章标签: wpf动画显示隐藏  1.成果 献祭了周末的晚上,成功召唤出了上面的番茄钟。正当我在感慨“不愧是Shadow大人,这难道就是传说中的五彩斑斓的黑?”“那才不是什么阴影效果,那是......
  • 【UWP】修改清单脱离沙盒运行
    总说周知,UWP是运行在沙盒里面的,所有权限都有严格限制,和沙盒外交互也需要特殊的通道,所以从根本杜绝了UWP毒瘤的存在。但是实际上UWP只是一个应用模型,本身是没有什么权限管理的,权限管理全靠AppContainer沙盒控制,如果我们脱离了这个沙盒,UWP就会放飞自我了。那么有没有这种可......
  • AddHandler导致的解析漏洞
    https://www.freebuf.com/vuls/303745.html在etc/apache/site-enabled下设置配置文件添加AddHandlerapplication/x-httpd-php.php然后重启apache服务配置问题导致总结:1)如果在Apache的/etc/apache2/apache2.conf里有这样的配置<FilesMatch"YLion.jpg">​SetHandler......