WPF的TreeView执行ExpandSubtree时抛出异常System.NullReferenceException


最近拿到一个dump,有应用崩溃,通过查看dump,异常信息如下:

0:012> !pe
Exception object: 0000000005187278
Exception type:   System.NullReferenceException
Message:          Object reference not set to an instance of an object.
InnerException:   <none>
StackTrace (generated):
    SP               IP               Function
    000000002144DB50 000007FEEDF84989 PresentationFramework_ni!System.Windows.Controls.TreeViewItem.ExpandRecursive(System.Windows.Controls.TreeViewItem)+0x119
    000000002144DC10 000007FEEDF84B46 PresentationFramework_ni!System.Windows.Controls.TreeViewItem.ExpandRecursive(System.Windows.Controls.TreeViewItem)+0x2d6
    000000002144DCD0 000007FEEDE574B8 PresentationFramework_ni!System.Windows.Controls.TreeView.ExpandSubtree(System.Windows.Controls.TreeViewItem)+0x18
    000000002144DD00 000007FEEDE572F5 PresentationFramework_ni!S ystem.Windows.Controls.TreeView.OnKeyDown(System.Windows.Input.KeyEventArgs)+0x135
    000000002144DD40 000007FEF116B1E3 PresentationCore_ni!System.Windows.RoutedEventArgs.InvokeHandler(System.Delegate, System.Object)+0x53
    000000002144DDA0 000007FEF116A991 PresentationCore_ni!System.Windows.EventRoute.InvokeHandlersImpl(System.Object, System.Windows.RoutedEventArgs, Boolean)+0x271
    000000002144DFE0 000007FEF115408E PresentationCore_ni!System.Windows.UIElement.RaiseEventImpl(System.Windows.DependencyObject, System.Windows.RoutedEventArgs)+0x14e
    000000002144E070 000007FEF114FF66 PresentationCore_ni!System.Windows.UIElement.RaiseTrustedEvent(System.Windows.RoutedEventArgs)+0x96
    000000002144E0D0 000007FEF117C921 PresentationCore_ni!System.Windows.Input.InputManager.ProcessStagingArea()+0x471
    000000002144E160 000007FEF117C42B PresentationCore_ni!System.Windows.Input.InputManager.ProcessInput(System.Windows.Input.InputEventArgs)+0xab
    000000002144E1B0 000007FEF117C1BC PresentationCore_ni!System.Windows.Interop.HwndKeyboardInputProvider.ReportInput(IntPtr, System.Windows.Input.InputMode, Int32, System.Windows.Input.RawKeyboardActions, Int32, Boolean, Boolean, Int32)+0x1bc

!pe即PrintException,从异常堆栈信息上可以看到当时在TreeView上按了某个键导致TreeView要展开TreeViewItem,然后循环时抛出空指针异常。

接下来就是查看当时传递的KeyDown事件是哪个,查看google后有的人说通过!clrstack -p可以看到函数参数的地址, 但试过后发现由于是Release版本,这个windbg命令并不起效。
只能用笨办法,通过!dso来查看当时整个线程所有堆栈变量, 如下:
0:012> ~12e !dso
OS Thread Id: 0xba4 (12)
RSP/REG          Object           Name
00000000214479B0 0000000005187278 Syste.NullReferenceException
000000002144DCB0 00000000051840c8 System.Windows.Input.KeyEventArgs
000000002144DCC0 0000000002d728f8 System.Windows.Controls.TreeView
000000002144DCD0 00000000041c1188 System.Windows.Controls.TreeViewItem

上面12是抛异常的clr线程号,可以通过~*kb查看所有现场的堆栈,就可以知道具体线程号
从上面命令的部分信息可以看到当时KeyEventArgs的地址。

接下来通过!do命令查看具体信息
012> !do 00000000051840c8
Name:        System.Windows.Input.KeyEventArgs
MethodTable: 000007fef1283900
EEClass:     000007fef0ee4de0
Size:        80(0x50) bytes
File:        C:\Windows\Microsoft.Net\assembly\GAC_64\PresentationCore\v4.0_4.0.0.0__31bf3856ad364e35\PresentationCore.dll
Fields:
              MT    Field   Offset                 Type VT     Attr            Value Name
000007fef5070c78  40001c7       80     System.EventArgs  0   shared           static Empty
                                 >> Domain:Value  00000000008083f0:0000000002bd96d0 <<
000007fef1279088  40012ff        8 ...ndows.RoutedEvent  0 instance 0000000002ba43d0 _routedEvent
000007fef5055ac8  4001300       10        System.Object  0 instance 0000000002d728f8 _source
000007fef5055ac8  4001301       18        System.Object  0 instance 00000000041c1188 _originalSource
000007fef43990a8  4001302       20 ...lized.BitVector32  1 instance 00000000051840e8 _flags
000007fef128b320  40016ce       28 ...Input.InputDevice  0 instance 0000000002bc2f00 _inputDevice
000007fef505c858  40016cf     1460         System.Int32  1   static        396682259 _timestamp
000007fef3161bf0  40018ba       38         System.Int32  1 instance               84 _realKey
000007fef3161bf0  40018bb       3c         System.Int32  1 instance               84 _key
000007fef1283da8  40018bc       30 ...resentationSource  0 instance 0000000003f8d7a0 _inputSource
000007fef505d688  40018bd       44       System.Boolean  1 instance                0 _isRepeat
000007fef505c858  40018be       40         System.Int32  1 instance               55 _scanCode
000007fef505d688  40018bf       45       System.Boolean  1 instance                0 _isExtendedKey

从上面可以看到当时按键Key的值是84,
通过查看enum类型的Key源码,发现84是*
namespace System.Windows.Input
{
  [ValueSerializer( typeof (KeyValueSerializer))]
  [TypeConverter( typeof (KeyConverter))]
  public enum Key
  {

    NumPad9 = 83,
    Multiply = 84,
    Add = 85,
    Separator = 86,
    Subtract = 87,
    Decimal = 88,
    Divide = 89,

通过查看TreeView的代码也可以看出Multiply的快捷键作用是ExpandSubTree

                        case Key.Multiply:
                            if (ExpandSubtree(_selectedContainer))
                            {
                                e.Handled = true ;
                            }
                            break ;

结论:
*是TreeView控件的默认系统快捷键,用来展开TreeViewItem,当TreeView的Style有问题时,导致递归展开子项时抛了异常。

解决办法:
修改Style或者屏蔽快捷键。

你可能感兴趣的:(exception,WPF,treeview,windbg,expandSubtree)