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

ADN Club => AutoCAD .NET API => Тема начата: Андрей Бушман от 04-12-2013, 14:27:39

Название: Не удаётся создать Subsection (раздел в реестре) для настроек PaletteSet
Отправлено: Андрей Бушман от 04-12-2013, 14:27:39
Доброго времени суток.

- AutoCAD 2009 x86 SP3 Enu.

На событие PaletteSet.Save вешаю такой код:
Код - C# [Выбрать]
  1. void palette_set_Save(object sender, Win.PalettePersistEventArgs e) {
  2.         App.IConfigurationSection subsection_company = null;
  3.         App.IConfigurationSection subsection_product = null;
  4.  
  5.         GetSubsections(e.ConfigurationSection, out subsection_company, out subsection_product);
  6.  
  7.         if (palette_set != null) {
  8.                 if (subsection_company == null)
  9.                         subsection_company = e.ConfigurationSection.CreateSubsection(company_name);
  10.                
  11.                 Boolean is_read_only = subsection_company.IsReadOnly; // False
  12.  
  13.                 if (subsection_product == null)
  14.                         // COMException here!
  15.                         // Message: Error HRESULT E_FAIL has been returned from a call to a COM component.
  16.                         subsection_product = subsection_company.CreateSubsection(product_name);
  17.  
  18.                 subsection_company.WriteProperty("Copyright", "© Andrey Bushman, 2013");
  19.                 subsection_company.WriteProperty("Site", "http://sites.google.com/site/bushmansnetlaboratory/");
  20.  
  21.                 subsection_product.WriteProperty("Location X", palette_set.Location.X);
  22.                 subsection_product.WriteProperty("Location Y", palette_set.Location.Y);
  23.                 subsection_product.WriteProperty("Width", palette_set.Size.Width);
  24.                 subsection_product.WriteProperty("Height", palette_set.Size.Height);
  25.         }
  26. }
  27.  
  28. void GetSubsections(App.IConfigurationSection config_section,
  29.         out App.IConfigurationSection subsection_company,
  30.         out App.IConfigurationSection subsection_product) {
  31.  
  32.         subsection_company = null;
  33.         subsection_product = null;
  34.  
  35.         if (config_section == null)
  36.                 return;
  37.  
  38.         subsection_company = config_section.ContainsSubsection(company_name) ?
  39.                 config_section.OpenSubsection(company_name) : null;
  40.  
  41.         subsection_product = subsection_company != null && subsection_company.ContainsSubsection(product_name) ?
  42.                 subsection_product = subsection_company.OpenSubsection(product_name) : null;
  43. }

Однако получаю исключение, обозначенное в комментариях. Я пробовал создавать вложенную секцию (Subsection) и в коде, подключенном к PaletteSet.Load - там та же история.

Почему не удаётся создать вложенную секцию?

Спасибо.
Название: Re: Неудаётся создать Subsection (раздел в реестре) для настроек PaletteSet
Отправлено: Андрей Бушман от 04-12-2013, 16:08:36
Хм... Написал простой пример, где посредством IConfigurationSection вношу изменения в реестр двумя способами (второй - это аналог коду из первого сообщения). Как это ни странно, но сейчас оба способа работают...

Возникли некоторые непонятные моменты:

1. Я не понял, почему в этот раз не возникает ошибка, обозначенная в аналогичном коде, приведённом выше.
2. Брэйкпоинт в palette_set_Save никогда не срабатывает, а срабатывает лишь в palette_set_Load.
3. Несмотря на п.2, палитра каким-то чудом запоминает свою позицию. Поиск по реестру ничего не даёт (искал по "ААА", "Location X", а так же по указанному GUID). Куда AutoCAD сохраняет эту информацию?

Наверное у меня уже глаз замылился... :(

Код - C# [Выбрать]
  1. // © Andrey Bushman, 2013
  2. using System;
  3. using Microsoft.Win32;
  4.  
  5. using cad = Autodesk.AutoCAD.ApplicationServices.Application;
  6. using App = Autodesk.AutoCAD.ApplicationServices;
  7. using Db = Autodesk.AutoCAD.DatabaseServices;
  8. using Ed = Autodesk.AutoCAD.EditorInput;
  9. using Rtm = Autodesk.AutoCAD.Runtime;
  10. using Win = Autodesk.AutoCAD.Windows;
  11. using System.IO;
  12.  
  13. [assembly: Rtm.CommandClass(typeof(Bushman.CAD.Problems.Commands))]
  14. [assembly: Rtm.ExtensionApplication(typeof(Bushman.CAD.Problems.Commands))]
  15.  
  16. namespace Bushman.CAD.Problems {
  17.  
  18.         public class Commands : Rtm.IExtensionApplication {
  19.  
  20.                 internal static Win.PaletteSet palette_set = null;
  21.  
  22.                 [Rtm.CommandMethod("cmd_1", Rtm.CommandFlags.Modal)]
  23.                 public void Command_1() {
  24.                         Ed.Editor ed = cad.DocumentManager.MdiActiveDocument.Editor;
  25.                         App.IConfigurationSection cp = cad.UserConfigurationManager.OpenCurrentProfile();
  26.  
  27.                         const String name = "Bushman";
  28.                         const String name2 = "My Some Application";
  29.                         const String propName = "Property 1";
  30.                         App.IConfigurationSection section = cp.ContainsSubsection(name) ?
  31.                                 cp.OpenSubsection(name) : cp.CreateSubsection(name);
  32.  
  33.                         App.IConfigurationSection section2 = section.ContainsSubsection(name2) ?
  34.                                 section.OpenSubsection(name2) : section.CreateSubsection(name2);
  35.  
  36.                         section2.WriteProperty(propName, "Hello, World!");
  37.                         String cprofile = cad.GetSystemVariable("cprofile") as String;
  38.                         String path = Path.Combine(Db.HostApplicationServices.Current.RegistryProductRootKey, @"Profiles\" + cprofile);
  39.                         RegistryKey regKey = Registry.CurrentUser.OpenSubKey(path, false);
  40.                         RegistryKey regKey2 = regKey.OpenSubKey(name).OpenSubKey(name2);
  41.                         String value = regKey2.GetValue(propName, String.Empty) as String;
  42.                         ed.WriteMessage("Register: {0}\n", regKey2.Name);
  43.                         ed.WriteMessage("The register is successfully changed!\n");
  44.                 }
  45.  
  46.                 [Rtm.CommandMethod("cmd_2", Rtm.CommandFlags.Modal)]
  47.                 public void Command_2() {
  48.                         Ed.Editor ed = cad.DocumentManager.MdiActiveDocument.Editor;
  49.                         if (palette_set == null) {
  50.                                 palette_set = new Win.PaletteSet("My Palette", new Guid("{49DBC66F-21BE-4D9F-A5A9-BA750543042E}"));
  51.                                 palette_set.Load += new Win.PalettePersistEventHandler(palette_set_Load);
  52.                                 palette_set.Save += new Win.PalettePersistEventHandler(palette_set_Save);
  53.                         }
  54.                         palette_set.KeepFocus = true;
  55.                         palette_set.Visible = true;
  56.                 }
  57.  
  58.                 void palette_set_Load(object sender, Win.PalettePersistEventArgs e) {
  59.                         App.IConfigurationSection section = e.ConfigurationSection;
  60.                         App.IConfigurationSection subsection = null;
  61.                         App.IConfigurationSection subsection2 = null;
  62.                         const String name = "AAA";
  63.                         const String name2 = "BBB";
  64.                         if (!section.IsReadOnly) {
  65.                                 subsection = section.ContainsSubsection(name) ?
  66.                                 section.OpenSubsection(name) : section.CreateSubsection(name);
  67.  
  68.                                 if (!subsection.IsReadOnly) {
  69.                                         subsection2 = subsection.ContainsSubsection(name2) ?
  70.                                         subsection.OpenSubsection(name2) : subsection.CreateSubsection(name2);
  71.                                 }
  72.                                 Int32 x = (Int32)subsection2.ReadProperty("Location X", 300);
  73.                                 Int32 y = (Int32)subsection2.ReadProperty("Location Y", 200);
  74.                         }
  75.                 }
  76.  
  77.                 void palette_set_Save(object sender, Win.PalettePersistEventArgs e) {
  78.                         App.IConfigurationSection section = e.ConfigurationSection;
  79.                         App.IConfigurationSection subsection = null;
  80.                         App.IConfigurationSection subsection2 = null;
  81.                         const String name = "AAA";
  82.                         const String name2 = "BBB";
  83.                         if (!section.IsReadOnly) {
  84.                                 subsection = section.ContainsSubsection(name) ?
  85.                                 section.OpenSubsection(name) : section.CreateSubsection(name);
  86.  
  87.                                 if (!subsection.IsReadOnly) {
  88.                                         subsection2 = subsection.ContainsSubsection(name2) ?
  89.                                         subsection.OpenSubsection(name2) : subsection.CreateSubsection(name2);
  90.                                 }
  91.                                 subsection2.WriteProperty("Location X", palette_set.Location.X);
  92.                                 subsection2.WriteProperty("Location Y", palette_set.Location.Y);
  93.                         }
  94.                 }
  95.  
  96.  
  97.                 public void Initialize() {
  98.                         Ed.Editor ed = cad.DocumentManager.MdiActiveDocument.Editor;
  99.                         ed.WriteMessage("The 'Hello World' is loaded... \n");
  100.                 }
  101.  
  102.                 public void Terminate() {
  103.                         // throw new NotImplementedException();
  104.                 }
  105.         }
  106. }
Название: Re: Не удаётся создать Subsection (раздел в реестре) для настроек PaletteSet
Отправлено: Александр Ривилис от 05-12-2013, 03:13:33
3. Несмотря на п.2, палитра каким-то чудом запоминает свою позицию. Поиск по реестру ничего не даёт (искал по "ААА", "Location X", а так же по указанному GUID). Куда AutoCAD сохраняет эту информацию?
Может по имени палитры поищешь? Мне всегда казалось, что сохраняется эта информация сюда:
HKEY_CURRENT_USER\Software\Autodesk\AutoCAD\RXX.X\ACAD-YYYY:LLL\Profiles\<<Имя профиля>>\Dialogs
Название: Re: Не удаётся создать Subsection (раздел в реестре) для настроек PaletteSet
Отправлено: Андрей Бушман от 05-12-2013, 11:26:11
Может по имени палитры поищешь? Мне всегда казалось, что сохраняется эта информация сюда:
HKEY_CURRENT_USER\Software\Autodesk\AutoCAD\RXX.X\ACAD-YYYY:LLL\Profiles\<<Имя профиля>>\Dialogs
Нет, вы ошибаетесь. Как выяснилось, информация записывается в файл %AppData%\Autodesk\AutoCAD 2014\R19.1\enu\Support\Profiles\Unnamed Profile\Profile.aws Вместо Unnamed Profile подставляете имя своего профиля.
Записанная в указанном файле информация выглядит так:
Код - XML [Выбрать]
  1. <Tool CLSID="{49DBC66F-21BE-4D9F-A5A9-BA750543042E}">
  2.   <CAdUiDockControlBar Orientation="-1" AllowDocking="1">
  3.     <FloatInfo Left="342" Top="310" Width="300" Height="300"/>
  4.     <DockInfo Left="0" Top="792" Width="300" Height="798" MRUDockID="59420"/>
  5.   </CAdUiDockControlBar>
  6.   <CAdUiPaletteSet/>
  7.   <AAA>
  8.     <BBB/>
  9.   </AAA>
  10. </Tool>

Обратите внимание на то, что элементы AAA и BBB созданы за счёт выполнения метода palette_set_Load. Однако я регистрировал и метод palette_set_Save, который должен был при завершении работы AutoCAD дописывать туда два дополнительных элемента, но этого почему-то не происходит (зарегистрированный код не вызывается автокадом)...

Поскольку информация, связанная с палитрами записывается в XML фай, то сразу становится понятна причина сбоя... Я ведь изначально ожидал, что информация будет записываться в реестр и вложенному подразделу пытался задать имя "Sheet Set Viewer". В реестре такие имена допустимы, но не в XML - там в имени элемента не должно содержаться пробелов. Т.о. заменив имя подраздела на "Sheet_Set_Viewer", я тем самым устранил проблему. В XML это выглядит так:

Код - XML [Выбрать]
  1. <Tool CLSID="{E06974C1-B748-4D8A-B1CC-CB9AADA26B79}">
  2.   <CAdUiDockControlBar Orientation="-1" AllowDocking="1">
  3.     <FloatInfo Left="150" Top="200" Width="300" Height="300"/>
  4.     <DockInfo Left="0" Top="396" Width="300" Height="798" MRUDockID="59420"/>
  5.   </CAdUiDockControlBar>
  6.   <CAdUiPaletteSet/>
  7.   <Bushman>
  8.     <Sheet_Set_Viewer/>
  9.   </Bushman>
  10. </Tool>

Отсюда вывод: если не хотите, чтобы в один прекрасный момент ваш код, использующий IConfigurationSection перестал работать, когда компания Autodesk вдруг решит часть настроек перенести из реестра в XML, то имена своим пользовательским разделам, подразделам и параметрам следует на всякий случай назначать без пробелов. :)

Т.о. вопрос, обозначенный в первом сообщении темы закрыт. Однако меня по прежнему интересует, почему выполняется мой код, зарегистрированный на событие Load и не выполняется код, зарегистрированный на событие Save?

Показываю простой исходный код, демонстрирующий проблему:

Код - C# [Выбрать]
  1. // © Andrey Bushman, 2013
  2. using System;
  3. using Microsoft.Win32;
  4.  
  5. using cad = Autodesk.AutoCAD.ApplicationServices.Application;
  6. using App = Autodesk.AutoCAD.ApplicationServices;
  7. using Db = Autodesk.AutoCAD.DatabaseServices;
  8. using Ed = Autodesk.AutoCAD.EditorInput;
  9. using Rtm = Autodesk.AutoCAD.Runtime;
  10. using Win = Autodesk.AutoCAD.Windows;
  11. using System.IO;
  12.  
  13. [assembly: Rtm.CommandClass(typeof(Bushman.CAD.Problems.Commands))]
  14. [assembly: Rtm.ExtensionApplication(typeof(Bushman.CAD.Problems.Commands))]
  15.  
  16. namespace Bushman.CAD.Problems {
  17.  
  18.         public class Commands : Rtm.IExtensionApplication {
  19.  
  20.                 internal static Win.PaletteSet palette_set = null;
  21.  
  22.                 [Rtm.CommandMethod("cmd_1", Rtm.CommandFlags.Modal)]
  23.                 public void Command_1() {
  24.                         Ed.Editor ed = cad.DocumentManager.MdiActiveDocument.Editor;
  25.                         App.IConfigurationSection cp = cad.UserConfigurationManager.OpenCurrentProfile();
  26.  
  27.                         const String name = "Bushman";
  28.                         // This names can to contain the spaces
  29.                         const String name2 = "My Some Application";
  30.                         const String propName = "Property 1";
  31.                         // This settings will created in the registry (HKCU)
  32.                         App.IConfigurationSection section = cp.ContainsSubsection(name) ?
  33.                                 cp.OpenSubsection(name) : cp.CreateSubsection(name);
  34.  
  35.                         App.IConfigurationSection section2 = section.ContainsSubsection(name2) ?
  36.                                 section.OpenSubsection(name2) : section.CreateSubsection(name2);
  37.  
  38.                         section2.WriteProperty(propName, "Hello, World!");
  39.                         String cprofile = cad.GetSystemVariable("cprofile") as String;
  40.                         String path = Db.HostApplicationServices.Current.UserRegistryProductRootKey
  41.                                 + @"\Profiles\" + cprofile;
  42.  
  43.                         using (RegistryKey regKey = Registry.CurrentUser.OpenSubKey(path, false)) {
  44.                                 using (RegistryKey regKey2 = regKey.OpenSubKey(name).OpenSubKey(name2)) {
  45.                                         String value = regKey2.GetValue(propName, String.Empty) as String;
  46.                                         ed.WriteMessage("Register: {0}\n", regKey2.Name);
  47.                                         ed.WriteMessage("The register is successfully changed!\n");
  48.                                 }
  49.                         }
  50.                 }
  51.  
  52.                 [Rtm.CommandMethod("cmd_2", Rtm.CommandFlags.Modal)]
  53.                 public void Command_2() {
  54.                         Ed.Editor ed = cad.DocumentManager.MdiActiveDocument.Editor;
  55.                         if (palette_set == null) {
  56.                                 // This settings will be saved into the
  57.                                 // %AppData%\Autodesk\AutoCAD 2014\R19.1\enu\Support\Profiles\Unnamed Profile\Profile.aws
  58.                                 // if the current profile is <<Unnamed Profile>>.
  59.                                 palette_set = new Win.PaletteSet("My Palette",
  60.                                         new Guid("{49DBC66F-21BE-4D9F-A5A9-BA750543042E}"));
  61.                                 palette_set.Load += new Win.PalettePersistEventHandler(palette_set_Load);
  62.                                 palette_set.Save += new Win.PalettePersistEventHandler(palette_set_Save);
  63.                         }
  64.  
  65.                         palette_set.KeepFocus = true;
  66.                         palette_set.Visible = true;
  67.                 }
  68.  
  69.                 // This names can't to contain the spaces!
  70.                 const String name = "AAA";
  71.                 const String name2 = "BBB";
  72.                 const String val_1_name = "Value_1";
  73.                 const String val_2_name = "Value_2";
  74.  
  75.                 void palette_set_Load(object sender, Win.PalettePersistEventArgs e) {
  76.                         App.IConfigurationSection section = e.ConfigurationSection;
  77.                         App.IConfigurationSection subsection = null;
  78.                         App.IConfigurationSection subsection2 = null;
  79.  
  80.                         if (!section.IsReadOnly) {
  81.                                 subsection = section.ContainsSubsection(name) ?
  82.                                 section.OpenSubsection(name) : section.CreateSubsection(name);
  83.  
  84.                                 if (!subsection.IsReadOnly) {
  85.                                         subsection2 = subsection.ContainsSubsection(name2) ?
  86.                                         subsection.OpenSubsection(name2) : subsection.CreateSubsection(name2);
  87.                                 }
  88.                                 Int32 val_1 = (Int32)subsection2.ReadProperty(val_1_name, 100);
  89.                                 Int32 val_2 = (Int32)subsection2.ReadProperty(val_2_name, 200);
  90.                         }
  91.                 }
  92.  
  93.                 void palette_set_Save(object sender, Win.PalettePersistEventArgs e) {
  94.                         App.IConfigurationSection section = e.ConfigurationSection;
  95.                         App.IConfigurationSection subsection = null;
  96.                         App.IConfigurationSection subsection2 = null;
  97.                         if (!section.IsReadOnly) {
  98.                                 subsection = section.ContainsSubsection(name) ?
  99.                                 section.OpenSubsection(name) : section.CreateSubsection(name);
  100.  
  101.                                 if (!subsection.IsReadOnly) {
  102.                                         subsection2 = subsection.ContainsSubsection(name2) ?
  103.                                         subsection.OpenSubsection(name2) : subsection.CreateSubsection(name2);
  104.                                 }
  105.                                 subsection2.WriteProperty(val_1_name, 700);
  106.                                 subsection2.WriteProperty(val_2_name, 800);
  107.                         }
  108.                 }
  109.  
  110.  
  111.                 public void Initialize() {
  112.                         Ed.Editor ed = cad.DocumentManager.MdiActiveDocument.Editor;
  113.                         ed.WriteMessage("The 'Hello World' is loaded... \n");
  114.                 }
  115.  
  116.                 public void Terminate() {
  117.                         // throw new NotImplementedException();
  118.                 }
  119.         }
  120. }

На всякий случай прикрепляю исходники, настроенные на AutoCAD 2014 x64.

Спасибо.
Название: Re: Не удаётся создать Subsection (раздел в реестре) для настроек PaletteSet
Отправлено: Андрей Бушман от 05-12-2013, 12:26:05
Я попробовал выполнить сохранение настроек, подписавшись на событие Application.BeginQuit, но это не помогло. В комментариях я показал точку сбоя и своё предположение о его причине...
Код - C# [Выбрать]
  1. // © Andrey Bushman, 2013
  2. using System;
  3. using Microsoft.Win32;
  4.  
  5. using cad = Autodesk.AutoCAD.ApplicationServices.Application;
  6. using App = Autodesk.AutoCAD.ApplicationServices;
  7. using Db = Autodesk.AutoCAD.DatabaseServices;
  8. using Ed = Autodesk.AutoCAD.EditorInput;
  9. using Rtm = Autodesk.AutoCAD.Runtime;
  10. using Win = Autodesk.AutoCAD.Windows;
  11. using System.IO;
  12.  
  13. [assembly: Rtm.CommandClass(typeof(Bushman.CAD.Problems.Commands))]
  14. [assembly: Rtm.ExtensionApplication(typeof(Bushman.CAD.Problems.Commands))]
  15.  
  16. namespace Bushman.CAD.Problems {
  17.  
  18.         public class Commands : Rtm.IExtensionApplication {
  19.  
  20.                 internal static Win.PaletteSet palette_set = null;
  21.  
  22.                 [Rtm.CommandMethod("cmd_1", Rtm.CommandFlags.Modal)]
  23.                 public void Command_1() {
  24.                         Ed.Editor ed = cad.DocumentManager.MdiActiveDocument.Editor;
  25.                         App.IConfigurationSection cp = cad.UserConfigurationManager.OpenCurrentProfile();
  26.  
  27.                         const String name = "Bushman";
  28.                         // This names can to contain the spaces
  29.                         const String name2 = "My Some Application";
  30.                         const String propName = "Property 1";
  31.                         // This settings will created in the registry (HKCU)
  32.                         App.IConfigurationSection section = cp.ContainsSubsection(name) ?
  33.                                 cp.OpenSubsection(name) : cp.CreateSubsection(name);
  34.  
  35.                         App.IConfigurationSection section2 = section.ContainsSubsection(name2) ?
  36.                                 section.OpenSubsection(name2) : section.CreateSubsection(name2);
  37.  
  38.                         section2.WriteProperty(propName, "Hello, World!");
  39.                         String cprofile = cad.GetSystemVariable("cprofile") as String;
  40.                         String path = Db.HostApplicationServices.Current.UserRegistryProductRootKey
  41.                                 + @"\Profiles\" + cprofile;
  42.  
  43.                         using (RegistryKey regKey = Registry.CurrentUser.OpenSubKey(path, false)) {
  44.                                 using (RegistryKey regKey2 = regKey.OpenSubKey(name).OpenSubKey(name2)) {
  45.                                         String value = regKey2.GetValue(propName, String.Empty) as String;
  46.                                         ed.WriteMessage("Register: {0}\n", regKey2.Name);
  47.                                         ed.WriteMessage("The register is successfully changed!\n");
  48.                                 }
  49.                         }
  50.                 }
  51.  
  52.                 [Rtm.CommandMethod("cmd_2", Rtm.CommandFlags.Modal)]
  53.                 public void Command_2() {
  54.                         Ed.Editor ed = cad.DocumentManager.MdiActiveDocument.Editor;
  55.                         if (palette_set == null) {
  56.                                 // This settings will be saved into the
  57.                                 // %AppData%\Autodesk\AutoCAD 2014\R19.1\enu\Support\Profiles\Unnamed Profile\Profile.aws
  58.                                 // if the current profile is <<Unnamed Profile>>.
  59.                                 palette_set = new Win.PaletteSet("My Palette",
  60.                                         new Guid("{49DBC66F-21BE-4D9F-A5A9-BA750543042E}"));
  61.                                 palette_set.Load += new Win.PalettePersistEventHandler(palette_set_Load);
  62.                                 cad.BeginQuit += new EventHandler(cad_BeginQuit);
  63.                         }
  64.  
  65.                         palette_set.KeepFocus = true;
  66.                         palette_set.Visible = true;
  67.                 }
  68.  
  69.                 static App.IConfigurationSection _palette_set = null;
  70.  
  71.                 void cad_BeginQuit(object sender, EventArgs e) {
  72.                         palette_set_Save(null, _palette_set);
  73.                 }
  74.  
  75.                 // This names can't to contain the spaces!
  76.                 const String name = "AAA";
  77.                 const String name2 = "BBB";
  78.                 const String val_1_name = "Value_1";
  79.                 const String val_2_name = "Value_2";
  80.  
  81.                 void palette_set_Load(object sender, Win.PalettePersistEventArgs e) {
  82.                         App.IConfigurationSection section = _palette_set = e.ConfigurationSection;
  83.                         App.IConfigurationSection subsection = null;
  84.                         App.IConfigurationSection subsection2 = null;
  85.  
  86.                         if (!section.IsReadOnly) {
  87.                                 subsection = section.ContainsSubsection(name) ?
  88.                                 section.OpenSubsection(name) : section.CreateSubsection(name);
  89.  
  90.                                 if (!subsection.IsReadOnly) {
  91.                                         subsection2 = subsection.ContainsSubsection(name2) ?
  92.                                         subsection.OpenSubsection(name2) : subsection.CreateSubsection(name2);
  93.                                 }
  94.                                 Int32 val_1 = (Int32)subsection2.ReadProperty(val_1_name, 100);
  95.                                 Int32 val_2 = (Int32)subsection2.ReadProperty(val_2_name, 200);
  96.                         }
  97.                 }
  98.  
  99.                 void palette_set_Save(object sender, App.IConfigurationSection section) {
  100.                         App.IConfigurationSection subsection = null;
  101.                         App.IConfigurationSection subsection2 = null;
  102.                         if (section != null && !section.IsReadOnly) {
  103.                                 // TODO: Problem is here.
  104.                                 // Here execution of code interrupts... Maybe IConfigurationSection is disposed already...
  105.                                 subsection = section.ContainsSubsection(name) ?
  106.                                 section.OpenSubsection(name) : section.CreateSubsection(name);
  107.  
  108.                                 if (!subsection.IsReadOnly) {
  109.                                         subsection2 = subsection.ContainsSubsection(name2) ?
  110.                                         subsection.OpenSubsection(name2) : subsection.CreateSubsection(name2);
  111.                                 }
  112.                                 subsection2.WriteProperty(val_1_name, 700);
  113.                                 subsection2.WriteProperty(val_2_name, 800);
  114.                         }
  115.                 }
  116.  
  117.  
  118.                 public void Initialize() {
  119.                         Ed.Editor ed = cad.DocumentManager.MdiActiveDocument.Editor;
  120.                         ed.WriteMessage("The 'Hello World' is loaded... \n");
  121.                 }
  122.  
  123.                 public void Terminate() {
  124.                         // throw new NotImplementedException();
  125.                 }
  126.         }
  127. }
Название: Re: Не удаётся создать Subsection (раздел в реестре) для настроек PaletteSet
Отправлено: Александр Ривилис от 05-12-2013, 12:35:45
На последний вопрос ответ готов:
Использование ActiveX интерфейса AutoCAD при его завершении (http://adn-cis.org/ispolzovanie-activex-interfejsa-autocad-pri-ego-zavershenii.html)
Название: Re: Не удаётся создать Subsection (раздел в реестре) для настроек PaletteSet
Отправлено: Андрей Бушман от 05-12-2013, 12:44:07
На последний вопрос ответ готов:
Использование ActiveX интерфейса AutoCAD при его завершении
Ок, значит вопрос по Application.BeginQuit отпадает. Но остаётся тот, что мне наиболее интересен - почему Save не фурычит? Я предпочитаю использовать IConfigurationSection для того, чтобы там же хранить и настройки элементов управления, размещённых на вкладках моей палитры. Поэтому - что у нас не так с Save?
Название: Re: Не удаётся создать Subsection (раздел в реестре) для настроек PaletteSet
Отправлено: Александр Ривилис от 05-12-2013, 12:47:15
Советую подписаться на DocumentCollection.DocumentToBeDestroyed и сохранять информацию о палитре в нём.
Название: Re: Не удаётся создать Subsection (раздел в реестре) для настроек PaletteSet
Отправлено: Андрей Бушман от 05-12-2013, 12:50:23
Советую подписаться на DocumentCollection.DocumentToBeDestroyed и сохранять информацию о палитре в нём.
Это всё понятно, читал. Но во первых - не хотелось бы перезаписывать настройки каждый раз, как закрывается документ, а во вторых, что же у нас всё таки не так с Save? Я хочу разобраться.... Не стесняйтесь потревожить ADN, если это действительно баг или требуются дополнительные танцы, чтобы сие заработало... Мне требуется понимание того, что происходит. :)
Название: Re: Не удаётся создать Subsection (раздел в реестре) для настроек PaletteSet
Отправлено: Александр Ривилис от 05-12-2013, 12:52:03
Хорошо. Потревожу. Я правильно понял, что ты проверил в AutoCAD 2014 SP1 x64? И что событие Save не возникало вообще?
Название: Re: Не удаётся создать Subsection (раздел в реестре) для настроек PaletteSet
Отправлено: Андрей Бушман от 05-12-2013, 12:58:23
Хорошо. Потревожу. Я правильно понял, что ты проверил в AutoCAD 2014 SP1 x64? И что событие Save не возникало вообще?
Да, причём эту информацию я уже указывал и исходники (http://adn-cis.org/forum/index.php?action=dlattach;topic=379.0;attach=114) прикреплял.
Название: Re: Не удаётся создать Subsection (раздел в реестре) для настроек PaletteSet
Отправлено: Александр Ривилис от 05-12-2013, 13:38:28
Отправил в ADN DevHelp.
Название: Re: Не удаётся создать Subsection (раздел в реестре) для настроек PaletteSet
Отправлено: Андрей Бушман от 05-12-2013, 14:40:47
Советую подписаться на DocumentCollection.DocumentToBeDestroyed и сохранять информацию о палитре в нём.

Не помогает... Вот код с примером:

Код - C# [Выбрать]
  1. // © Andrey Bushman, 2013
  2. using System;
  3. using Microsoft.Win32;
  4. using System.IO;
  5.  
  6. using cad = Autodesk.AutoCAD.ApplicationServices.Application;
  7. using App = Autodesk.AutoCAD.ApplicationServices;
  8. using Db = Autodesk.AutoCAD.DatabaseServices;
  9. using Ed = Autodesk.AutoCAD.EditorInput;
  10. using Rtm = Autodesk.AutoCAD.Runtime;
  11. using Win = Autodesk.AutoCAD.Windows;
  12.  
  13. [assembly: Rtm.CommandClass(typeof(Bushman.CAD.Problems.Commands))]
  14. [assembly: Rtm.ExtensionApplication(typeof(Bushman.CAD.Problems.Commands))]
  15.  
  16. namespace Bushman.CAD.Problems {
  17.  
  18.         public class Commands : Rtm.IExtensionApplication {
  19.  
  20.                 internal static Win.PaletteSet palette_set = null;
  21.  
  22.                 [Rtm.CommandMethod("cmd_3", Rtm.CommandFlags.Modal)]
  23.                 public void Command_3() {
  24.                         Ed.Editor ed = cad.DocumentManager.MdiActiveDocument.Editor;
  25.                         if (palette_set == null) {
  26.                                 // This settings will be saved into the
  27.                                 // %AppData%\Autodesk\AutoCAD 2014\R19.1\enu\Support\Profiles\Unnamed Profile\Profile.aws
  28.                                 // if the current profile is <<Unnamed Profile>>.
  29.                                 palette_set = new Win.PaletteSet("My Palette",
  30.                                         new Guid("{49DBC66F-21BE-4D9F-A5A9-BA750543042E}"));
  31.                                 palette_set.Load += new Win.PalettePersistEventHandler(palette_set_Load);
  32.                                 cad.DocumentManager.DocumentToBeDestroyed += new App.DocumentCollectionEventHandler(
  33.                                         DocumentManager_DocumentToBeDestroyed);
  34.                         }
  35.  
  36.                         palette_set.KeepFocus = true;
  37.                         palette_set.Visible = true;
  38.                 }
  39.  
  40.                 void DocumentManager_DocumentToBeDestroyed(object sender, App.DocumentCollectionEventArgs e) {
  41.                         palette_set_Save(null, _palette_set);
  42.                 }
  43.  
  44.                 static App.IConfigurationSection _palette_set = null;
  45.  
  46.                 // This names can't to contain the spaces!
  47.                 const String name = "AAA";
  48.                 const String name2 = "BBB";
  49.                 const String val_1_name = "Value_1";
  50.                 const String val_2_name = "Value_2";
  51.  
  52.                 void palette_set_Load(object sender, Win.PalettePersistEventArgs e) {
  53.                         App.IConfigurationSection section = _palette_set = e.ConfigurationSection;
  54.                         App.IConfigurationSection subsection = null;
  55.                         App.IConfigurationSection subsection2 = null;
  56.  
  57.                         if (!section.IsReadOnly) {
  58.                                 subsection = section.ContainsSubsection(name) ?
  59.                                 section.OpenSubsection(name) : section.CreateSubsection(name);
  60.  
  61.                                 if (!subsection.IsReadOnly) {
  62.                                         subsection2 = subsection.ContainsSubsection(name2) ?
  63.                                         subsection.OpenSubsection(name2) : subsection.CreateSubsection(name2);
  64.                                 }
  65.                                 Int32 val_1 = (Int32)subsection2.ReadProperty(val_1_name, 100);
  66.                                 Int32 val_2 = (Int32)subsection2.ReadProperty(val_2_name, 200);
  67.                         }
  68.                 }
  69.  
  70.                 void palette_set_Save(object sender, App.IConfigurationSection section) {
  71.                         if (section == null || section.IsReadOnly)
  72.                                 return;
  73.                         App.IConfigurationSection subsection = null;
  74.                         App.IConfigurationSection subsection2 = null;
  75.  
  76.                         // TODO: The problem is here!!!
  77.                         // Here execution of code interrupts... Maybe IConfigurationSection is disposed already...
  78.                         subsection = section.ContainsSubsection(name) ?
  79.                         section.OpenSubsection(name) : section.CreateSubsection(name);
  80.  
  81.                         if (!subsection.IsReadOnly) {
  82.                                 subsection2 = subsection.ContainsSubsection(name2) ?
  83.                                 subsection.OpenSubsection(name2) : subsection.CreateSubsection(name2);
  84.                         }
  85.                         subsection2.WriteProperty(val_1_name, 700);
  86.                         subsection2.WriteProperty(val_2_name, 800);
  87.                 }
  88.  
  89.  
  90.                 public void Initialize() {
  91.                         Ed.Editor ed = cad.DocumentManager.MdiActiveDocument.Editor;
  92.                         ed.WriteMessage("The 'Hello World' is loaded... \n");
  93.                 }
  94.  
  95.                 public void Terminate() {
  96.                         // throw new NotImplementedException();
  97.                 }
  98.         }
  99. }

В комментариях я пометил строку кода, в которой возникают две ошибки (строка 76), одна за другой. Получаю два сообщения (смотрим скрины). Что в этот раз может быть не так?
Название: Re: Не удаётся создать Subsection (раздел в реестре) для настроек PaletteSet
Отправлено: Александр Ривилис от 05-12-2013, 15:03:09
Мне нравится исключение с сообщением "Операция завершена успешно." :)
Интересно, а если их обернуть в try/catch - работать будет нормально?
Название: Re: Не удаётся создать Subsection (раздел в реестре) для настроек PaletteSet
Отправлено: Андрей Бушман от 05-12-2013, 15:05:34
Мне нравится исключение с сообщением "Операция завершена успешно." :-)
А мне уж как-то давно не весело. И так изо всех сил внимательно смотрю под ноги, чтобы ботинки не запачкать в этом поле, но не помогает: куда не наступлю - везде "попадаю в цель"... Я один такой "везучий"? :(
Название: Re: Не удаётся создать Subsection (раздел в реестре) для настроек PaletteSet
Отправлено: Александр Ривилис от 05-12-2013, 15:08:54
Попробуй объявить класс как static.
Название: Re: Не удаётся создать Subsection (раздел в реестре) для настроек PaletteSet
Отправлено: Андрей Бушман от 05-12-2013, 15:11:28
Попробуй объявить класс как static.
я попробую, только что лежит в основе этого предположения? переменная, с которой я работаю в коде и так является статической. Неужто этого мало и требуется static class? В этом случае лесом пойдёт реализация интерфейса IExtensionApplication...
Название: Re: Не удаётся создать Subsection (раздел в реестре) для настроек PaletteSet
Отправлено: Александр Ривилис от 05-12-2013, 15:14:19
что лежит в основе этого предположения?
В основе этого предположения то, что для событий уровня DocumentCollection очень(!!!) желательны статические методы, т.к. в противном случае на каждый документ создаётся свой экземпляр класса и какой обработчик будет использоваться не ясно.
Название: Re: Не удаётся создать Subsection (раздел в реестре) для настроек PaletteSet
Отправлено: Андрей Бушман от 05-12-2013, 15:19:00
Мне нравится исключение с сообщением "Операция завершена успешно."
Однако в xml файле нужные изменения не появляются. Т.о. я не знаю, что в этом сообщении подразумевается под "успехом"...
Название: Re: Не удаётся создать Subsection (раздел в реестре) для настроек PaletteSet
Отправлено: Александр Ривилис от 05-12-2013, 15:20:23
Однако в xml файле нужные изменения не появляются.
1. try/catch поставил?
2. класс уже статический?
Название: Re: Не удаётся создать Subsection (раздел в реестре) для настроек PaletteSet
Отправлено: Андрей Бушман от 05-12-2013, 15:24:42
Попробуй объявить класс как static.
Без особой надежды попробовал. Те же самые сообщения об ошибках.
Название: Re: Не удаётся создать Subsection (раздел в реестре) для настроек PaletteSet
Отправлено: Александр Ривилис от 05-12-2013, 15:27:15
1. try/catch поставил?
И проверь subsection равно ли null после этого
Название: Re: Не удаётся создать Subsection (раздел в реестре) для настроек PaletteSet
Отправлено: Андрей Бушман от 05-12-2013, 15:33:13
1. try/catch поставил?
И проверь subsection равно ли null после этого
Проверял. subsection по прежнему равен null (после возникновения исключения). Вот код:
Код - C# [Выбрать]
  1. // © Andrey Bushman, 2013
  2. using System;
  3. using Microsoft.Win32;
  4. using System.IO;
  5.  
  6. using cad = Autodesk.AutoCAD.ApplicationServices.Application;
  7. using App = Autodesk.AutoCAD.ApplicationServices;
  8. using Db = Autodesk.AutoCAD.DatabaseServices;
  9. using Ed = Autodesk.AutoCAD.EditorInput;
  10. using Rtm = Autodesk.AutoCAD.Runtime;
  11. using Win = Autodesk.AutoCAD.Windows;
  12.  
  13. [assembly: Rtm.CommandClass(typeof(Bushman.CAD.Problems.Commands))]
  14.  
  15. namespace Bushman.CAD.Problems {
  16.  
  17.         public static class Commands {
  18.  
  19.                 internal static Win.PaletteSet palette_set = null;
  20.  
  21.                 [Rtm.CommandMethod("cmd_3", Rtm.CommandFlags.Modal)]
  22.                 public static void Command_3() {
  23.                         Ed.Editor ed = cad.DocumentManager.MdiActiveDocument.Editor;
  24.                         if (palette_set == null) {
  25.                                 // This settings will be saved into the
  26.                                 // %AppData%\Autodesk\AutoCAD 2014\R19.1\enu\Support\Profiles\Unnamed Profile\Profile.aws
  27.                                 // if the current profile is <<Unnamed Profile>>.
  28.                                 palette_set = new Win.PaletteSet("My Palette",
  29.                                         new Guid("{49DBC66F-21BE-4D9F-A5A9-BA750543042E}"));
  30.                                 palette_set.Load += new Win.PalettePersistEventHandler(palette_set_Load);
  31.                                 cad.DocumentManager.DocumentToBeDestroyed += new App.DocumentCollectionEventHandler(
  32.                                         DocumentManager_DocumentToBeDestroyed);
  33.                         }
  34.  
  35.                         palette_set.KeepFocus = true;
  36.                         palette_set.Visible = true;
  37.                 }
  38.  
  39.                 static void DocumentManager_DocumentToBeDestroyed(object sender, App.DocumentCollectionEventArgs e) {
  40.                         palette_set_Save(null, _palette_set);
  41.                 }
  42.  
  43.                 static App.IConfigurationSection _palette_set = null;
  44.  
  45.                 // This names can't to contain the spaces!
  46.                 const String name = "AAA";
  47.                 const String name2 = "BBB";
  48.                 const String val_1_name = "Value_1";
  49.                 const String val_2_name = "Value_2";
  50.  
  51.                 static void palette_set_Load(object sender, Win.PalettePersistEventArgs e) {
  52.                         App.IConfigurationSection section = _palette_set = e.ConfigurationSection;
  53.                         App.IConfigurationSection subsection = null;
  54.                         App.IConfigurationSection subsection2 = null;
  55.  
  56.                         if (!section.IsReadOnly) {
  57.                                 subsection = section.ContainsSubsection(name) ?
  58.                                 section.OpenSubsection(name) : section.CreateSubsection(name);
  59.  
  60.                                 if (!subsection.IsReadOnly) {
  61.                                         subsection2 = subsection.ContainsSubsection(name2) ?
  62.                                         subsection.OpenSubsection(name2) : subsection.CreateSubsection(name2);
  63.                                 }
  64.  
  65.                                 Int32 val_1 = (Int32)subsection2.ReadProperty(val_1_name, 100);
  66.                                 Int32 val_2 = (Int32)subsection2.ReadProperty(val_2_name, 200);
  67.                         }
  68.                 }
  69.  
  70.                 static void palette_set_Save(object sender, App.IConfigurationSection section) {
  71.                         if (section == null || section.IsReadOnly)
  72.                                 return;
  73.                         App.IConfigurationSection subsection = null;
  74.                         App.IConfigurationSection subsection2 = null;
  75.                         try {
  76.                                 // TODO: The problem is here!!!
  77.                                 // Here execution of code interrupts... Maybe IConfigurationSection is disposed already...
  78.                                 subsection = section.ContainsSubsection(name) ?
  79.                                 section.OpenSubsection(name) : section.CreateSubsection(name);
  80.                         }
  81.                         catch { } // Exception occured. The subsection is null.
  82.                         if (subsection != null && !subsection.IsReadOnly) {
  83.                                 subsection2 = subsection.ContainsSubsection(name2) ?
  84.                                 subsection.OpenSubsection(name2) : subsection.CreateSubsection(name2);
  85.                         }
  86.                         if (subsection2 != null && !subsection2.IsReadOnly) {
  87.                                 subsection2.WriteProperty(val_1_name, 700);
  88.                                 subsection2.WriteProperty(val_2_name, 800);
  89.                         }
  90.                 }
  91.         }
  92. }
Название: Re: Не удаётся создать Subsection (раздел в реестре) для настроек PaletteSet
Отправлено: Александр Ривилис от 05-12-2013, 15:44:59
Давай разделим код внутри try/catch чтобы было понятно на какой операции вылет, т.е. отдельно
Код - C# [Выбрать]
  1. bool b = section.ContainsSubsection(name);
отдельно
Код - C# [Выбрать]
  1. section.OpenSubsection(name);
отдельно
Код - C# [Выбрать]
  1. subsection.CreateSubsection(name2);
Название: Re: Не удаётся создать Subsection (раздел в реестре) для настроек PaletteSet
Отправлено: Андрей Бушман от 05-12-2013, 16:19:38
Сделал. Обнаружил странный результат... Сначала подправленный код:

Код - C# [Выбрать]
  1. // © Andrey Bushman, 2013
  2. // AutoCAD 2014 x64 SP1 Enu
  3. using System;
  4. using Microsoft.Win32;
  5.  
  6. using cad = Autodesk.AutoCAD.ApplicationServices.Application;
  7. using App = Autodesk.AutoCAD.ApplicationServices;
  8. using Db = Autodesk.AutoCAD.DatabaseServices;
  9. using Ed = Autodesk.AutoCAD.EditorInput;
  10. using Rtm = Autodesk.AutoCAD.Runtime;
  11. using Win = Autodesk.AutoCAD.Windows;
  12.  
  13. [assembly: Rtm.CommandClass(typeof(Bushman.CAD.Problems.Commands))]
  14.  
  15. namespace Bushman.CAD.Problems {
  16.  
  17.     public static class Commands {
  18.  
  19.         internal static Win.PaletteSet palette_set = null;
  20.  
  21.         [Rtm.CommandMethod("cmd_3", Rtm.CommandFlags.Modal)]
  22.         public static void Command_3() {
  23.             Ed.Editor ed = cad.DocumentManager.MdiActiveDocument.Editor;
  24.             if (palette_set == null) {
  25.                 // This settings will be saved into the
  26.                 // %AppData%\Autodesk\AutoCAD 2014\R19.1\enu\Support\Profiles\Unnamed Profile\Profile.aws
  27.                 // if the current profile is <<Unnamed Profile>>.
  28.                 palette_set = new Win.PaletteSet("My Palette",
  29.                         new Guid("{49DBC66F-21BE-4D9F-A5A9-BA750543042E}"));
  30.                 palette_set.Load += new Win.PalettePersistEventHandler(palette_set_Load);
  31.             }
  32.  
  33.             palette_set.KeepFocus = true;
  34.             palette_set.Visible = true;
  35.         }
  36.  
  37.         [Rtm.CommandMethod("cmd_4", Rtm.CommandFlags.Modal)]
  38.         public static void Command_4() {
  39.             palette_set_Save(section);
  40.         }
  41.  
  42.         static App.IConfigurationSection section = null;
  43.  
  44.         // This names can't to contain the spaces!
  45.         const String name = "AAA";
  46.         const String name2 = "BBB";
  47.         const String val_1_name = "Value_1";
  48.         const String val_2_name = "Value_2";
  49.  
  50.         static void palette_set_Load(object sender, Win.PalettePersistEventArgs e) {
  51.             section = e.ConfigurationSection;
  52.             App.IConfigurationSection subsection = null;
  53.             App.IConfigurationSection subsection2 = null;
  54.  
  55.             if (!section.IsReadOnly) {
  56.                 Boolean n = section.ContainsSubsection(name); // True
  57.                 if (n)
  58.                     subsection = section.OpenSubsection(name);
  59.                 else
  60.                     subsection = section.CreateSubsection(name);
  61.  
  62.                 if (!subsection.IsReadOnly) {
  63.                     Boolean b = subsection.ContainsSubsection(name2); // True
  64.                     if (b)
  65.                         subsection2 = subsection.OpenSubsection(name2);
  66.                     else
  67.                         subsection2 = subsection.CreateSubsection(name2);
  68.                 }
  69.  
  70.                 Int32 val_1 = (Int32)subsection2.ReadProperty(val_1_name, 100);
  71.                 Int32 val_2 = (Int32)subsection2.ReadProperty(val_2_name, 200);
  72.             }
  73.         }
  74.  
  75.         static void palette_set_Save(App.IConfigurationSection section) {
  76.             if (section == null || section.IsReadOnly)
  77.                 return;
  78.             App.IConfigurationSection subsection = null;
  79.             App.IConfigurationSection subsection2 = null;
  80.             try {
  81.                 Boolean b = section.ContainsSubsection(name); // False... Why???                                
  82.                 if (b)
  83.                     subsection = section.OpenSubsection(name);
  84.                 else
  85.                     subsection = section.CreateSubsection(name); // Exception is here
  86.             }
  87.             catch { } // Exception occured. The subsection is null.
  88.             if (subsection != null && !subsection.IsReadOnly) {
  89.                 Boolean n = subsection.ContainsSubsection(name2);
  90.                 if (n)
  91.                     subsection2 = subsection.OpenSubsection(name2);
  92.                 else
  93.                     subsection2 = subsection.CreateSubsection(name2);
  94.             }
  95.             if (subsection2 != null && !subsection2.IsReadOnly) {
  96.                 subsection2.WriteProperty(val_1_name, 700);
  97.                 subsection2.WriteProperty(val_2_name, 800);
  98.             }
  99.         }
  100.     }
  101. }

Операцию сохранения я даже вынес в отдельную команду cmd_4, дабы иметь возможность вызвать её самостоятельно.Обратите внимание на то, что все логические проверки, выполняемые в методе palette_set_Load, возвращают в качестве значения True, т.е. все подразделы обнаружены (они и в самом деле присутствуют в файле Profile.aws). Однако в коде метода palette_set_Save такая проверка возвращает False, хотя работа идёт с одним и тем же статическим объектом:

Код - C# [Выбрать]
  1. static App.IConfigurationSection section

Затем идёт попытка создания подраздела, в результате чего и генерируется исключение.

Вопрос: Почему логическая проверка в методе palette_set_Save возвращает False, а не True?

Я вот смотрю на эти строки кода:

Код - C# [Выбрать]
  1. static void palette_set_Load(object sender, Win.PalettePersistEventArgs e) {
  2.     section = e.ConfigurationSection;

Может быть по выходу из метода  palette_set_Load AutoCAD вызывает метод e.ConfigurationSection.Dispose(), в виду чего IConfigurationSection section становится некорректным и в то же время не равным null?


Спасибо.
Название: Re: Не удаётся создать Subsection (раздел в реестре) для настроек PaletteSet
Отправлено: Андрей Бушман от 06-12-2013, 10:30:34
Проблема решена. Даже правильней сказать так: экспериментальным образом я обнаружил мягко говоря странные вещи, влияющие на обработку событий в AutoCAD. Возможно это будет интересно ещё кому-то... Итак, на данный момент, на руках я имею следующие факты:

Ну а теперь, собственно, работающий код, в котором учтены все обозначенные мною выше пункты:

Код - C# [Выбрать]
  1. /* © Andrey Bushman, 2013
  2.  * AutoCAD 2014 x64 SP1
  3.  * The sample, how to save the some settings of your custom controls into the AWS file.
  4.  * I showed the feature of the "IConfigurationSection.Save" event's registration.
  5.  */
  6.  
  7. using System;
  8. using Microsoft.Win32;
  9.  
  10. using cad = Autodesk.AutoCAD.ApplicationServices.Application;
  11. using App = Autodesk.AutoCAD.ApplicationServices;
  12. using Db = Autodesk.AutoCAD.DatabaseServices;
  13. using Ed = Autodesk.AutoCAD.EditorInput;
  14. using Rtm = Autodesk.AutoCAD.Runtime;
  15. using Win = Autodesk.AutoCAD.Windows;
  16.  
  17. [assembly: Rtm.CommandClass(typeof(Bushman.CAD.Problems.Commands))]
  18.  
  19. namespace Bushman.CAD.Problems {
  20.  
  21.         public class Commands {
  22.  
  23.                 [Rtm.CommandMethod("cmd_4", Rtm.CommandFlags.Modal)]
  24.                 public void Command_4() {
  25.                         Ed.Editor ed = cad.DocumentManager.MdiActiveDocument.Editor;
  26.  
  27.                         // This settings will be saved into the
  28.                         // %AppData%\Autodesk\AutoCAD 2014\R19.1\enu\Support\Profiles\Unnamed Profile\Profile.aws
  29.                         // if the current profile is <<Unnamed Profile>>.
  30.                         Win.PaletteSet palette_set = new Win.PaletteSet("My Palette",
  31.                                 new Guid("{49DBC66F-21BE-4D9F-A5A9-BA750543042E}"));
  32.                         palette_set.Load += new Win.PalettePersistEventHandler(palette_set_Load);
  33.                         palette_set.Save += new Win.PalettePersistEventHandler(palette_set_Save);
  34.  
  35.                         // WARNING! If you will comment the next code line, the 'Save' event not occurs!
  36.                         // I think it is a bug of API.
  37.                         palette_set.Saving += new Win.PalettePersistEventHandler(palette_set_Saving);
  38.  
  39.                         palette_set.KeepFocus = true;
  40.                         palette_set.Visible = true;
  41.                 }
  42.  
  43.                 void palette_set_Save(object sender, Win.PalettePersistEventArgs e) {
  44.                         palette_set_Save(e.ConfigurationSection);
  45.                 }
  46.  
  47.                 void palette_set_Saving(object sender, Win.PalettePersistEventArgs e) {
  48.                         // The empty implementation...
  49.                 }
  50.  
  51.                 // This names can't to contain the spaces (it will used as the xml
  52.                 // element's and attribute's names)!
  53.                 const String name = "AAA";
  54.                 const String name2 = "BBB";
  55.                 const String val_1_name = "Value_1";
  56.                 const String val_2_name = "Value_2";
  57.  
  58.                 void palette_set_Load(object sender, Win.PalettePersistEventArgs e) {
  59.                         App.IConfigurationSection section = e.ConfigurationSection;
  60.                         App.IConfigurationSection subsection = null;
  61.                         App.IConfigurationSection subsection2 = null;
  62.  
  63.                         if (!section.IsReadOnly) {
  64.                                 Boolean n = section.ContainsSubsection(name);
  65.                                 if (n)
  66.                                         subsection = section.OpenSubsection(name);
  67.                                 else
  68.                                         subsection = section.CreateSubsection(name);
  69.  
  70.                                 if (!subsection.IsReadOnly) {
  71.                                         Boolean b = subsection.ContainsSubsection(name2);
  72.                                         if (b)
  73.                                                 subsection2 = subsection.OpenSubsection(name2);
  74.                                         else
  75.                                                 subsection2 = subsection.CreateSubsection(name2);
  76.                                 }
  77.  
  78.                                 Int32 val_1 = (Int32)subsection2.ReadProperty(val_1_name, 100);
  79.                                 Int32 val_2 = (Int32)subsection2.ReadProperty(val_2_name, 200);                        
  80.                         }
  81.                 }
  82.  
  83.                 void palette_set_Save(App.IConfigurationSection section) {
  84.                         if (section == null || section.IsReadOnly)
  85.                                 return;
  86.                         App.IConfigurationSection subsection = null;
  87.                         App.IConfigurationSection subsection2 = null;
  88.  
  89.                         Boolean b = section.ContainsSubsection(name);
  90.                         if (b)
  91.                                 subsection = section.OpenSubsection(name);
  92.                         else
  93.                                 subsection = section.CreateSubsection(name);
  94.  
  95.                         if (subsection != null && !subsection.IsReadOnly) {
  96.                                 Boolean n = subsection.ContainsSubsection(name2);
  97.                                 if (n)
  98.                                         subsection2 = subsection.OpenSubsection(name2);
  99.                                 else
  100.                                         subsection2 = subsection.CreateSubsection(name2);
  101.                         }
  102.  
  103.                         if (subsection2 != null && !subsection2.IsReadOnly) {
  104.                                 subsection2.WriteProperty(val_1_name, 123);
  105.                                 subsection2.WriteProperty(val_2_name, 456);
  106.                         }
  107.                 }
  108.         }
  109. }

Если по завершению работы AutoCAD вы заглянете в AWS файл, то обнаружите, что в нём появились такие настройки:

Код - XML [Выбрать]
  1. <Tool CLSID="{49DBC66F-21BE-4D9F-A5A9-BA750543042E}">
  2.   <CAdUiDockControlBar Orientation="-1" AllowDocking="1">
  3.     <FloatInfo Left="458" Top="295" Width="447" Height="384"/>
  4.     <DockInfo Left="0" Top="6732" Width="300" Height="798" MRUDockID="59420"/>
  5.   </CAdUiDockControlBar>
  6.   <CAdUiPaletteSet/>
  7.   <AAA>
  8.     <BBB Value_1="123" Value_2="456"/>
  9.   </AAA>
  10. </Tool>

Если вы закомментируете строку 37, то событие IConfigurationSection.Save происходить не будет. В виду этого не будет вызван на исполнение код метода palette_set_Save и, как следствие, выполненные в этом коде изменения настроек не будут произведены.
Название: Re: Не удаётся создать Subsection (раздел в реестре) для настроек PaletteSet
Отправлено: Александр Ривилис от 06-12-2013, 20:05:38
К сожалению, AutoCAD не генерирует событие PaletteSet.Save, если вы дополнительно не зарегистрировались и на свойство PaletteSet.Saving (даже если оно вам и не нужно). Вам придётся зарегистрировать на PaletteSet.Saving хотя бы "пустышку" (метод, в котором ничего нет). Это баг.
Молодец. Отличная работа! Похоже ты прав. Кстати, в составе ObjectARX SDK 2009 (и в более ранних) есть пример samples\dotNet\DockingPalette. В нём есть подписка на события Save и Load, но нет подписки на событие Saving. Интересно работает ли корректно этот пример? У меня как раз AutoCAD 2009 не установлен, а в других версиях проверять будет не вполне корректно.

P.S.: Интересно в ADN DevHelp найдут сами решение или придётся им подсказать? Пока подождём.  ::)
Название: Re: Не удаётся создать Subsection (раздел в реестре) для настроек PaletteSet
Отправлено: Андрей Бушман от 09-12-2013, 12:32:22
Меня несколько удивляет тот факт, что генерация события Save происходит ДО генерации события Saving - по логике наименований должно быть наоборот...

Обнаружил ещё кое-что... Оказывается, что событие Save (при отсутствии подписки на Saving) не генерируется в том случае, если палитра пустая. В случае же наличия на палитре какого-либо элемента, событие Save начинает работать (даже если нет подписки на Saving).

Код - C# [Выбрать]
  1. /* © Andrey Bushman, 2013
  2.  * AutoCAD 2014 x64 SP1
  3.  * The sample, how to save the some settings of your custom controls into the AWS file.
  4.  */
  5.  
  6. using System;
  7. using Microsoft.Win32;
  8.  
  9. using cad = Autodesk.AutoCAD.ApplicationServices.Application;
  10. using App = Autodesk.AutoCAD.ApplicationServices;
  11. using Db = Autodesk.AutoCAD.DatabaseServices;
  12. using Ed = Autodesk.AutoCAD.EditorInput;
  13. using Rtm = Autodesk.AutoCAD.Runtime;
  14. using Win = Autodesk.AutoCAD.Windows;
  15. using Int = System.Windows.Forms.Integration;
  16. using WF = System.Windows.Forms;
  17. [assembly: Rtm.CommandClass(typeof(Bushman.CAD.Problems.Commands))]
  18.  
  19. namespace Bushman.CAD.Problems {
  20.  
  21.         public class Commands {
  22.  
  23.                 [Rtm.CommandMethod("cmd_5", Rtm.CommandFlags.Modal)]
  24.                 public void Command_5() {
  25.                         Ed.Editor ed = cad.DocumentManager.MdiActiveDocument.Editor;
  26.  
  27.                         // This settings will be saved into the
  28.                         // %AppData%\Autodesk\AutoCAD 2014\R19.1\enu\Support\Profiles\Unnamed Profile\Profile.aws
  29.                         // if the current profile is the <<Unnamed Profile>>.
  30.                         Win.PaletteSet palette_set = new Win.PaletteSet("My Palette",
  31.                                         new Guid("{49DBC66F-21BE-4D9F-A5A9-BA750543042E}"));
  32.  
  33.                         // Add the some Control item on the palette (the Label for example)...
  34.                         WF.Label label = new WF.Label();
  35.                         label.Text = "Hello, World";
  36.                         palette_set.Add("123", label);
  37.  
  38.                         palette_set.Load += new Win.PalettePersistEventHandler(palette_set_Load);
  39.                         palette_set.Save += new Win.PalettePersistEventHandler(palette_set_Save);
  40.  
  41.                         palette_set.KeepFocus = true;
  42.                         palette_set.Visible = true;
  43.                 }
  44.  
  45.                 void palette_set_Save(object sender, Win.PalettePersistEventArgs e) {
  46.                         palette_set_Save(e.ConfigurationSection);
  47.                 }
  48.  
  49.                 // This names can't to contain the spaces (it will used as the xml
  50.                 // element's and attribute's names)!
  51.                 const String name = "AAA";
  52.                 const String name2 = "BBB";
  53.                 const String val_1_name = "Value_1";
  54.                 const String val_2_name = "Value_2";
  55.  
  56.                 void palette_set_Load(object sender, Win.PalettePersistEventArgs e) {
  57.                         App.IConfigurationSection section = e.ConfigurationSection;
  58.                         App.IConfigurationSection subsection = null;
  59.                         App.IConfigurationSection subsection2 = null;
  60.  
  61.                         if (!section.IsReadOnly) {
  62.                                 Boolean n = section.ContainsSubsection(name);
  63.                                 if (n)
  64.                                         subsection = section.OpenSubsection(name);
  65.                                 else
  66.                                         subsection = section.CreateSubsection(name);
  67.  
  68.                                 if (!subsection.IsReadOnly) {
  69.                                         Boolean b = subsection.ContainsSubsection(name2);
  70.                                         if (b)
  71.                                                 subsection2 = subsection.OpenSubsection(name2);
  72.                                         else
  73.                                                 subsection2 = subsection.CreateSubsection(name2);
  74.                                 }
  75.  
  76.                                 Int32 val_1 = (Int32)subsection2.ReadProperty(val_1_name, 100);
  77.                                 Int32 val_2 = (Int32)subsection2.ReadProperty(val_2_name, 200);
  78.                         }
  79.                 }
  80.  
  81.                 void palette_set_Save(App.IConfigurationSection section) {
  82.                         if (section == null || section.IsReadOnly)
  83.                                 return;
  84.                         App.IConfigurationSection subsection = null;
  85.                         App.IConfigurationSection subsection2 = null;
  86.  
  87.                         Boolean b = section.ContainsSubsection(name);
  88.                         if (b)
  89.                                 subsection = section.OpenSubsection(name);
  90.                         else
  91.                                 subsection = section.CreateSubsection(name);
  92.  
  93.                         if (subsection != null && !subsection.IsReadOnly) {
  94.                                 Boolean n = subsection.ContainsSubsection(name2);
  95.                                 if (n)
  96.                                         subsection2 = subsection.OpenSubsection(name2);
  97.                                 else
  98.                                         subsection2 = subsection.CreateSubsection(name2);
  99.                         }
  100.  
  101.                         if (subsection2 != null && !subsection2.IsReadOnly) {
  102.                                 subsection2.WriteProperty(val_1_name, 123);
  103.                                 subsection2.WriteProperty(val_2_name, 456);
  104.                         }
  105.                 }
  106.         }
  107. }

Любопытный момент: если при этом выполнена подписка и на событие Saving, то Save генерируется дважды. Во втором случае последовательность генерации событий следующая:

Избыточная цепь генерации событий, на мой взгляд.

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

С уважением, Андрей.
Название: Re: Не удаётся создать Subsection (раздел в реестре) для настроек PaletteSet
Отправлено: Александр Ривилис от 09-12-2013, 20:35:51
Оказывается, что событие Save (при отсутствии подписки на Saving) не генерируется в том случае, если палитра пустая.
Не очень понятно баг это или фича, но в ADN DevHelp отправлю - пусть объяснят.
Избыточная цепь генерации событий, на мой взгляд.
Согласен полностью.
Жду первого ответа по этой теме от ADN DevHelp.

Название: Re: Не удаётся создать Subsection (раздел в реестре) для настроек PaletteSet
Отправлено: Александр Ривилис от 10-12-2013, 17:01:46
На первый вопрос я получил ответ от ADN DevHelp - PaletteSet.Save генерируется только если она не пустая, т.е. есть хоть одна Palette. Но это ты уже и сам нашел.