/// <summary>
        /// Invoked when the debugger transitions from Design mode to Run mode or Break mode.
        /// </summary>
        public int StartDebuggingPE()
        {
            try
            {
                log.Write("Enter Debug Mode: project '{0}'", _vsProject.DisplayName);

                // EnC service is global (per solution), but the debugger calls this for each project.
                // Avoid starting the debug session if it has already been started.
                if (_encService.DebuggingSession == null)
                {
                    Debug.Assert(s_debugStateProjectCount == 0);
                    Debug.Assert(s_breakStateProjectCount == 0);
                    Debug.Assert(s_breakStateEnteredProjects.Count == 0);

                    _encService.OnBeforeDebuggingStateChanged(DebuggingState.Design, DebuggingState.Run);

                    _encService.StartDebuggingSession(_vsProject.VisualStudioWorkspace.CurrentSolution);
                    s_encDebuggingSessionInfo = new EncDebuggingSessionInfo();

                    s_readOnlyDocumentTracker = new VsReadOnlyDocumentTracker(_encService, _editorAdaptersFactoryService, _vsProject);
                }

                string outputPath = _vsProject.TryGetObjOutputPath();

                // The project doesn't produce a debuggable binary or we can't read it.
                // Continue on since the debugger ignores HResults and we need to handle subsequent calls.
                if (outputPath != null)
                {
                    try
                    {
                        InjectFault_MvidRead();
                        _metadata = ModuleMetadata.CreateFromFile(outputPath);
                        _metadata.GetModuleVersionId();
                    }
                    catch (FileNotFoundException)
                    {
                        // If the project isn't referenced by the project being debugged it might not be built.
                        // In that case EnC is never allowed for the project, and thus we can assume the project hasn't entered debug state.
                        log.Write("StartDebuggingPE: '{0}' metadata file not found: '{1}'", _vsProject.DisplayName, outputPath);
                        _metadata = null;
                    }
                    catch (Exception e)
                    {
                        log.Write("StartDebuggingPE: error reading MVID of '{0}' ('{1}'): {2}", _vsProject.DisplayName, outputPath, e.Message);
                        _metadata = null;

                        var descriptor = new DiagnosticDescriptor("Metadata", "Metadata", ServicesVSResources.ErrorWhileReading, DiagnosticCategory.EditAndContinue, DiagnosticSeverity.Error, isEnabledByDefault: true, customTags: DiagnosticCustomTags.EditAndContinue);

                        _diagnosticProvider.ReportDiagnostics(_encService.DebuggingSession, EditAndContinueDiagnosticUpdateSource.DebuggerErrorId, _vsProject.Id, _encService.DebuggingSession.InitialSolution,
                            new[]
                            {
                                Diagnostic.Create(descriptor, Location.None, outputPath, e.Message)
                            });
                    }
                }
                else
                {
                    log.Write("StartDebuggingPE: project has no output path '{0}'", _vsProject.DisplayName);
                    _metadata = null;
                }

                if (_metadata != null)
                {
                    // The debugger doesn't call EnterBreakStateOnPE for projects that don't have MVID.
                    // However a project that's initially not loaded (but it might be in future) enters 
                    // both the debug and break states.
                    s_debugStateProjectCount++;
                }

                _activeMethods = new HashSet<uint>();
                _exceptionRegions = new List<VsExceptionRegion>();
                _activeStatementIds = new Dictionary<uint, ActiveStatementId>();

                // The HResult is ignored by the debugger.
                return VSConstants.S_OK;
            }
            catch (Exception e) when (FatalError.ReportWithoutCrash(e))
            {
                return VSConstants.E_FAIL;
            }
        }
        public int StopDebuggingPE()
        {
            try
            {
                log.Write("Exit Debug Mode: project '{0}'", _vsProject.DisplayName);
                Debug.Assert(s_breakStateEnteredProjects.Count == 0);

                // Clear the solution stored while projects were entering break mode. 
                // It should be cleared as soon as all tracked projects enter the break mode 
                // but if the entering break mode fails for some projects we should avoid leaking the solution.
                Debug.Assert(s_breakStateEntrySolution == null);
                s_breakStateEntrySolution = null;

                // EnC service is global (per solution), but the debugger calls this for each project.
                // Avoid ending the debug session if it has already been ended.
                if (_encService.DebuggingSession != null)
                {
                    _encService.OnBeforeDebuggingStateChanged(DebuggingState.Run, DebuggingState.Design);

                    _encService.EndDebuggingSession();
                    LogEncSession();

                    s_encDebuggingSessionInfo = null;
                    s_readOnlyDocumentTracker.Dispose();
                    s_readOnlyDocumentTracker = null;
                }

                if (_metadata != null)
                {
                    _metadata.Dispose();
                    _metadata = null;

                    s_debugStateProjectCount--;
                }
                else
                {
                    // an error might have been reported:
                    _diagnosticProvider.ClearDiagnostics(_encService.DebuggingSession, _vsProject.VisualStudioWorkspace, EditAndContinueDiagnosticUpdateSource.DebuggerErrorId, _vsProject.Id, documentId: null);
                }

                _activeMethods = null;
                _exceptionRegions = null;
                _committedBaseline = null;
                _activeStatementIds = null;

                Debug.Assert((_pdbReaderObjAsStream == IntPtr.Zero) || (_pdbReader == null));

                if (_pdbReader != null)
                {
                    Marshal.ReleaseComObject(_pdbReader);
                    _pdbReader = null;
                }

                // The HResult is ignored by the debugger.
                return VSConstants.S_OK;
            }
            catch (Exception e) when (FatalError.ReportWithoutCrash(e))
            {
                return VSConstants.E_FAIL;
            }
        }
        public int StopDebuggingPE()
        {
            try
            {
                log.Write("Exit Debug Mode: project '{0}'", _vsProject.DisplayName);
                Debug.Assert(s_breakStateEnteredProjects.Count == 0);

                // EnC service is global (per solution), but the debugger calls this for each project.
                // Avoid ending the debug session if it has already been ended.
                if (_encService.DebuggingSession != null)
                {
                    _encService.EndDebuggingSession();
                    LogEncSession();

                    s_encDebuggingSessionInfo = null;
                    s_readOnlyDocumentTracker.Dispose();
                    s_readOnlyDocumentTracker = null;
                }

                if (_metadata != null)
                {
                    _metadata.Dispose();
                    _metadata = null;

                    s_debugStateProjectCount--;
                }
                else
                {
                    // an error might have been reported:
                    _diagnosticProvider.ClearDiagnostics(_encService.DebuggingSession, _vsProject.VisualStudioWorkspace, EditAndContinueDiagnosticUpdateSource.DebuggerErrorId, _vsProject.Id, documentId: null);
                }

                _activeMethods = null;
                _exceptionRegions = null;
                _committedBaseline = null;
                _activeStatementIds = null;

                if (_pdbReaderObj != null)
                {
                    Marshal.ReleaseComObject(_pdbReaderObj);
                    _pdbReaderObj = null;
                }

                if (_pdbProvider != null)
                {
                    _pdbProvider.Dispose();
                    _pdbProvider = null;
                }

                _pdbReader = null;

                // The HResult is ignored by the debugger.
                return VSConstants.S_OK;
            }
            catch (Exception e) when(FatalError.Report(e))
            {
                throw ExceptionUtilities.Unreachable;
            }
            }