File: DebugEngine\ProgramPublisher.cs
Project: ndp\cdf\src\WF\RunTime\System.Workflow.Runtime.csproj (System.Workflow.Runtime)
// Copyright (c) Microsoft Corp., 2004. All rights reserved.
#region Using directives
 
using System;
using System.Threading;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Diagnostics;
 
#endregion
 
namespace System.Workflow.Runtime.DebugEngine
{
    [ComImport, Guid(Guids.CLSID_WDEProgramPublisher)]
    internal class WDEProgramPublisher
    {
    }
 
    internal sealed class ProgramPublisher
    {
        #region Data members
 
        private bool isPublished = false;
        IWDEProgramPublisher publisher;
        private DebugController controller;
        GCHandle gchWdeProgramNode; // This is used to pin the wdeProgramNodeSingleton (VS Debugger is using address to calculate cookies)
        private IWDEProgramNode wdeProgramNodeSingleton;
 
        #endregion
 
        #region Methods
 
        public ProgramPublisher()
        {
            this.publisher = null;
        }
 
        public bool Publish(DebugController controller)
        {
            Debug.WriteLine("WDE: ProgramPublisher.Publish()");
 
            // In order to guarantee that the Program Nodes are always in the MTA, publish on a separate thread.
            if (isPublished)
                return false;
 
            try
            {
                this.controller = controller;
                Thread publisherThread = new Thread(PublisherThreadFunc);
                publisherThread.SetApartmentState(ApartmentState.MTA);
                publisherThread.IsBackground = true;
                publisherThread.Start();
                publisherThread.Join();
            }
            catch (Exception e)
            {
                // Eat up exceptions if the debugger is not installed.
                Debug.WriteLine("WDE: ProgramPublisher.Publish() exception: " + e.ToString());
            }
 
            return this.isPublished;
        }
 
        private void PublisherThreadFunc()
        {
            try
            {
                this.publisher = new WDEProgramPublisher() as IWDEProgramPublisher;
                this.wdeProgramNodeSingleton = new ProgramNode(this.controller);
                this.gchWdeProgramNode = GCHandle.Alloc(this.wdeProgramNodeSingleton);
 
                this.publisher.Publish(this.wdeProgramNodeSingleton);
                this.isPublished = true;
            }
            catch (Exception e)
            {
                // Ignore any exceptions that are caused by WDE.dll not being present or registered.
                Debug.WriteLine("WDE: ProgramPublisher.PublisherThreadFunc() exception: " + e.ToString());
            }
        }
 
        public void Unpublish()
        {
            if (!isPublished)
                return;
 
            Debug.WriteLine("WDE: ProgramPublisher.Unpublish()");
 
            // In order to guarantee that the Program Nodes are always in the MTA, unpublish on a separate thread.
            try
            {
                Thread unpublisherThread = new Thread(UnpublishThreadFunc);
                unpublisherThread.SetApartmentState(ApartmentState.MTA);
                unpublisherThread.IsBackground = true;
                unpublisherThread.Start();
                unpublisherThread.Join();
            }
            catch (Exception e)
            {
                // Eat up exceptions if the debugger is not installed, etc.
                Debug.WriteLine("WDE: ProgramPublisher.Unpublish() exception: " + e.ToString());
            }
 
            Debug.WriteLine("WDE: ProgramPublisher.Unpublish() Done");
        }
 
        private void UnpublishThreadFunc()
        {
            try
            {
                this.publisher.Unpublish(this.wdeProgramNodeSingleton);
            }
            catch (Exception e)
            {
                Debug.WriteLine("WDE: ProgramPublisher.UnpublishThreadFunc(): catch exception " + e.ToString());
                // We eat up any exceptions that can occur because the host process is abnormally terminated.
            }
            finally
            {
                this.gchWdeProgramNode.Free(); // Rrelease pin on the this.wdeProgramNodeSingleton
 
                Marshal.ReleaseComObject(this.publisher);
                this.publisher = null;
            }
 
            this.isPublished = false;
        }
 
        #endregion
    }
 
    [ComImport(), Guid(Guids.IID_IWDEProgramPublisher), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    internal interface IWDEProgramPublisher
    {
        void Publish([MarshalAs(UnmanagedType.IUnknown)] object ProgramNode);
        void Unpublish([MarshalAs(UnmanagedType.IUnknown)] object ProgramNode);
    }
 
 
}