WinDBG:来自 WinForms 应用程序的内存转储 - 如何获取文本框的值
Posted
技术标签:
【中文标题】WinDBG:来自 WinForms 应用程序的内存转储 - 如何获取文本框的值【英文标题】:WinDBG: memory dump from WinForms application - how to get a value of text box 【发布时间】:2021-10-18 00:32:59 【问题描述】:我有一个来自 GUI 应用程序(.NET、WinForms)的内存转储,我正在尝试获取文本框的值(即在文本框中输入的值)。
我可以访问底层文本框对象,但 text
字段为空:
0:009> !DumpObj /d 000002afab5bc530
Name: System.Windows.Forms.TextBox
MethodTable: 00007ff87c847038
EEClass: 00007ff87c8ffe30
Size: 248(0xf8) bytes
File: C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System.Windows.Forms\v4.0_4.0.0.0__b77a5c561934e089\System.Windows.Forms.dll
Fields:
MT Field Offset Type VT Attr Value Name
00007ff88c655dd8 40005ba 8 System.Object 0 instance 0000000000000000 __identity
00007ff88ba275a0 400293e 10 ...ponentModel.ISite 0 instance 0000000000000000 site
00007ff88ba1dbd0 400293f 18 ....EventHandlerList 0 instance 000002afab5bd4b8 events
00007ff88c655dd8 400293d 11d0 System.Object 0 static 0000000000000000 EventDisposed
00007ff87c84a188 400081b 20 ...ntrolNativeWindow 0 instance 000002afab5bc660 window
00007ff87c8487e8 400081c 28 ...ows.Forms.Control 0 instance 000002afab558398 parent
00007ff87c8487e8 400081d 30 ...ows.Forms.Control 0 instance 000002afab558398 reflectParent
00007ff87c84aab0 400081e 38 ...orms.CreateParams 0 instance 000002afab5bd3d8 createParams
00007ff88c6585a0 400081f 70 System.Int32 1 instance 34 x
00007ff88c6585a0 4000820 74 System.Int32 1 instance 63 y
00007ff88c6585a0 4000821 78 System.Int32 1 instance 229 width
00007ff88c6585a0 4000822 7c System.Int32 1 instance 20 height
00007ff88c6585a0 4000823 80 System.Int32 1 instance 225 clientWidth
00007ff88c6585a0 4000824 84 System.Int32 1 instance 16 clientHeight
00007ff88c6585a0 4000825 88 System.Int32 1 instance 16908815 state
00007ff88c6585a0 4000826 8c System.Int32 1 instance 2120 state2
00007ff87d6d2da0 4000827 90 System.Int32 1 instance 8768 controlStyle
00007ff88c6585a0 4000828 94 System.Int32 1 instance 2 tabIndex
00007ff88c6559c0 4000829 40 System.String 0 instance 0000000000000000 text <<<<<< this one
(但文本框肯定已填充,因为我可以在屏幕上看到值)。
有没有办法获取文本框text
字段/属性的值?
【问题讨论】:
.NET 属性是一对函数,一个 getter 和一个 setter。 WinForms 文本框中的文本是本机 Windows 文本框控件中的文本(通过将 WM_SETTEXT 和 WM_GETTEXT 消息发送到控件/窗口来设置。抱歉,我目前知识不足,希望对您有所帮助。您可以在 MSFT 调试博客上找到一些帮助。请记住,这不是特定于 WinForms,您使用的是原生 Windows 控件 看起来Control
使用StringBuilder
将文本存储在getter internal virtual string WindowText
即StringBuilder sb = new StringBuilder(textLen + 1);
所以只要StringBuilder
对象没有被垃圾收集,那么你应该能够找到它。您可能想尝试使用 sourceforge 上的免费工具 ClrDbg
。
【参考方案1】:
WinForms 文本框并不总是在您每次按下某个键时创建一个新的字符串对象,除非您有强制执行此操作的代码。如果您将 32767 字符 CounterString 粘贴到 TextBox 中,您会期望在 .NET 堆上的某处有两倍长的字符串,但实际上没有:
0:012> !dumpheap -mt 689024e4 -min 0n65000
Address MT Size
Statistics:
MT Count TotalSize Class Name
Total 0 objects
因此您不能简单地通过!dumpheap
和!do
访问它。
ReferenceSource给我们
public override string Text
get
return base.Text;
set
base.Text = value;
selectionSet = false;
因此委托给 TextBoxBase,TextBoxBase 再次委托给 Control。
public virtual string Text
get
if (CacheTextInternal)
return(text == null) ? "" : text;
else
return WindowText;
我们看到您识别出的text
属性用于缓存或使用WindowText
。
int textLen = SafeNativeMethods.GetWindowTextLength(new HandleRef(window, Handle));
// Check to see if the system supports DBCS character
// if so, double the length of the buffer.
if (SystemInformation.DbcsEnabled)
textLen = (textLen * 2) + 1;
StringBuilder sb = new StringBuilder(textLen + 1);
UnsafeNativeMethods.GetWindowText(new HandleRef(window, Handle), sb, sb.Capacity);
return sb.ToString();
使用 Spy++ 可以确认 WM_GETTEXTLENGTH (GetWindowTextLength) 和 WM_GETTEXT (GetWindowText) 用于从本机控件获取文本:
因此,只要您的 .NET 代码不访问 TextBox 的 Text
属性,您就需要查看控件的本机端。
【讨论】:
以上是关于WinDBG:来自 WinForms 应用程序的内存转储 - 如何获取文本框的值的主要内容,如果未能解决你的问题,请参考以下文章
来自 AForge FFMPEG 的图片框为空 - C#/WinForms
Richtexbox 如何在 Winforms 上附加来自事件侦听器的异步文本?