Document.Editor.Command(...) и т.п. = eInvalidInput на AutoCAD 2016

Автор Тема: Document.Editor.Command(...) и т.п. = eInvalidInput на AutoCAD 2016  (Прочитано 15470 раз)

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

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

  • ADN OPEN
  • Сообщений: 20
  • Карма: 0
А acedCmdS вместо acedCmd в 2016?
Ээээ... уже запутался... кажется это кончилось тем, что я не нашёл её определение, чтобы его DllImport... Хотя нет, вот же в документации ARX... сейчас попробую (возможно ещё раз)

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

  • ADN OPEN
  • Сообщений: 20
  • Карма: 0
Сделал так:
Код - C# [Выбрать]
  1.         [System.Security.SuppressUnmanagedCodeSecurity]
  2.         [DllImport(@"accore.dll", CallingConvention = CallingConvention.Cdecl)]
  3.         extern static int acedCmdS(IntPtr resbuf, bool stub1, IntPtr stub2);
...
Код - C# [Выбрать]
  1.         ResultBuffer rb = new ResultBuffer();
  2.         rb.Add(new TypedValue(5005, "_ATTSYNC"));
  3.         rb.Add(new TypedValue(5005, "_N"));
  4.         rb.Add(new TypedValue(5005, n));
  5.         int stat = acedCmdS(rb.UnmanagedObject, false, IntPtr.Zero);
  6.  
  7.         log("stat=" + stat.ToString() + "\r\n");
До последней строки (где log()) не доходит, исключений нет, тишина просто

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

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

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

  • ADN OPEN
  • Сообщений: 20
  • Карма: 0
Извиняюсь. У меня паника уже... acedCmdS выполняется, всё отлично.
Счастье то какое!
Ещё перепроверю пару десятков раз...

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
До последней строки (где log()) не доходит, исключений нет, тишина просто

Тут я не понял. Если не доходит, то может ждёт чего-то от пользователя. Установи CMDECHO в 1 чтобы в командной строке что-нибудь печаталось.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • Сообщений: 20
  • Карма: 0
Тут я не понял. Если не доходит, то может ждёт чего-то от пользователя. Установи CMDECHO в 1 чтобы в командной строке что-нибудь печаталось.
Всё доходит. Я просто новый файлик с исходником из студии не закинул туда где AutoCAD ждёт...
Прошу прощения

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Подозреваю, что
Код - C# [Выбрать]
  1. extern static int acedCmdS(IntPtr resbuf, bool stub1, IntPtr stub2);
стоит заменить на
Код - C# [Выбрать]
  1. extern static int acedCmdS(IntPtr resbuf, [MarshalAs(UnmanagedType.U1)] bool stub1, IntPtr stub2);
(читать здесь: https://msdn.microsoft.com/en-us/library/ms182206.aspx)
Причина в разнице типов bool в C++ и C#. Впрочем, так как передаётся false (т.е. 0), то возможно разницы и не будет.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Отмечено как Решение Александр Ривилис 23-01-2016, 15:17:20

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

  • ADN OPEN
  • Сообщений: 20
  • Карма: 0
Спасибо за оперативную помощь. Всё теперь работает, проверил и в 2014м и в 2016м.
В итоге получилось вот что:
Код - C# [Выбрать]
  1. #if R17_2 || R18_0 || R18_1 || R18_2
  2.         [System.Security.SuppressUnmanagedCodeSecurity]
  3.         [DllImport(@"acad.exe", CallingConvention = CallingConvention.Cdecl)]
  4.         extern static int acedCmd(IntPtr resbuf);
  5. #elif R19_0 || R19_1
  6.         [System.Security.SuppressUnmanagedCodeSecurity]
  7.         [DllImport(@"accore.dll", CallingConvention = CallingConvention.Cdecl)]
  8.         extern static int acedCmd(IntPtr resbuf);
  9. #elif R20_0 || R20_1
  10.         [System.Security.SuppressUnmanagedCodeSecurity]
  11.         [DllImport(@"accore.dll", CallingConvention = CallingConvention.Cdecl)]
  12.         extern static int acedCmdS(IntPtr resbuf, bool stub1, IntPtr stub2);
  13.         static int acedCmd(IntPtr resbuf)
  14.         {
  15.             return acedCmdS(resbuf, false, IntPtr.Zero);
  16.         }
  17. #endif
  18.  
  19. //...
  20. acedCmd(rb.UnmanagedObject);
  21.  

P.S. По поводу новой версии кода. Да, вы правы, когда речь идёт о том, что мы загружаем (Assembly.Load...) новую версию уже загруженной сборки, если она была где-то скомпилирована. Если же она скомпилирована прямо тут (динамически через CodeProvider), она сразу грузится в AppDomain и изменения вступают в силу.
P.P.S. Не факт, что размер bool == 1 (ибо определяется реализацией), у MS, да == 1. Ну и + там всегда false. Честно говоря, я думал компилятор сам разберётся.

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Я бы вместо условной компиляции написал бы P/Invoke трех функций и вызвал бы нужную в зависимости от версии AutoCAD (Application.Version). Но это на любителя... Что касается замены кода, то акцентирую внимание на то, что ты принудительно подменяешь код, который был ранее. Если в коде были обработчики событий, то (так как ты их не отключаешь), они будут ссылаться на старые, заменённые тобой функции. А это значит, что крах неизбежен. Так что будь очень осторожен.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
P.P.S. Не факт, что размер bool == 1 (ибо определяется реализацией), у MS, да == 1. Ну и + там всегда false. Честно говоря, я думал компилятор сам разберётся.
Как раз нет. Почитай тему: http://adn-cis.org/forum/index.php?topic=1719.0 Там как раз ошибка вылезла именно из-за того, что использовался (по-умолчанию) UnmanagedType.Bool вместо UnmanagedType.I1.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Дима_

  • ADN Club
  • ****
  • Сообщений: 473
  • Карма: 66
Я бы вместо условной компиляции написал бы P/Invoke трех функций и вызвал бы нужную в зависимости от версии AutoCAD (Application.Version). Но это на любителя...
Если не секрет - в чем причина предпочтений, если только не из желания загружать одну и ту же сборку в разные версии.

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Если не секрет - в чем причина предпочтений, если только не из желания загружать одну и ту же сборку в разные версии.
Это представь себе сколько конфигураций (и соотвественно количество сборок) нужно иметь для:
Код - C# [Выбрать]
  1. #if R17_2 || R18_0 || R18_1 || R18_2
хотя в большинстве случаев в этом нет необходимости.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • Сообщений: 20
  • Карма: 0
Я бы вместо условной компиляции написал бы P/Invoke трех функций и вызвал бы нужную в зависимости от версии AutoCAD (Application.Version)
Хорошая идея! Я замучался уже делать сборки под разные версии начиная с 2009й и по 2016ю. Я до недавнего времени думал, что если импортированной функции нет по факту, то программа просто не запустится...
Ещё бы вот здесь как-то избежать условной компиляции:
Код - C# [Выбрать]
  1. #if R17_2 || R18_0 || R18_1 || R18_2
  2. using Autodesk.AutoCAD.ApplicationServices;
  3. using Autodesk.AutoCAD.EditorInput;
  4.  
  5. #elif R19_0 || R19_1 || R20_0 || R20_1
  6. extern alias AcCoreMgd;
  7. using AcCoreMgd.Autodesk.AutoCAD.ApplicationServices;
  8. using AcCoreMgd.Autodesk.AutoCAD.ApplicationServices.Core;
  9. using AcCoreMgd.Autodesk.AutoCAD.EditorInput;
  10.  
  11. #endif
Без этого компилятор ругается на Document, что он определён и в CoreMgd и в Mgd...

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

  • ADN OPEN
  • Сообщений: 20
  • Карма: 0
А это значит, что крах неизбежен
Изначальная идея была, чтобы можно было оперативно менять только то, что часто меняется (особенно вначале внедрения чего-то нового), т.к. просто подменить dll-ку теперь нельзя (как раньше FreeLibrary), нужно перезапускать AutoCAD (или ещё что-то). Возиться с AppDoamin + IPC тоже не хочется из-за этого почему-то.
На счёт событий проверю, мне интересно стало просто. Отпишусь потом.

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

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