How to tell if a .Net control is visible using windbg
I got a crashdump where we're debating whether a control was visible to the end user or not. Looking with !do I can't see any explic开发者_JAVA百科it field that holds the true/false value matching up with the Visible property, which doesn't surprise that much as we're probably down in win32 teritory. Does anyone know how to deduce what Visible would have returned from the dump file?
thanks Oskar
My initial thought was that this was just a question of looking up the right field, but actually it took a bit more digging. If you look at Control in Reflector, you'll see that the Visible property calls GetVisibleCore, which checks an internal state field against the value 2 (which happens to be the constant STATE_VISIBLE).
So in order to find out if a control is visible, we need to locate the state field and do some bit manipulation.
If you have the address of the instance, you can do the following:
.shell -ci "!do <ADDRESS>" grep state (use findstr, if you don't have grep)
The output is something similar to this
0:000> .shell -ci "!do 015892a4" grep state
03aeedcc 400112c 4c System.Int32 1 instance 17432589 state <=== HERE!
03aeedcc 400112d 50 System.Int32 1 instance 2060 state2
049ac32c 40011ef d0 ...lized.BitVector32 1 instance 01589374 state
03aeedcc 40011f0 ad4 System.Int32 1 static 1 stateScalingNeededOnLayout
03aeedcc 40011f1 ad8 System.Int32 1 static 2 stateValidating
03aeedcc 40011f2 adc System.Int32 1 static 4 stateProcessingMnemonic
03aeedcc 40011f3 ae0 System.Int32 1 static 8 stateScalingChild
03aeedcc 40011f4 ae4 System.Int32 1 static 16 stateParentChanged
Notice, that there are two state fields. I haven't looked into why this is the case, but the one you want is the System.Int32. In my example it has a value of 17432589.
The code in GetState is as follows
return ((this.state & flag) != 0);
so all you have to do from here is (17432589 & 2) != 0
and you'll have the Visible state of the specific instance.
Actually, you may have to go a step further. If the above returns false, you need to look up the parent and repeat the trick. For my simple example using a Form that was not necessary.
精彩评论