eFileError, когда вызов функции открытия чертежа идёт не из CommandMethod

Автор Тема: eFileError, когда вызов функции открытия чертежа идёт не из CommandMethod  (Прочитано 6740 раз)

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

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

Оффлайн LisАвтор темы

  • ADN OPEN
  • Сообщений: 27
  • Карма: 1
Здравствуйте.

Столкнулся со следующей проблемой -- у меня есть открытие чертежа, оно происходит так:
1. Открываем в плагине некую БД.
2. Появляется окно с пользовательским интерфейсом, где можно выбрать чертеж.
3.1. После выбора конкретного чертежа его можно скачать (и сохранить на компьютере в некоторой папке). В данном случае всё отрабатывает корректно. Вызывается некая команда с CommandMethod, из которой уже вызывается в дальнейшем метод открытия и сохранения чертежа.
Но после второго пункта может пойти и другой вариант развития событий:
3.2. Открываем историю чертежа -- тут появится ещё одно окошко, которое будет уже содержать историю изменения чертежа. Когда мы хотим скачать какую-либо из версий, то вылетает исключение eFileError (хотя сохранение пройдёт успешно, ошибку выдаёт именно открытие его в AutoCAD/Civil). Это всё происходит для одного и того же чертежа, так что проблема вряд ли в версии, в которой он сохранен. Но теперь же в цепочке методов, ведущих к открытию чертежа и его сохранению, не будет команды с CommandMethod. Появилось подозрение, что ошибка в этом (хоть это и не однозначно), однако "впихнуть" CommandMethod просто так не получится.

Что можете посоветовать в сложившейся ситуации?

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Что такое "функция открытия чертежа"?
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн LisАвтор темы

  • ADN OPEN
  • Сообщений: 27
  • Карма: 1
Что такое "функция открытия чертежа"?
Если правильно понимаю вопрос, то попробую подробнее объяснить ситуацию: этих функций даже две. Изначально стояла:
Application.DocumentManager.Open("fileName");
Она также выдавала ошибку, мол, контекст не существует. Предположили, что ошибки уйдут с помощью следующей функции:
Application.DocumentManager.AppContextOpenDocument("fileName");
Но нет, эта уже выдаёт eFileError.

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Application.DocumentManager.Open("fileName");
Как минимум этот код нужно выполнять из контекста приложения (т.е., если это команда, то с флагом Session). И если открыт модальный диалог, то его нужно закрыть - иначе не сработает. Ну и DocumentActivationEnabled = true;
Ну и убедись, что это файл закрыт (т.е. не открыт ни в одной из программ в Windows).
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн LisАвтор темы

  • ADN OPEN
  • Сообщений: 27
  • Карма: 1
Александр Ривилис, спасибо большое за советы! Я обязательно попробую их все и дам обратную связь.)

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Она также выдавала ошибку, мол, контекст не существует.
А ты случайно не пытаешься открыть чертеж из отдельного потока (Task)? Если да, то так делать нельзя - открывать нужно только из главного потока.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн LisАвтор темы

  • ADN OPEN
  • Сообщений: 27
  • Карма: 1
А ты случайно не пытаешься открыть чертеж из отдельного потока (Task)?
Если честно, то сейчас по памяти сказать не могу (доступа к репозиторию на домашнем ПК, увы, нет), но, по-моему, всё же не вызывается из отдельного потока (но проверю обязательно эту версию). Но тогда небольшой вопрос: если бы это вызывалось из отдельного потока и "ломалось", то разве и в первом случае не было бы тогда ошибки?

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
то разве и в первом случае не было бы тогда ошибки?
Извини, но я не понял разницу между первым и вторым.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн LisАвтор темы

  • ADN OPEN
  • Сообщений: 27
  • Карма: 1
разницу между первым и вторым
Хм. Я бы сказал, что разница именно в вызовах.

В первом случае идёт вызов function(), которая помечена CommandMethod (кстати говоря, с Session -- это точно помню). Из этой команды уже вызывается некий третий метод, который использует Application.DocumentManager.AppContextOpenDocument("fileName");
А во втором случае вызывается также function(), но в другом проекте и без помеченного CommandMethod (то бишь обычная функция). Эта функция вызывает абсолютно тот же третий метод, но вот там уже как раз ошибка, где происходит Application.DocumentManager.AppContextOpenDocument("fileName");

Пытался добавить CommandMethod для второй function(), но не получилось, так как он в упор не хотел видеть ссылки на подключенные библиотеки. То есть ссылки сами добавил, но он никакого Autodesk.* и знать не хочет. :)

Оффлайн Lemieux

  • ADN OPEN
  • ****
  • Сообщений: 384
  • Карма: 21
Здравствуйте.

Столкнулся со следующей проблемой -- у меня есть открытие чертежа, оно происходит так:
1. Открываем в плагине некую БД.
2. Появляется окно с пользовательским интерфейсом, где можно выбрать чертеж.
3.1. После выбора конкретного чертежа его можно скачать (и сохранить на компьютере в некоторой папке). В данном случае всё отрабатывает корректно. Вызывается некая команда с CommandMethod, из которой уже вызывается в дальнейшем метод открытия и сохранения чертежа.
Но после второго пункта может пойти и другой вариант развития событий:
3.2. Открываем историю чертежа -- тут появится ещё одно окошко, которое будет уже содержать историю изменения чертежа. Когда мы хотим скачать какую-либо из версий, то вылетает исключение eFileError (хотя сохранение пройдёт успешно, ошибку выдаёт именно открытие его в AutoCAD/Civil). Это всё происходит для одного и того же чертежа, так что проблема вряд ли в версии, в которой он сохранен. Но теперь же в цепочке методов, ведущих к открытию чертежа и его сохранению, не будет команды с CommandMethod. Появилось подозрение, что ошибка в этом (хоть это и не однозначно), однако "впихнуть" CommandMethod просто так не получится.

Что можете посоветовать в сложившейся ситуации?

Так что точно делается? Открытие или скачивание чертежа? Или сначала скачивание, а потом открытие? Что за истории чертежа, как реализованы? Используется MVVM паттерн?

Оффлайн LisАвтор темы

  • ADN OPEN
  • Сообщений: 27
  • Карма: 1
Так что точно делается?
Смотрите, насколько я разобрался в коде (а проект не мой), мы обращаемся к базе данных -- там лежат различные чертежи, некоторые из чертежей имеют несколько версий (та самая история, но как именно реализована не смогу подсказать, в эту сторону не копал). Мы скачиваем сначала из этой самой БД чертеж, сохраняем его в некотором месте на диске, а уже после открываем (путь, по которому мы открываем, корректный, проверял).
MVVM используется, да.

Оффлайн Lemieux

  • ADN OPEN
  • ****
  • Сообщений: 384
  • Карма: 21
MVVM используется, да.
99% из-за него вылетает эта ошибка.

Как вызывается окно? ShowModalDialog или ShowModelessDialog?

Вот моя тема, когда я столкнулся с данной проблемой https://adn-cis.org/forum/index.php?topic=10569.0

Оффлайн LisАвтор темы

  • ADN OPEN
  • Сообщений: 27
  • Карма: 1
Как вызывается окно? ShowModalDialog или ShowModelessDialog?
Пока не смогу ответить наверняка, но... Интересная мысль, я в эту сторону и не думал копать. Посмотрю завтра, как появится доступ к коду.

Оффлайн Lemieux

  • ADN OPEN
  • ****
  • Сообщений: 384
  • Карма: 21
Как вызывается окно? ShowModalDialog или ShowModelessDialog?
Пока не смогу ответить наверняка, но... Интересная мысль, я в эту сторону и не думал копать. Посмотрю завтра, как появится доступ к коду.
Скорей всего окно нужно будет вызывать через ShowModelessDialog или вызов/закрытие окна/работу команды делить на 2/3 части (в зависимости от того как регистрируется команда).

Оффлайн LisАвтор темы

  • ADN OPEN
  • Сообщений: 27
  • Карма: 1
Lemieux, прочитал топик с Вашей проблемой, весьма любопытно. Тоже попробую проверить открытие/закрытие, ибо тоже подозреваю в этом некоторую проблему, ибо в первом UI окне всё нормально отрабатывает же, а когда в нём открываем историю (появляется второе уже окно) и скачиваем, то тут уже ошибки.

А вот про делить 2/3 части не совсем понял.

Оффлайн Lemieux

  • ADN OPEN
  • ****
  • Сообщений: 384
  • Карма: 21
А вот про делить 2/3 части не совсем понял.
У меня команда в САПРе регистрируется через Utils.AddCommand();
И получается:
1. Регистрирую команду в Initialize
2. Вызываю командой метод, который вызывает класс с основной логикой команды, в котором и вызывается окно. Создаётся основная ViewModel и передаётся в конструктор окна, вызывается окно и блокируется работа класса из которого вызвалось окно.
3. После завершения работы с окном оно закрывается и управление возвращается в класс из которого вызывалось окно, и проводится проверка на статус закрытия окна. Если всё норм, то работаем с данными из ViewModel.

Если ты регистрируешь команду через CommandMethod, то 1 и 2 шаги можно объединить. Всё это делается только тогда, когда добавляются/открываются новые документы в приложении. При работе с текущим документом можно вызывать окно в любом месте.
Как я понял, AutoCAD важно то, чтобы метод ShowModalDialog завершил работу, а не факт закрытия окна.

Оффлайн Алексей Кулик

  • Administrator
  • *****
  • Сообщений: 1097
  • Карма: 172
Цитата: Lis от 13-08-2022, 18:50:37

    MVVM используется, да.

99% из-за него вылетает эта ошибка.
Ух ты, а почему именно из-за MVVM?
Все, что сказано - личное мнение.

Правила форума существуют не просто так!

Приводя в сообщении код, не забывайте про его форматирование!

Оффлайн Lemieux

  • ADN OPEN
  • ****
  • Сообщений: 384
  • Карма: 21
Цитата: Lis от 13-08-2022, 18:50:37

    MVVM используется, да.

99% из-за него вылетает эта ошибка.
Ух ты, а почему именно из-за MVVM?

Точно не скажу. Я столкнулся с этой проблемой только тогда когда стал переписывать весь код на MVVM. То, что работало с codebehind, перестало работать с MVVM. Пришлось переделывать подход к работе с окнами и новыми файлами.

Оффлайн Алексей Кулик

  • Administrator
  • *****
  • Сообщений: 1097
  • Карма: 172
Цитата: Lis от 13-08-2022, 18:50:37

    MVVM используется, да.

99% из-за него вылетает эта ошибка.
Ух ты, а почему именно из-за MVVM?

Точно не скажу. Я столкнулся с этой проблемой только тогда когда стал переписывать весь код на MVVM. То, что работало с codebehind, перестало работать с MVVM. Пришлось переделывать подход к работе с окнами и новыми файлами.
Может, проблема не в паттерне, а в том, как именно был "переписан" код? Потому как у меня как минимум несколько проектов нормально работают в MVVM. Правда, без асинхронщины. Ну и интерфейсы с делегатами в полный рост используются.
Все, что сказано - личное мнение.

Правила форума существуют не просто так!

Приводя в сообщении код, не забывайте про его форматирование!

Оффлайн Lemieux

  • ADN OPEN
  • ****
  • Сообщений: 384
  • Карма: 21
Цитата: Lis от 13-08-2022, 18:50:37

    MVVM используется, да.

99% из-за него вылетает эта ошибка.
Ух ты, а почему именно из-за MVVM?

Точно не скажу. Я столкнулся с этой проблемой только тогда когда стал переписывать весь код на MVVM. То, что работало с codebehind, перестало работать с MVVM. Пришлось переделывать подход к работе с окнами и новыми файлами.
Может, проблема не в паттерне, а в том, как именно был "переписан" код? Потому как у меня как минимум несколько проектов нормально работают в MVVM. Правда, без асинхронщины. Ну и интерфейсы с делегатами в полный рост используются.
Новые документы добавляются в коллекцию документов, во время работы окна?
А при чём тут АМП и интерфейсы с делегатами? При использовании АМП будет вылетать совсем другая ошибка. И если мне память не изменяет, использование async/await в коде даже не запустить команду. А вот с помощью Parallel.Invoke() можно запустить несколько потоков из AutoCAD и других приложений (например Excel), при это поток AutoCAD должен запускаться первым.

Оффлайн LisАвтор темы

  • ADN OPEN
  • Сообщений: 27
  • Карма: 1
Пожалуй, могу дополнить немного информацию о происходящем. Насколько я могу судить, несмотря на некоторые асинхронные сортировки, всё выполняется в главном потоке, так как оба окна (с чертежами и историей для конкретного чертежа) открываются через Application.ShowModalWindow(window).

Однако, кажется, я обнаружил проблему -- так как у нас создаётся два модальных окна, то в первом случае, когда мы не обращаемся к истории, при попытке сохранить и открыть чертёж преждевременно закрывается модальное окно. А вот когда мы открываем историю и уже из неё выбираем какую-либо версию для той же операции, то закрывается только модальное окно истории, а вот первое модальное окно остаётся в том же состоянии, в котором и было.

Оффлайн Lemieux

  • ADN OPEN
  • ****
  • Сообщений: 384
  • Карма: 21
несмотря на некоторые асинхронные сортировки
Что за асинхронные сортировки?

открываются через Application.ShowModalWindow(window)
Попробуй заменить на ShowModelessWindow()

Оффлайн LisАвтор темы

  • ADN OPEN
  • Сообщений: 27
  • Карма: 1
Что за асинхронные сортировки?
Некто из других разработчиков сделал метод, где сортирует из бд записи по признаку (так как не все записи доступны могут быть пользователю).
Попробуй заменить на ShowModelessWindow()
А вот как раз попробовал, что интересно -- это даже принесло свои плоды, так как теперь из окошка истории действительно можно сохранять без проблем, однако вызывается первое окошко из команды и почему-то прогрузка завершается только после того, как команда полностью завершит своё выполнение. Это не очень хорошо, у ShowModalWindow такого не наблюдается.
Также замена опасна может быть тем, что ShowModalWindow возвращает нам bool?, а ShowModelessWindow() возвращает void. Вызов Show... стоит в return'е, поэтому, чтобы использовать ShowModelessWindow(), пришлось захардкодить по умолчанию true, а это прямо на неприятный такой костыль похоже.

Оффлайн Алексей Кулик

  • Administrator
  • *****
  • Сообщений: 1097
  • Карма: 172
Off-Topic: показать
В принципе можно, наверное, сделать публичное свойство bool? ShowResult, с приватным set'ом.
Все, что сказано - личное мнение.

Правила форума существуют не просто так!

Приводя в сообщении код, не забывайте про его форматирование!

Оффлайн Lemieux

  • ADN OPEN
  • ****
  • Сообщений: 384
  • Карма: 21
Вызов Show... стоит в return'е
Интересное решение.

Некто из других разработчиков сделал метод, где сортирует из бд записи по признаку
Что-то мне подсказывает, что код работает синхронно. Этот разработчик не тестировал работу плагина/модуля/команды?
Теперь ты понимаешь, что  придётся переписывать логику или лепить костыли?

В принципе можно, наверное, сделать публичное свойство bool? ShowResult, с приватным set'ом.
У меня своё кастомное окно так сделано, которое имитирует окно палитры, в котором уже хостятся UserControl.

Отмечено как Решение Lis 16-08-2022, 09:39:49

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
А вот когда мы открываем историю и уже из неё выбираем какую-либо версию для той же операции, то закрывается только модальное окно истории, а вот первое модальное окно остаётся в том же состоянии, в котором и было.
Вот об этом я и говорил. Открытое модальное окно препятствует переключению документов.
« Последнее редактирование: 15-08-2022, 16:15:18 от Александр Ривилис »
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн LisАвтор темы

  • ADN OPEN
  • Сообщений: 27
  • Карма: 1
Открытое модальное окно препятствует переключению документов.
Вы были правы. :)

К сожалению, пока из-за громоздкости кода проекта мне не удалось откопать, где именно происходит нажатие на кнопку "истории" (так как в единственном подходящем шаблоне этой кнопки нет вообще), а потому закрываю модальное окно очень топорно -- в одном из методов через window.Close(). Почитав скинутый выше топик, применил SendStringToExecute(), которая и правда принесла мне немного счастья, так как теперь это стало работать так, как ожидается -- чертежи корректно открываются в обоих случаях. Но теперь, правда, появилась парочка статических переменных, "таскающих" дескриптор окна и путь, по которому лежит чертёж, что, безусловно, не есть хорошо. Ещё буду думать в сторону оптимизации и избавлении от статических переменных, а также рыскать, откуда вообще появляется кнопка истории. Если получится, то обязательно дам знать в этой теме. Иначе придётся довольствоваться этим временно-постоянным решением.

Всем ещё раз спасибо большое за помощь, ваши советы мне помогли как с точки зрения понимания природы ошибки, так и с точки зрения её решения!

P.S. -- Хотелось дополнить, кстати, что для меня атрибут Session стал небольшим открытием -- не знал, что его наличие строго гарантирует открытие чертежа и взаимодействие с рабочей областью выбранного чертежа. Возможно, потомкам это будет полезно.

P.P.S. -- А вообще, чисто в теории, от статических переменных можно избавиться, если передавать некоторые параметры в команду через SendStringToExecute(), но пока такой реализации ещё не встречал.

UPD: https://forums.autodesk.com/t5/net/make-a-command-with-parameter/td-p/7172578 -- касательно передачи параметров (зачёркнуто, чтобы никто не ругался на формулировку) в SendStringToExecute(). Быть может, кому-то это пригодится из интересующихся.
« Последнее редактирование: 17-08-2022, 09:15:42 от Lis »