Задать каталог трубопроводной сети

Автор Тема: Задать каталог трубопроводной сети  (Прочитано 2254 раз)

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

Оффлайн ВильдарАвтор темы

  • ADN Club
  • ****
  • Сообщений: 310
  • Карма: 50
  • Skype: vildar82
Всем привет,
Есть ли какая-то возможность задать эти настройки программно:


Искал тут: civil.Settings.GetSettings<SettingsPipeNetwork>(), но не нашел.

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

  • ADN
  • *
  • Сообщений: 1903
  • Карма: 474
  • LISP/C#, AutoCAD/Civil 3D
  • Skype: zagor_dmtr
Насколько мне известно, в API нет такой возможности. Но можно попробовать поискать по реестру и файлам пользовательских профилей - возможно, что эта информация хранится где-то там.

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

  • ADN
  • *
  • Сообщений: 1903
  • Карма: 474
  • LISP/C#, AutoCAD/Civil 3D
  • Skype: zagor_dmtr
Вот похожая тема: http://adn-cis.org/forum/index.php?topic=879.0

Оффлайн ВильдарАвтор темы

  • ADN Club
  • ****
  • Сообщений: 310
  • Карма: 50
  • Skype: vildar82
Дмитрий Загорулькин спасибо, действительно в реестре нашлось:

Пока проверил, что записи читаются из реестра при каждом обращении и можно при запущенном автокаде менять значения.

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

  • ADN
  • *
  • Сообщений: 1903
  • Карма: 474
  • LISP/C#, AutoCAD/Civil 3D
  • Skype: zagor_dmtr
и можно при запущенном автокаде менять значения
Наверное можно. Но это не всегда корректно работает даже если использовать встроенные команды задать-обновить каталог. Проблемы возникают тогда, когда в каталог труб и колодцев добавлен пользовательский параметр. Если назначается такой каталог, то эти свойства Civil не подхватывает. Почему-то механизм подгрузки каталога устроен таким образом, что все пользовательские свойства считываются только один раз при загрузке Civil 3D. Однако, в API есть методы для этого (как я понимаю, сам ещё не пробовал их, т.к. считаю "горячую" смену каталога - очень проблемным сценарием работы):
NetworkCatalogDef.DeclareNewParameter
NetworkCatalogDef.DeclarePartProperty
Как я понимаю, надо прочитать соответствующие XML-файлы подгружаемого каталога и задекларировать найденные пользовательские свойства. Только как их отличить от стандартных? Или задекларировать все найденные, но будет ли это корректно работать? Надо всё проверять, тестировать. Но учитывая очень специфическое поведение трубопроводного каталога в Civil, пока что, я сторонник перезапуска Civil 3D при смене каталога...

Оффлайн ВильдарАвтор темы

  • ADN Club
  • ****
  • Сообщений: 310
  • Карма: 50
  • Skype: vildar82
Пока планирую записывать пути каталога из плагина автокада при старте, таким способом:
Код - C# [Выбрать]
  1.             var cp = Application.UserConfigurationManager.OpenCurrentProfile();
  2.             cp = cp.OpenSubsection(@"Preferences\AeccUiNetwork110");
  3.             // Запись
  4.             cp.WriteProperty("16C49365-B844-484b-92CE-9A8ACE681B57", Path.GetLocalSettingsFile(@"Pipes Catalog\Pipes Metric Russia"));
  5.             cp.WriteProperty("DCE203A2-D381-466f-A23E-08A9D9F8FDBD", Path.GetLocalSettingsFile(@"Pipes Catalog\Structures Metric Russia"));
  6.             cp.WriteProperty("F670B5B9-DA12-476d-B461-4FB5C5650A82", Path.GetLocalSettingsFile(@"Pipes Catalog\Pipes Metric Russia"));
  7.             cp.WriteProperty("F1FEBE2D-D589-4f85-BF8E-650ED06A5EA5", Path.GetLocalSettingsFile(@"Pipes Catalog\Structures Metric Russia"));
  8.             cp.WriteProperty("SharedContentPath", Path.GetLocalSettingsFile(@"Pipes Catalog\Aecc Shared Content"));

Вроде нормальный вариант.
Только смущает имя раздела реестра "AeccUiNetwork110". Как бы его точно определять? Я так понимаю от версии акада будет меняться число.

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

  • ADN
  • *
  • Сообщений: 1903
  • Карма: 474
  • LISP/C#, AutoCAD/Civil 3D
  • Skype: zagor_dmtr
Конечно, число меняется от версии к версии. Но То что до номера - неизменно. Поэтому, как вариант - поиск в Preferences ключа с названием, начинающимся на "AeccUiNetwork".
Я это делал так:
Код - C# [Выбрать]
  1. string productKeyName
  2.     = HostApplicationServices.Current.UserRegistryProductRootKey;
  3. string profileName
  4.     = Application.GetSystemVariable("CPROFILE").ToString();
  5.  
  6. RegistryKey genKey;
  7. try
  8. {
  9.     genKey = Registry.CurrentUser.OpenSubKey
  10.         (string.Format(@"{0}\Profiles\{1}\Preferences",
  11.         productKeyName, profileName), false);
  12. }
  13. catch (System.Exception ex)
  14. {
  15.     Debug.WriteLine(ex.Message);
  16.     Debug.WriteLine(ex.StackTrace);
  17.     genKey = null;
  18. }
  19.  
  20. RegistryKey netKey;
  21. using (genKey)
  22. {
  23.     try
  24.     {
  25.         string[] subNames = genKey?.GetSubKeyNames();
  26.         string netSubKeyName = subNames?.FirstOrDefault
  27.             (item => item.Contains("AeccUiNetwork"));
  28.         netKey = !string.IsNullOrEmpty(netSubKeyName) ?
  29.             genKey?.OpenSubKey(netSubKeyName, false) : null;
  30.     }
  31.     catch (System.Exception ex)
  32.     {
  33.         Debug.WriteLine(ex.Message);
  34.         Debug.WriteLine(ex.StackTrace);
  35.         netKey = null;
  36.     }
  37. }
  38.  
« Последнее редактирование: 04-07-2018, 17:12:37 от Дмитрий Загорулькин »

Оффлайн ВильдарАвтор темы

  • ADN Club
  • ****
  • Сообщений: 310
  • Карма: 50
  • Skype: vildar82
Да точно.
А гуиды параметров наверно неизменны.

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

  • ADN
  • *
  • Сообщений: 1903
  • Карма: 474
  • LISP/C#, AutoCAD/Civil 3D
  • Skype: zagor_dmtr
А гуиды параметров наверно неизменны.
Вот этого не знаю, надо проверять.

Оффлайн Andant

  • ADN Club
  • **
  • Сообщений: 72
  • Карма: 22
Нашел решение для напорных сетей.
Internal класс Autodesk.Civil.DatabaseServices.Styles.PressurePartCatalog  имеет статический метод SetCatalog, который может быть вызван при помощи рефлексии.
Для безнапорных сетей аналога не нашел.

Оффлайн ВильдарАвтор темы

  • ADN Club
  • ****
  • Сообщений: 310
  • Карма: 50
  • Skype: vildar82
Re: Задать каталог трубопроводной сети
« Ответ #10 : 11-07-2018, 17:06:57 »
Andant, а этот класс в какой сборке?

Оффлайн Andant

  • ADN Club
  • **
  • Сообщений: 72
  • Карма: 22
Re: Задать каталог трубопроводной сети
« Ответ #11 : 11-07-2018, 17:09:14 »
AeccPressurePipesMgd.dll

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

  • ADN
  • *
  • Сообщений: 1903
  • Карма: 474
  • LISP/C#, AutoCAD/Civil 3D
  • Skype: zagor_dmtr
Re: Задать каталог трубопроводной сети
« Ответ #12 : 24-01-2019, 18:54:46 »
Да точно.
А гуиды параметров наверно неизменны.
Не совсем так.
В каталоге у каждого файла с расширением .apc внутри есть GUID. Когда мы задаём каталог для труб - мы, по сути, указываем путь к конкретному файлу .apc. Civil читает файл, получает из него GUID и записывает в реестр значение: GUID - путь к файлу .apc.
Т.к. практически все правят имеющиеся в каталоге файлы, то GUID-ы у всех одни и те же.
Теперь у меня появился вопрос - а как же тогда Civil определяет какой из этих файлов подключен в данный момент?

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

  • ADN
  • *
  • Сообщений: 1903
  • Карма: 474
  • LISP/C#, AutoCAD/Civil 3D
  • Skype: zagor_dmtr
Re: Задать каталог трубопроводной сети
« Ответ #13 : 25-01-2019, 13:57:09 »
Итак, по порядку.
Для подключения каталога труб и колодцев требуется задать:
Папку каталога (1)
Каталог, из которого будут браться настройки для труб (2)
Каталог, из которого будут браться настройки для колодцев (3)

Когда изменяется папка каталога, Civil сканирует указанную папку по следующему принципу:
Ищутся все папки в указанном расположении.
В каждой папке ищется файл .apc с именем, соответствующем имени папки.
Если файл .apc обнаружен - из него читается название каталога и раздел, к которому он относится (труба или колодец).
Из полученных из файлов .apc данных формируются списки имён, которые будут доступны для выбора каталога труб (2) и каталога колодцев (3).
Когда изменяются эти настройки, Civil 3D записывает данные в реестр в раздел: HKEY_CURRENT_USER\Software\Autodesk\AutoCAD\RXX.X\ACAD-X000:XXX\Profiles\<<ИМЯ_ПРОФИЛЯ>>\Preferences\AeccUiNetworkXXX
Где вместо X - числа, зависящие от версии Civil 3D.
Изменяются три ключа:
1. SharedContentPath - в него записывается путь к папке "Aecc Shared Content" внутри папки каталога (1). Это определяет, какая папка каталога подключена в данный момент для всего приложения Civil 3D этой версии для текущего пользователя Windows и текущего профиля AutoCAD.
2. Ключ с именем в виде GUID формата XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX - в него записывается путь к файлу .apc, который определяет настройки каталога труб (2). Файл имеет XML структуру. Внутри этого файла .apc есть корневой элемент pXML с атрибутом id в формате GUID. Civil читает это значение и записывает как имя ключа.
3. То же самое, но для каталога колодцев.
Если ключи с такими именами уже существовали ранее, они перезаписываются. Если отсутствовали - создаются заново. То есть, в реестре просто хранятся данные о том, какие GUID каталогов использовались и где можно найти соответствующие им файлы. Это просто список, из которого однозначно нельзя определить, какой каталог труб или колодцев подключен в данный момент.
Далее - один неочевидный момент. Какой именно каталог труб и каталог колодцев подключен из заданной папки каталога - задаётся отдельно для каждого чертежа и сохраняется внутри него! Хранятся эти данные внутри недоступного для открытых API месте - в объекте AeccDbSettingsNode. Исследования показали, что, скорее всего, туда записывается GUID подключенных каталогов.
Итак, получается такая картина. Когда запускается Civil 3D сперва читается значение ключа SharedContentPath и определяется папка подключенного каталога. Затем, читаются все GUID-ключи. Когда открывается чертёж, из него получаются GUID'ы подключенных каталогов и определяется путь к ним по GUID-ключам. Есть ещё дополнительная проверка того, что назначенные чертежу каталоги находятся внутри папки подключенного в данный момент каталога.
Ну и напоследок. Civil 3D читает значение ключа SharedContentPath каждый раз при запуске инструментов, использующих каталог. Но изменение этого ключа при уже запущенном Civil 3D не даёт никакого эффекта. Пожалуй, единственное, на что это может повлиять - при запуске команды назначения каталога там будет указан путь, прописанный в данный момент в реестре. Ключи-GUID'ы читаются только при запуске Civil, так что, их изменение во время работы Civil не даст вообще ничего. Изменения "подхватятся" только после повторного запуска приложения.

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

  • ADN
  • *
  • Сообщений: 1903
  • Карма: 474
  • LISP/C#, AutoCAD/Civil 3D
  • Skype: zagor_dmtr
Re: Задать каталог трубопроводной сети
« Ответ #14 : 25-01-2019, 17:57:49 »
Интересно, а вот чисто теоретически, можно ли как-то использовать из .NET кода эти методы? (окопал помощью IL_Spy в AeccDbMgd):
Код - C# [Выбрать]
  1. internal unsafe static AecRmCString* AeccPartCatalogId.getPipesCatalogId(AeccPartCatalogId* P_0, AecRmCString* P_1)
  2. {
  3.         //IL_000c: Expected I, but got I8
  4.         uint num = 0u;
  5.         AecRmCString.{ctor}(P_1, (AecRmCString*)((long)(IntPtr)P_0 + 8));
  6.         try
  7.         {
  8.                 num = 1u;
  9.                 return P_1;
  10.         }
  11.         catch
  12.         {
  13.                 //try-fault
  14.                 if ((num & 1) != 0)
  15.                 {
  16.                         num = (uint)((int)num & -2);
  17.                         ___CxxCallUnwindDtor((IntPtr)(void*)/*OpCode not supported: LdFtn*/, P_1);
  18.                 }
  19.                 throw;
  20.         }
  21. }
Код - C# [Выбрать]
  1. internal unsafe static AecRmCString* AeccPartCatalogId.getStructureCatalogId(AeccPartCatalogId* P_0, AecRmCString* P_1)
  2. {
  3.         uint num = 0u;
  4.         AecRmCString.{ctor}(P_1, (AecRmCString*)P_0);
  5.         try
  6.         {
  7.                 num = 1u;
  8.                 return P_1;
  9.         }
  10.         catch
  11.         {
  12.                 //try-fault
  13.                 if ((num & 1) != 0)
  14.                 {
  15.                         num = (uint)((int)num & -2);
  16.                         ___CxxCallUnwindDtor((IntPtr)(void*)/*OpCode not supported: LdFtn*/, P_1);
  17.                 }
  18.                 throw;
  19.         }
  20. }