WinDBG: memory dump from WinForms application - how to get a value of text box

329 Views Asked by At

I have a memory dump from a GUI application (.NET, WinForms) and I am trying to get the value of a textbox (i.e. the value entered in the textbox).

I can get to the underlying text box object, but the text field is empty:

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

(but the textbox is definitely populated as I can see the value on the screen).

Is there a way to get the value of text box text field/property?

1

There are 1 best solutions below

0
Thomas Weller On

The WinForms textbox does not always create a new string object each time you press a key, unless you have code that forces that. If you paste a 32767 char CounterString into the TextBox, you would expect a twice as long string somewhere on the .NET heap, but there isn't:

0:012> !dumpheap -mt 689024e4 -min 0n65000
 Address       MT     Size

Statistics:
      MT    Count    TotalSize Class Name
Total 0 objects

So you can't simply access it via !dumpheap and !do.

ReferenceSource gives us

public override string Text {
    get {
        return base.Text;
    }
    set {
        base.Text = value;
        selectionSet = false;
    }
}

and thus delegates to TextBoxBase, which delegates again to Control.

public virtual string Text {
    get {
        if (CacheTextInternal) {
            return(text == null) ? "" : text;
        }
        else {
            return WindowText;
        }
    }

There we see that the text property you identified us used in case of caching or uses WindowText instead.

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();

And with Spy++ one can confirm WM_GETTEXTLENGTH (GetWindowTextLength) and WM_GETTEXT (GetWindowText) are used to get the text from the native control:

Windows messages in Spy++

So, as long as your .NET code does not access the Text property of the TextBox, you need to be looking on the native side of the control.