Доступ к Revit из внешнего приложения

Автор Тема: Доступ к Revit из внешнего приложения  (Прочитано 17505 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн Александр Игнатович

  • Administrator
  • *****
  • Сообщений: 1152
  • Карма: 338
  • Skype: alexandr.ignatovich.itc
Re: Доступ к Revit из внешнего приложения
« Ответ #15 : 02-05-2018, 16:26:38 »
Добрый день, коллеги.

Я честно говоря, не знаю, с чем именно связано изменение поведения кода в Revit 2019, полагаю, что дело всё же в реализации ServiceHost самим фреймворком. Дело в том, что исходный код полагается на то, что методы сервиса и обработчик события OnIdling вызываются более-менее независимо, т.е. в методе сервиса (упрощенно) запускается:
Код - C# [Выбрать]
  1. lock (Locker)
  2.             {
  3.                 TaskContainer.Instance.EnqueueTask(GetDocumentPath); // <- здесь запуск задачи GetDocumentPath
  4.  
  5.                 Monitor.Wait(Locker, WaitTimeout);// <- вот здесь ожидается, что где-то кто-то за отведенный промежуток времени вызовет Monitor.Pulse(Locker);
  6.             }
  7.  
  8.             return currentDocumentPath;
  9.  

Соответственно в обработчике событий вызывается Monitor.Pulse:
Код - C# [Выбрать]
  1.         private void GetDocumentPath(UIApplication uiapp)
  2.         {
  3.             try
  4.             {
  5.                 currentDocumentPath = uiapp.ActiveUIDocument.Document.PathName;
  6.             }
  7.             finally
  8.             {
  9.                 lock (Locker)
  10.                 {
  11.                     Monitor.Pulse(Locker); //<- ТЫЦ!
  12.                 }
  13.             }
  14.         }

Ну а сам этот код фактически вызывается из обработчика события OnIdling, который дергает сам Revit.

Всё вроде бы хорошо, но фактически событие OnIdling вызываться перестает, останавливаемся на строке
Код - C# [Выбрать]
  1. Monitor.Wait(Locker, WaitTimeout);
По таймауту сервис отваливается, а затем код успешно выполняется из обработчика события

Окей, так пусть же serviceHost открывается в отдельном потоке:
Код - C# [Выбрать]
  1.         private const string ServiceUrlHttp = "http://localhost:9001/RevitExternalService";
  2.         private const string ServiceUrlTcp = "net.tcp://localhost:9002/RevitExternalService";
Код - C# [Выбрать]
  1.         public Result OnStartup(UIControlledApplication application)
  2.         {
  3.             application.Idling += OnIdling;
  4.            
  5.             try
  6.             {
  7.                 Task.Factory.StartNew(() =>
  8.                 {
  9.                     var serviceHost = new ServiceHost(typeof(RevitExternalService), new Uri(ServiceUrlHttp), new Uri(ServiceUrlTcp));
  10.  
  11.                     serviceHost.Description.Behaviors.Add(new ServiceMetadataBehavior());
  12.                     serviceHost.AddServiceEndpoint(typeof(IRevitExternalService), new BasicHttpBinding(), ServiceUrlHttp);
  13.                     serviceHost.AddServiceEndpoint(typeof(IRevitExternalService), new NetTcpBinding(), ServiceUrlTcp);
  14.                     serviceHost.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexHttpBinding(), "mex");
  15.                     serviceHost.Open();
  16.                 }, TaskCreationOptions.LongRunning);
  17.                
  18.             }
  19.             catch (Exception ex)
  20.             {
  21. //....
  22.             }
  23.  
  24.             return Result.Succeeded;
  25.         }

Ну и собственно, теперь снова всё работает

Оффлайн Ярослав

  • ADN OPEN
  • **
  • Сообщений: 82
  • Карма: 1
Re: Доступ к Revit из внешнего приложения
« Ответ #16 : 03-05-2018, 09:14:20 »
Добрый день.
Спасибо, но теперь вообще не может подключится к сервису.
Так как адрес у меня в клиенте
            "net.pipe://localhost/"
 и клиент говорит что: прослушивание по net.pipe://localhost/ не выполняла ни одна конечная точка которая могла бы принять сообщение.
Или теперь нужно другой адрес вбивать?

Оффлайн Александр Игнатович

  • Administrator
  • *****
  • Сообщений: 1152
  • Карма: 338
  • Skype: alexandr.ignatovich.itc
Re: Доступ к Revit из внешнего приложения
« Ответ #17 : 03-05-2018, 09:58:30 »
Попробуйте другой адрес/порт, у меня, вообще говоря, в журнале была ошибка, что-то связанное с тем, что не удалось на этом адресе развернуть сервис, поскольку он уже кем-то используется. Сейчас не смогу полный текст привести, тут на работе Revit 2018, 19-ый только дома есть

Оффлайн Ярослав

  • ADN OPEN
  • **
  • Сообщений: 82
  • Карма: 1
Re: Доступ к Revit из внешнего приложения
« Ответ #18 : 03-05-2018, 10:27:24 »
А какой адрес задавать? При попытках задать адрес типа
       "http://localhost:9001/RevitExternalService";
        "net.tcp://localhost:9002/RevitExternalService";
клиент говорит что ему нужен net.pipe адрес.

А теперь вообще не хочет создавать сервер говорит : недопустимый URI в 
var serviceHost = new ServiceHost(typeof(RevitExternalService), new Uri(ServiceUrlHttp), new Uri(ServiceUrlTcp));

Оффлайн Александр Игнатович

  • Administrator
  • *****
  • Сообщений: 1152
  • Карма: 338
  • Skype: alexandr.ignatovich.itc
Re: Доступ к Revit из внешнего приложения
« Ответ #19 : 03-05-2018, 10:43:57 »
Ну странно вообще говоря, у меня завелось всё, единственное, нужно либо прописать в системе права на создание wcf-сервиса по данному адресу, либо запускать Revit от администратора. А клиент, да, ему нужно указать правильный конфиг/биндинг, либо использовать SvcUtil, чтобы сгенерировать код и конфиг-файл...

Адреса ServiceUrlHttp и ServiceUrlTcp взяли такие?
Код - C# [Выбрать]
  1.             private const string ServiceUrlHttp = "http://localhost:9001/RevitExternalService";
  2.             private const string ServiceUrlTcp = "net.tcp://localhost:9002/RevitExternalService";

Оффлайн Ярослав

  • ADN OPEN
  • **
  • Сообщений: 82
  • Карма: 1
Re: Доступ к Revit из внешнего приложения
« Ответ #20 : 03-05-2018, 11:02:46 »
Да такие. Так вот первый раз сервис запускался без проблем, только клиент не мог подключится к адресу. Но после того как я начал изменять конфиг файл клиента серверу перестал нравится URI.
А конфиг/биндинг нужно на оба подключения(ServiceUrlHttp и ServiceUrlTcp) создавать?

Оффлайн Александр Игнатович

  • Administrator
  • *****
  • Сообщений: 1152
  • Карма: 338
  • Skype: alexandr.ignatovich.itc
Re: Доступ к Revit из внешнего приложения
« Ответ #21 : 03-05-2018, 11:10:27 »
Вообще говоря не понял, каким образом серверу перестал нравиться URI при изменении клиента?

Подключение можно только то, что нужно, тогда только надо убрать второй end point тоже. Я делал на основе вот этого https://habr.com/post/331952/
Клиент писать было немного лень, использовал wcftestclient, подключался к endpoint-у на http.

Если хотите, вечером форкну проект, залью рабочую версию

Оффлайн Ярослав

  • ADN OPEN
  • **
  • Сообщений: 82
  • Карма: 1
Re: Доступ к Revit из внешнего приложения
« Ответ #22 : 03-05-2018, 11:16:47 »
С URI уже разобрался, после перезагрузки системы, заработало.
За проект буду очень благодарен.
А пока сам попробую разбираться.

Отмечено как Решение Александр Ривилис 04-05-2018, 14:01:02

Оффлайн Александр Игнатович

  • Administrator
  • *****
  • Сообщений: 1152
  • Карма: 338
  • Skype: alexandr.ignatovich.itc
Re: Доступ к Revit из внешнего приложения
« Ответ #23 : 03-05-2018, 21:53:48 »
Обещанный форк репозитория с рабочим кодом: https://github.com/CADBIMDeveloper/RevitExternalAccessDemo

Ну и результат работы создания стен, используя сервис:



Оффлайн Ярослав

  • ADN OPEN
  • **
  • Сообщений: 82
  • Карма: 1
Re: Доступ к Revit из внешнего приложения
« Ответ #24 : 04-05-2018, 08:54:27 »
БОЛЬШОЕ СПАСИБО!!!!!
Оказывается все так просто.
А мне еще учится и учится....(((
еще раз спасибо.

Оффлайн Александр Игнатович

  • Administrator
  • *****
  • Сообщений: 1152
  • Карма: 338
  • Skype: alexandr.ignatovich.itc
Re: Доступ к Revit из внешнего приложения
« Ответ #25 : 04-05-2018, 09:14:53 »
Ну учиться надо всегда и везде)

А вообще, Autodesk эти летом обещает выложить Revit IO - движок Revit-а в облаке, по аналогии с тем, что уже давно есть для AutoCAD-а, это, вероятно, более подходящее решение для подобных задач