C#由于获取WPF窗口名称造成的异常报错问题

报错内容

报错信息:win32Exception:传递给系统调用的数据区域太小。在MS.Win32.UnsafeNativeMethons.GetWindowText中报错

csharp 复制代码
//报错的代码部分
namespace MS.Win32;

[MS.Internal.WindowsBase.FriendAccessAllowed]
internal sealed class UnsafeNativeMethods

[SecurityCritical]
internal static int GetWindowText(HandleRef hWnd, [Out] StringBuilder lpString, int nMaxCount)
{
    int windowText = NativeMethodsSetLastError.GetWindowText(hWnd, lpString, nMaxCount);
    if (windowText == 0)
    {
        int lastWin32Error = Marshal.GetLastWin32Error();
        if (lastWin32Error != 0)
        {
            throw new Win32Exception(lastWin32Error);
        }
    }
    return windowText;
}
csharp 复制代码
//上一层堆栈
namespace System.Windows.Automation.Peers;

/// <summary>Exposes <see cref="T:System.Windows.Window" /> types to UI Automation.</summary>
public class WindowAutomationPeer : FrameworkElementAutomationPeer

[SecurityCritical]
[SecurityTreatAsSafe]
protected override string GetNameCore()
{
    string text = base.GetNameCore();
    if (text == string.Empty)
    {
        Window window = (Window)base.Owner;
        if (!window.IsSourceWindowNull)
        {
            StringBuilder stringBuilder = new StringBuilder(512);
            MS.Win32.UnsafeNativeMethods.GetWindowText(new HandleRef(null, window.CriticalHandle), stringBuilder, stringBuilder.Capacity);
            text = stringBuilder.ToString();
            if (text == null)
            {
                text = string.Empty;
            }
        }
    }
    return text;
}

解决办法

1.如果是.Net 的框架,则更新到.Net7以上

2.如果是.Net Formwork框架,则更新Windows系统为win10_22H1以上版本

分析

在之前,我在分析来自于系统原子表溢出造成的软件闪退问题中(链接)

csharp 复制代码
https://blog.csdn.net/m0_51559565/article/details/142548105?spm=1011.2415.3001.5331

同样都是来自于微软的Win32的报错,查询逻辑也是比较相似,我们首要需要在微软的官网查询到对应函数代表的作用和意思

在微软的官方文档中。说明当前函数是作为获取窗口的句柄和窗口名称的作用。

在WPF中,每一次页面的刷新,都需要获取到对应的页面句柄和窗口名称。所有这个问题应该是在刷新页面UI时候出现的问题。实际上,问题的出现也是在设备运行时,在更新当前窗口状态时候报的错误。

由于时WPF刷新UI的问题,那么涉及到底层的问题,大概率是我们不能解决的。所以第一时间先克隆一份WPF的源码。

在WPF中,通常所有涉及框架底层的报错的问题,我们可以直接在WPF的GitHub中提出问题,并附带报错信息。微软官方在看到问题后,一般都会有人进行解决。

csharp 复制代码
//WPF源码Github链接
https://github.com/dotnet/wpf.git


从报错的源码向上查找堆栈。

在protected override string GetNameCore()中我们可以发现现在源码和我们报错的代码不一样,可以证明,可能是在此处有过修改。这个时候我们可以查看一下这条函数的提交记录。

在2023年6月28日有一个异常报错的提交数据。Git的提交信息中显示,

注释提到在GetWindowText失败时回退到Window.Title,这是为了修复特定的错误(#7344和#7345)。此外,注释解释了这是为了从不良行为的窗口消息挂钩中恢复,这些挂钩可能会在消息处理期间更改最后一个错误。这个的作用就是在GetWindowText报错时进行报错捕获,返回当前窗口的标题。

由于时2023年6月的Git提交,后续没有其他额外的内容了。通常这种情况,微软会在下一个.Net版本会更新推送这个新的代码。由于.net formwork并不会频繁更新版本。但是formwork会在Windows中拿到win32的DLL,所以这个更新提交会更随着Windows的版本进行更新。

所以我们只需要对Windows和.net进行更新到2023年6月的版本。

题外

另外有意思的是。只是我没想到,微软的人也喜欢直接在报错时候直接tryCatch就完事了。

相关推荐
曹牧1 小时前
C#:未被引用的函数
c#
java资料站4 小时前
二、Spring AI Alibaba · ChatModel
java·windows·spring
北冥you鱼5 小时前
Go 语言空接口(interface{})使用场景与最佳实践
开发语言·windows·golang
上位机妹子6 小时前
EF Core 两种继承映射:每层次一张表(TPH)与每类型一张表(TPT)
数据库·c#·.netcore·ef core
夏虫不可与之言冰8 小时前
Windows WSL2 (Ubuntu) 搭建 ESP‑IDF 6.1 开发环境全过程演示
linux·windows·ubuntu·esp32·乐鑫科技·乐鑫eim·乐鑫代理商
小羊没烦恼!8 小时前
jQuery1.5的改进细节
java·服务器·开发语言·前端·c#
下页、再停留9 小时前
【C#桌面客户端系列学习-8】批量导出数据为csv格式
开发语言·c#·visual studio
波力海苔夹心脆67510 小时前
C# 视觉检测实战:PLC 按钮触发 VisionPro 检测,OK 亮灯 / NG 灭灯(西门子 PLC,含界面显示与图片存档)
开发语言·经验分享·c#·自动化·视觉检测·.net
打工仔折腾 AI10 小时前
FaceFusion本地换脸实战:Windows整合包、模型选择与遮罩调参记录
人工智能·windows·后端·python·深度学习·性能优化·ai agent 实战
kim11 小时前
一个人 + AI,用 WinForms 搓了个 376KB 的 Windows 便签:便签 / 截图 / 标注 / OCR / 待办全塞进去了
c#