Сообщество программистов Autodesk в СНГ

ADN Club => AutoCAD .NET API => Тема начата: Андрей Бушман от 26-05-2016, 16:07:18

Название: Из-за чего acedSetEnv может не изменять значение переменной Acad?
Отправлено: Андрей Бушман от 26-05-2016, 16:07:18
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. }
Название: Re: Из-за чего acedSetEnv может не изменять значение переменной Acad?
Отправлено: Александр Ривилис от 26-05-2016, 16:13:54
Нет ли каких-то ограничений или запрета на вызов acedSetEnv в коде метода Initialize()?
Встречный вопрос. Тоже самое не в Initialize() работает?
Название: Re: Из-за чего acedSetEnv может не изменять значение переменной Acad?
Отправлено: Андрей Бушман от 26-05-2016, 16:15:46
Нет ли каких-то ограничений или запрета на вызов acedSetEnv в коде метода Initialize()?
Встречный вопрос. Тоже самое не в Initialize() работает?
Сейчас проверю, но проблема в том, что этот код должен выполняться при загрузке сборки.
Название: Re: Из-за чего acedSetEnv может не изменять значение переменной Acad?
Отправлено: Александр Ривилис от 26-05-2016, 16:21:07
Ну как минимум вместо:
Код - C# [Выбрать]
  1. int setEnvResult = acedSetEnv("Acad", sbPaths); // 5100 i.e. RTNORM
должно быть:
Код - C# [Выбрать]
  1. int setEnvResult = acedSetEnv("ACAD", sbPaths); // 5100 i.e. RTNORM
Название: Re: Из-за чего acedSetEnv может не изменять значение переменной Acad?
Отправлено: Андрей Бушман от 26-05-2016, 16:21:15
Засунул в отдельную команду (для проверки) - результат тот же.
Название: Re: Из-за чего acedSetEnv может не изменять значение переменной Acad?
Отправлено: Андрей Бушман от 26-05-2016, 16:25:41
Ну как минимум вместо:
мля... Да, так изменения происходят. Значит это баг API - если регистр символов важен, то возвращаться должно было RTERROR или что-то иное,  но не RTNORM, раз изменений не произошло. Я полагал, что возвращение RTNORM означает, что регистр не имеет значения.

Спасибо.
Название: Re: Из-за чего acedSetEnv может не изменять значение переменной Acad?
Отправлено: Александр Ривилис от 26-05-2016, 16:31:20
Ну как минимум вместо:
мля... Да, так изменения происходят. Значит это баг API - если регистр символов важен, то возвращаться должно было RTERROR или что-то иное,  но не RTNORM, раз изменений не произошло. Я полагал, что возвращение RTNORM означает, что регистр не имеет значения.

Спасибо.
Неа. Ты снова попался. Поищи по реестру. Кудато вписалась переменная "Acad", но не туда куда ты ожидал...
Название: Re: Из-за чего acedSetEnv может не изменять значение переменной Acad?
Отправлено: Андрей Бушман от 26-05-2016, 16:35:32
Неа. Ты снова попался. Поищи по реестру. Кудато вписалась переменная "Acad", но не туда куда ты ожидал...
Это как? Хотите сказать, что поменяв имя "ACAD" на "Acad" запись происходит в какую-то другую ветку реестра?

Название: Re: Из-за чего acedSetEnv может не изменять значение переменной Acad?
Отправлено: Александр Ривилис от 26-05-2016, 16:36:02
У меня это значение прописалось сюда:
HKEY_CURRENT_USER\Software\Autodesk\AutoCAD\RXX.X\ACAD-YYYY:ZZZ\FixedProfile\General
Название: Re: Из-за чего acedSetEnv может не изменять значение переменной Acad?
Отправлено: Александр Ривилис от 26-05-2016, 16:36:56
Это как? Хотите сказать, что поменяв имя "ACAD" на "Acad" запись происходит в какую-то другую ветку реестра?
Именно так. И именно так и должно быть - нестандартное имя пишется в другую ветку.
Название: Re: Из-за чего acedSetEnv может не изменять значение переменной Acad?
Отправлено: Андрей Бушман от 26-05-2016, 16:39:09
Именно так. И именно так и должно быть - нестандартное имя пишется в другую ветку.
Да, нашёл. Пишет в ветку: HKEY_CURRENT_USER\Software\Autodesk\AutoCAD\R17.2\ACAD-7001:409\FixedProfile\General. Для чего эта ветка? Как она используется AutoCAD-ом?
Название: Re: Из-за чего acedSetEnv может не изменять значение переменной Acad?
Отправлено: Александр Ривилис от 26-05-2016, 16:40:21
О! Век живи - век учись! :)
Название: Re: Из-за чего acedSetEnv может не изменять значение переменной Acad?
Отправлено: Александр Ривилис от 26-05-2016, 16:44:38
Для чего эта ветка? Как она используется AutoCAD-ом?
Она используется для сохранения информации не зависящей от профиля AutoCAD (т.е. общая для всех профилей). Туда и ты можешь писать свои значения, которые зависят от версии и локализации AutoCAD и конкретного пользователя Windows. Например я там храню линейный масштабный коэффициент для GeomProps (с именем GeomPropsScale).