|
// 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);
}
}
|