views:

120

answers:

1

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 explicit 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

+4  A: 

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.

Brian Rasmussen
very nice, now I know that the control was visible (and my user right...) and have elsewhere verified that the server status in my process disagrees with what the control said, so the bug has to be somewhere in between :)
Oskar