Question

I'm developing an AutoCAD plugin for my application. I'm using AutoCAD 2012. Plugin opens .NET named pipe, and so I can connect to it from my desktop application very easily.

First of all, i have created an interface. Here it is

[ServiceContract]
public interface IConnector
{
    [OperationContract]
    [FaultContract(typeof(Exception))]
    void GetPdfVersion(string filePath, string exportFilePath);
}

My AutoCAD plugin derived from IExtensionApplication interface, so on Initialize method i've written this

this.host = new ServiceHost(typeof(Printer), new[] { new Uri("net.pipe://localhost") });
this.host.AddServiceEndpoint(typeof(IConnector), new NetNamedPipeBinding(), "GetPdfVersion");
this.host.Open();

In one of functions, I need to open document and process it. So, I have written folowing code

var docColl = Application.DocumentManager;
Document curDraw = null;
try
{
    if (File.Exists(@"d:\1.dwg"))
    {
        curDraw = docColl.Open(@"d:\1.dwg", true, string.Empty);
    }
}
catch (Exception e)
{
    Console.WriteLine(e);
}

But it throws a COM exception, on the curDraw = docColl.Open(@"d:\1.dwg", true, string.Empty); code, with HRESULT=-2147418113

I need Document object for processing the dwg file. Is there any possible ways to fix that error?

Was it helpful?

Solution

AutoCAD can't work with document object from external thread. That's the root of the problem. If I write method and put an CommandMethodAttribute - it will be work, but only from AutoCAD console... But, what if I need to do this operations from external application? First of all, need to specify the attribute on service behavior class

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Single, IncludeExceptionDetailInFaults = true)]

Thus be used only one thread for all operations.

The next step, in Initialize() method get the CurrentDispatcher object and put it in static variable.

private static Dispatcher dispatcher;
public void Initialize()
    {
        dispatcher = Dispatcher.CurrentDispatcher;

        this.host = new ServiceHost(typeof(Printer), new[] { new Uri("net.pipe://localhost") });
        this.host.AddServiceEndpoint(typeof(IConnector), new NetNamedPipeBinding(), "GetPdfVersion");
        this.host.Open();
    }

by this way, control of autocad execution context can be achieved. The next step is invoke the method through dispatcher

public void GetPdfVersion(string filePath, string exportFilePath)
    {
        dispatcher.Invoke(new Action<string, string>(this.GetPdfVer), filePath, exportFilePath);   
    }

So, by using this method, I can run code, contained in GetPdfVer method from external application and get all benefits of using WCF instead of COM-interaction.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top