Как запустить Editor.Command() с добавленной через .NET командой?

Автор Тема: Как запустить Editor.Command() с добавленной через .NET командой?  (Прочитано 2280 раз)

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

Тема содержит сообщение с Решением. Нажмите здесь чтобы посмотреть его.

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2098
  • Карма: 543
  • LISP/C#, AutoCAD/Civil 3D
  • Skype: zagor_dmtr
Пытаюсь использовать метод Editor.Command для запуска моей команды, которая определена в этой же DLL - метод постоянно выдает ошибку eInvalidInput. Единственный вариант, который мне пришел в голову - Editor.Command не работает с "неродными" командами. Так ли это?
Document.SendStringToExecute запускает ее без проблем, но мне нужно именно синхронное выполнение.
Кстати, Editor.CommandAsync отрабатывает команду, но затем выдает исключение:
                ************** Exception Text **************
System.NullReferenceException: Object reference not set to an instance of an object.
   at Autodesk.AutoCAD.EditorInput.Editor.CommandResult.Callback()
Код - C# [Выбрать]
  1. using Autodesk.AutoCAD.ApplicationServices;
  2. using Autodesk.AutoCAD.EditorInput;
  3. using Autodesk.AutoCAD.Runtime;
  4.  
  5. [assembly: ExtensionApplication(typeof(AcadTests.EditorCommandTest))]
  6.  
  7. namespace AcadTests
  8. {
  9.     public class EditorCommandTest : IExtensionApplication
  10.     {
  11.         [CommandMethod("TestCommand")]
  12.         public void Command()
  13.         {
  14.             Application.ShowAlertDialog("OK");
  15.         }
  16.  
  17.         public void Initialize()
  18.         {
  19.             Document adoc = Application.DocumentManager.MdiActiveDocument;
  20.             Editor ed = adoc.Editor;
  21.             try
  22.             {
  23.                // ed.Command("_.REGEN"); // Работает
  24.                ed.Command("_.TESTCOMMAND"); // eInvalidInput
  25.                // ed.CommandAsync("_.TESTCOMMAND"); // Работает, но затем сразу выдает исключение              
  26.             }
  27.             catch(System.Exception ex)
  28.             {
  29.                 Application.ShowAlertDialog(ex.Message);
  30.             }
  31.             //adoc.SendStringToExecute("_.TESTCOMMAND ", true, false, true); // Работает
  32.         }
  33.  
  34.         public void Terminate()
  35.         {
  36.            
  37.         }
  38.     }
  39. }
  40.  

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 10031
  • Карма: 1281
  • Рыцарь ObjectARX
  • Skype: rivilis
Единственный вариант, который мне пришел в голову - Editor.Command не работает с "неродными" командами. Так ли это?
Нет конечно. :) Просто команда у тебя еще не определена (AutoCAD о ней еще понятия не имеет), а ты её уже запускаешь... Ведь сначала выполняется метод Initialize, и только затем AutoCAD считывает все атрибуты CommandMethod, чтобы понять, какие команды у тебя определены в dll-файле.
Ну и кроме того в контексте Initialize вообще не следует использовать Editor.Command. Во-первых, у тебя может не быть открытых документов, во-вторых, Editor.Command можно запускать только из контекста документа.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 10031
  • Карма: 1281
  • Рыцарь ObjectARX
  • Skype: rivilis
Document.SendStringToExecute запускает ее без проблем, но мне нужно именно синхронное выполнение.
Зачем? И вообще в твоём контексте достаточно заменить:
Код - C# [Выбрать]
  1. ed.Command("_.TESTCOMMAND"); // eInvalidInput
на
Код - C# [Выбрать]
  1. Command();
Вот и будет тебе полная синхронность... :)
« Последнее редактирование: 19-09-2016, 01:22:12 от Александр Ривилис »
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2098
  • Карма: 543
  • LISP/C#, AutoCAD/Civil 3D
  • Skype: zagor_dmtr
Просто команда у тебя еще не определена (AutoCAD о ней еще понятия не имеет), а ты её уже запускаешь... Ведь сначала выполняется метод Initialize, и только затем AutoCAD считывает все атрибуты CommandMethod, чтобы понять, какие команды у тебя определены в dll-файле.
Но Document.SendStringToExecute ведь работает. Если команда была бы еще не определена в этот момент, в этом методе она бы тоже не запустилась.
Ну и кроме того в контексте Initialize вообще не следует использовать Editor.Command.
Я сделал пример с Initialize просто для демонстрации.
Во-первых, у тебя может не быть открытых документов.
Пример максимально простой, без дополнительных проверок. Конечно, подгружать DLL нужно только когда открыт какой-то документ, иначе будет исключение.
во-вторых, Editor.Command можно запускать только из контекста документа.
Не очень понимаю, что Вы имеете в виду в данном случае. Это же метод редактора документа, если есть редактор, значит есть и сам документ. Флага Session у команды нет, значит, она в принципе не в контексте документа запуститься не сможет. Но, опять же, повторюсь: SendStringToExecute работает. Может я чего-то не понимаю, конечно.
Ну а если так. Запускаю в событии Editor.EnteringQuiescentState. Абсолютно такое же поведение:
Извините, вам запрещён просмотр содержимого спойлеров.
Зачем?
У меня включены обработчики запуска-завершения команд. При выполнении моей команды, мне нужно, чтобы они не запускались. Поэтому, я решил их отключить, запустить мою команду, а потом снова включить. Но если через Document.SendStringToExecute запускать команду, то обратное включение обработчиков завершения команды происходит раньше, чем моя команда закончит свою работу и события отлавливаются. Я так понимаю, что это из-за асинхронности этого метода. Если же делать это синхронно, то, по идее, такого происходить не будет.
Да, конечно, можно определить, что запускается именно моя команда и не обрабатывать ее события. Но если есть такой замечательный метод, то хочется им воспользоваться.
Вообще, это уже второй случай, когда у меня не получается запустить свою команду через этот метод. Но в первый раз у меня не было времени и желания разбираться с этим и я просто пошел другим путем. Сейчас же мне захотелось понять: то ли я что-то не так делаю, то ли запуск своих команд через этот метод не работает. А все примеры, которые нашел в интернете, используют с ним только стандартные команды автокада.



Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 10031
  • Карма: 1281
  • Рыцарь ObjectARX
  • Skype: rivilis
Но Document.SendStringToExecute ведь работает. Если команда была бы еще не определена в этот момент, в этом методе она бы тоже не запустилась.
Нет. Она запускается позднее, когда AutoCAD уже знает о твоей команде. А до того он не анализирует строку запуска.

Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Отмечено как Решение Дмитрий Загорулькин 19-09-2016, 02:00:08

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 10031
  • Карма: 1281
  • Рыцарь ObjectARX
  • Skype: rivilis
Не очень понимаю, что Вы имеете в виду в данном случае. Это же метод редактора документа, если есть редактор, значит есть и сам документ

Если в двух словах, то Editor.Command можно использовать только из модальной команды или lisp-функции. Почитай в документации ObjectARX про контекст документа/контекст приложения и когда можно использовать функцию acedCommand/acedCmd
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2098
  • Карма: 543
  • LISP/C#, AutoCAD/Civil 3D
  • Skype: zagor_dmtr
Если в двух словах, то Editor.Command можно использовать только из модальной команды или lisp-функции.
Да, Вы, как всегда, правы. Работает из модальной команды:
Код - C# [Выбрать]
  1. using Autodesk.AutoCAD.ApplicationServices;
  2. using Autodesk.AutoCAD.EditorInput;
  3. using Autodesk.AutoCAD.Runtime;
  4.  
  5. namespace AcadTests
  6. {
  7.     public class EditorCommandTest
  8.     {
  9.         [CommandMethod("TestCommand", CommandFlags.Modal)]
  10.         public void Command()
  11.         {
  12.             Application.ShowAlertDialog("OK");
  13.         }
  14.  
  15.         [CommandMethod("RunTestCommand", CommandFlags.Modal)]
  16.         public void Command1()
  17.         {
  18.             Document adoc = Application.DocumentManager.MdiActiveDocument;
  19.             Editor ed = adoc.Editor;
  20.  
  21.             ed.Command("TestCommand");
  22.         }
  23.     }
  24. }
Ну теперь хоть понятно, в чем дело :). Спасибо!