Функция DocumentCollection.Open () не работает AutoCAD API

Я разрабатываю плагин AutoCAD для своего приложения. Я использую AutoCAD 2012. Плагин открывает именованный канал .NET, поэтому я могу легко подключиться к нему из своего настольного приложения.

Прежде всего, я создал интерфейс. Вот

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

Мой плагин AutoCAD является производным от интерфейса IExtensionApplication, поэтому в методе Initialize я написал это

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

В одной из функций мне нужно открыть документ и обработать его. Итак, я написал следующий код

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

Но это вызывает исключение COM в коде curDraw = docColl.Open(@"d:\1.dwg", true, string.Empty); с HRESULT = -2147418113

Мне нужен объект Document для обработки файла DWG. Есть ли какие-нибудь способы исправить эту ошибку?


person Denis Ionov    schedule 10.12.2013    source источник
comment
Вы пробовали делать что-то еще, кроме docColl.Open? Например, закрыть все открытые документы. Если да, то какую ошибку вы получили?   -  person Evgeny Timoshenko    schedule 19.12.2013
comment
Ага. Та же ошибка произошла, когда я попробовал. Я только что нашел решение. Я скоро напишу   -  person Denis Ionov    schedule 19.12.2013


Ответы (1)


AutoCAD не может работать с объектом документа из внешнего потока. В этом корень проблемы. Если я напишу метод и поставлю CommandMethodAttribute - он будет работать, но только из консоли AutoCAD ... Но что, если мне нужно будет делать эти операции из внешнего приложения? Прежде всего, необходимо указать атрибут в классе поведения службы.

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

Таким образом будет использоваться только один поток для всех операций.

На следующем шаге в методе Initialize() получите объект CurrentDispatcher и поместите его в статическую переменную.

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

таким образом можно добиться управления контекстом выполнения autocad. Следующим шагом будет вызов метода через диспетчер.

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

Итак, используя этот метод, я могу запустить код, содержащийся в методе GetPdfVer из внешнего приложения, и получить все преимущества использования WCF вместо COM-взаимодействия.

person Community    schedule 19.12.2013