ICorDebugValue GetCorValue(Value objectInstance) { if (objectInstance != null) { if (!DeclaringType.IsInstanceOfType(objectInstance)) { throw new CannotGetValueException("Object is not of type " + DeclaringType.FullName); } } // Current frame is used to resolve context specific static values (eg. ThreadStatic) ICorDebugFrame curFrame = null; if (this.Process.IsPaused && this.Process.SelectedThread != null && this.Process.SelectedThread.LastFunction != null && this.Process.SelectedThread.LastFunction.CorILFrame != null) { curFrame = this.Process.SelectedThread.LastFunction.CorILFrame.CastTo <ICorDebugFrame>(); } try { if (this.IsStatic) { return(DeclaringType.CorType.GetStaticFieldValue(MetadataToken, curFrame)); } else { return(objectInstance.CorObjectValue.GetFieldValue(DeclaringType.CorType.Class, MetadataToken)); } } catch (System.Exception e) { throw new CannotGetValueException(e.Message); } }
// See docs\Stepping.txt public void CheckExpiration() { try { ICorDebugChainEnum chainEnum = CorThread.EnumerateChains(); } catch (COMException e) { // 0x8013132D: The state of the thread is invalid. // 0x8013134F: Object is in a zombie state // 0x80131301: Process was terminated. if ((uint)e.ErrorCode == 0x8013132D || (uint)e.ErrorCode == 0x8013134F || (uint)e.ErrorCode == 0x80131301) { this.Expire(); return; } else { throw; } } if (process.Evaluating) { return; } ICorDebugChainEnum corChainEnum = CorThread.EnumerateChains(); int maxChainIndex = (int)corChainEnum.Count - 1; ICorDebugFrameEnum corFrameEnum = corChainEnum.Next().EnumerateFrames(); // corFrameEnum.Count can return 0 in ExitThread callback int maxFrameIndex = (int)corFrameEnum.Count - 1; ICorDebugFrame lastFrame = corFrameEnum.Next(); // Check the token of the current function - function can change if there are multiple handlers for an event Function function; if (lastFrame != null && functionCache.TryGetValue(new FrameID((uint)maxChainIndex, (uint)maxFrameIndex), out function) && function.Token != lastFrame.FunctionToken) { functionCache.Remove(new FrameID((uint)maxChainIndex, (uint)maxFrameIndex)); function.OnExpired(EventArgs.Empty); } // Expire all functions behind the current maximum // Multiple functions can expire at once (test case: Step out of Button1Click in simple winforms application) List <KeyValuePair <FrameID, Function> > toBeRemoved = new List <KeyValuePair <FrameID, Function> >(); foreach (KeyValuePair <FrameID, Function> kvp in functionCache) { if ((kvp.Key.ChainIndex > maxChainIndex) || (kvp.Key.ChainIndex == maxChainIndex && kvp.Key.FrameIndex > maxFrameIndex)) { toBeRemoved.Add(kvp); } } foreach (KeyValuePair <FrameID, Function> kvp in toBeRemoved) { functionCache.Remove(kvp.Key); kvp.Value.OnExpired(EventArgs.Empty); } }