Из-за чего acedSetEnv может не изменять значение переменной Acad?

Автор Тема: Из-за чего acedSetEnv может не изменять значение переменной Acad?  (Прочитано 9776 раз)

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

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

Оффлайн Андрей БушманАвтор темы

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
AutoCAD 2009 x64 SP3 Enu.

Функция acedSetEnv возвращает RTNORM, но по факту изменение переменной Acad не происходит (вызываю в коде метода Initialize()). В реестре изменений так же не произошло. См. комментарии в коде (строки 76-79). В чём может быть проблема? Нет ли каких-то ограничений или запрета на вызов acedSetEnv в коде метода Initialize()?

Код - C# [Выбрать]
  1. // Since AutoCAD 2011 the `CustomizationSection.RemovePartialMenu()`
  2. // method has other signature.
  3. // Also, the BUNDLE-package autoloader have appeared since AutoCAD 2012.
  4. static readonly System.Version acad_2011_version = new System.Version(
  5.     18, 1, 0, 0);
  6.  
  7. // Since AutoCAD 2013 the
  8. // 'SystemObjects.DynamicLinker.ProductKey' property
  9. // moved into the 'HostApplicationServices.Current.UserRegistryProductRootKey'.
  10. static readonly System.Version acad_2013_version = new System.Version(
  11.     19, 0, 0, 0);
  12.  
  13. ...
  14.  
  15. #if OLDER_THAN_AUTOCAD_2012
  16.         const string acedSetEnv_FileName = "acad.exe";
  17. #else
  18.         const string acedSetEnv_FileName = "accore.dll";
  19. #endif
  20.  
  21.         [System.Security.SuppressUnmanagedCodeSecurity]
  22.         [DllImport(acedSetEnv_FileName, CharSet = CharSet.Auto,
  23.             CallingConvention = CallingConvention.Cdecl)]
  24.         private static extern Int32 acedSetEnv(String envName, StringBuilder NewValue);
  25.  
  26. ...
  27.  
  28. // AutoCAD versions older than 2012 haven't BUNDLE-package
  29. // autoloader.
  30. if (cad.Version <= acad_2011_version) {
  31.         try {
  32.                 // Add the record into the 'Support File Search Path' if it is
  33.                 // not exist still.
  34.                 string cProfileName = cad.GetSystemVariable("cprofile") as string;
  35.  
  36.                 String productKey = string.Empty;
  37.                 if (cad.Version >= acad_2013_version) {
  38.                         productKey = (string) HostApplicationServices.Current.GetType().InvokeMember(
  39.                                 "UserRegistryProductRootKey",
  40.                                 BindingFlags.Public | BindingFlags.GetProperty |
  41.                                 BindingFlags.Instance, null, HostApplicationServices.Current, null);
  42.                 }
  43.                 else {
  44.                         productKey = (string)SystemObjects.DynamicLinker.GetType().InvokeMember(
  45.                                 "ProductKey",
  46.                                 BindingFlags.Public | BindingFlags.GetProperty |
  47.                                 BindingFlags.Instance, null, SystemObjects.DynamicLinker, null);
  48.                 }
  49.  
  50.                 String keyName = String.Format(@"{0}\Profiles\{1}\General",
  51.                         productKey, cProfileName);
  52.  
  53.                 RegistryKey regKey = Registry.CurrentUser.OpenSubKey(keyName, true);
  54.                 String regValue = regKey.GetValue("Acad", string.Empty) as string;
  55.  
  56.                 // It is true for .Net Framework new versions.
  57.                 if (regKey is IDisposable) {
  58.                         ((IDisposable)regKey).Dispose();
  59.                 }
  60.  
  61.                 regValue = regValue.Substring(0, regValue.Length - 1);
  62.                 List<string> paths = new List<string>(regValue.Split(';')
  63.                         .Where(n => n.Trim() != string.Empty)
  64.                         .Select(n => n.ToLower()));
  65.  
  66.                 string path = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(
  67.                         Assembly.GetExecutingAssembly().Location), @"..\..\..\")).ToLower();
  68.  
  69.                 string path2 = path.Substring(0, path.Length - 1); // without of the last '\' char.
  70.  
  71.                 if (!paths.Contains(path) && !paths.Contains(path2)) {
  72.                         StringBuilder sbPaths = new StringBuilder();
  73.                         foreach (string item in paths) {
  74.                                 sbPaths.AppendFormat("{0};", item);
  75.                         }
  76.                         sbPaths.Append(path2 + ";"); // I have tried with and without the ';' char...
  77.                         int setEnvResult = acedSetEnv("Acad", sbPaths); // 5100 i.e. RTNORM
  78.                         // TODO: The problem is here... The result is RTNORM but the
  79.                         // `Support File Search Path` and its registry value wasn't changed...
  80.                 }
  81.         }
  82.         catch (System.Exception ex) {
  83.                 doc.Editor.WriteMessage(ex.Message);
  84.         }
  85. }

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

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

Оффлайн Андрей БушманАвтор темы

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Нет ли каких-то ограничений или запрета на вызов acedSetEnv в коде метода Initialize()?
Встречный вопрос. Тоже самое не в Initialize() работает?
Сейчас проверю, но проблема в том, что этот код должен выполняться при загрузке сборки.

Отмечено как Решение Андрей Бушман 26-05-2016, 16:54:54

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Ну как минимум вместо:
Код - C# [Выбрать]
  1. int setEnvResult = acedSetEnv("Acad", sbPaths); // 5100 i.e. RTNORM
должно быть:
Код - C# [Выбрать]
  1. int setEnvResult = acedSetEnv("ACAD", sbPaths); // 5100 i.e. RTNORM
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Андрей БушманАвтор темы

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Засунул в отдельную команду (для проверки) - результат тот же.

Оффлайн Андрей БушманАвтор темы

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Ну как минимум вместо:
мля... Да, так изменения происходят. Значит это баг API - если регистр символов важен, то возвращаться должно было RTERROR или что-то иное,  но не RTNORM, раз изменений не произошло. Я полагал, что возвращение RTNORM означает, что регистр не имеет значения.

Спасибо.

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Ну как минимум вместо:
мля... Да, так изменения происходят. Значит это баг API - если регистр символов важен, то возвращаться должно было RTERROR или что-то иное,  но не RTNORM, раз изменений не произошло. Я полагал, что возвращение RTNORM означает, что регистр не имеет значения.

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

Оффлайн Андрей БушманАвтор темы

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Неа. Ты снова попался. Поищи по реестру. Кудато вписалась переменная "Acad", но не туда куда ты ожидал...
Это как? Хотите сказать, что поменяв имя "ACAD" на "Acad" запись происходит в какую-то другую ветку реестра?


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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
У меня это значение прописалось сюда:
HKEY_CURRENT_USER\Software\Autodesk\AutoCAD\RXX.X\ACAD-YYYY:ZZZ\FixedProfile\General
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

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

Оффлайн Андрей БушманАвтор темы

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Именно так. И именно так и должно быть - нестандартное имя пишется в другую ветку.
Да, нашёл. Пишет в ветку: HKEY_CURRENT_USER\Software\Autodesk\AutoCAD\R17.2\ACAD-7001:409\FixedProfile\General. Для чего эта ветка? Как она используется AutoCAD-ом?

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

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

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Для чего эта ветка? Как она используется AutoCAD-ом?
Она используется для сохранения информации не зависящей от профиля AutoCAD (т.е. общая для всех профилей). Туда и ты можешь писать свои значения, которые зависят от версии и локализации AutoCAD и конкретного пользователя Windows. Например я там храню линейный масштабный коэффициент для GeomProps (с именем GeomPropsScale).
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение