ADN Club > AutoCAD .NET API
Не удаётся создать Subsection (раздел в реестре) для настроек PaletteSet
Андрей Бушман:
Доброго времени суток.
- AutoCAD 2009 x86 SP3 Enu.
На событие PaletteSet.Save вешаю такой код:
--- Код - C# [Выбрать] ---void palette_set_Save(object sender, Win.PalettePersistEventArgs e) { App.IConfigurationSection subsection_company = null; App.IConfigurationSection subsection_product = null; GetSubsections(e.ConfigurationSection, out subsection_company, out subsection_product); if (palette_set != null) { if (subsection_company == null) subsection_company = e.ConfigurationSection.CreateSubsection(company_name); Boolean is_read_only = subsection_company.IsReadOnly; // False if (subsection_product == null) // COMException here! // Message: Error HRESULT E_FAIL has been returned from a call to a COM component. subsection_product = subsection_company.CreateSubsection(product_name); subsection_company.WriteProperty("Copyright", "© Andrey Bushman, 2013"); subsection_company.WriteProperty("Site", "http://sites.google.com/site/bushmansnetlaboratory/"); subsection_product.WriteProperty("Location X", palette_set.Location.X); subsection_product.WriteProperty("Location Y", palette_set.Location.Y); subsection_product.WriteProperty("Width", palette_set.Size.Width); subsection_product.WriteProperty("Height", palette_set.Size.Height); }} void GetSubsections(App.IConfigurationSection config_section, out App.IConfigurationSection subsection_company, out App.IConfigurationSection subsection_product) { subsection_company = null; subsection_product = null; if (config_section == null) return; subsection_company = config_section.ContainsSubsection(company_name) ? config_section.OpenSubsection(company_name) : null; subsection_product = subsection_company != null && subsection_company.ContainsSubsection(product_name) ? subsection_product = subsection_company.OpenSubsection(product_name) : null;}
Однако получаю исключение, обозначенное в комментариях. Я пробовал создавать вложенную секцию (Subsection) и в коде, подключенном к PaletteSet.Load - там та же история.
Почему не удаётся создать вложенную секцию?
Спасибо.
Андрей Бушман:
Хм... Написал простой пример, где посредством IConfigurationSection вношу изменения в реестр двумя способами (второй - это аналог коду из первого сообщения). Как это ни странно, но сейчас оба способа работают...
Возникли некоторые непонятные моменты:
1. Я не понял, почему в этот раз не возникает ошибка, обозначенная в аналогичном коде, приведённом выше.
2. Брэйкпоинт в palette_set_Save никогда не срабатывает, а срабатывает лишь в palette_set_Load.
3. Несмотря на п.2, палитра каким-то чудом запоминает свою позицию. Поиск по реестру ничего не даёт (искал по "ААА", "Location X", а так же по указанному GUID). Куда AutoCAD сохраняет эту информацию?
Наверное у меня уже глаз замылился... :(
--- Код - C# [Выбрать] ---// © Andrey Bushman, 2013using System;using Microsoft.Win32; using cad = Autodesk.AutoCAD.ApplicationServices.Application;using App = Autodesk.AutoCAD.ApplicationServices;using Db = Autodesk.AutoCAD.DatabaseServices;using Ed = Autodesk.AutoCAD.EditorInput;using Rtm = Autodesk.AutoCAD.Runtime;using Win = Autodesk.AutoCAD.Windows;using System.IO; [assembly: Rtm.CommandClass(typeof(Bushman.CAD.Problems.Commands))][assembly: Rtm.ExtensionApplication(typeof(Bushman.CAD.Problems.Commands))] namespace Bushman.CAD.Problems { public class Commands : Rtm.IExtensionApplication { internal static Win.PaletteSet palette_set = null; [Rtm.CommandMethod("cmd_1", Rtm.CommandFlags.Modal)] public void Command_1() { Ed.Editor ed = cad.DocumentManager.MdiActiveDocument.Editor; App.IConfigurationSection cp = cad.UserConfigurationManager.OpenCurrentProfile(); const String name = "Bushman"; const String name2 = "My Some Application"; const String propName = "Property 1"; App.IConfigurationSection section = cp.ContainsSubsection(name) ? cp.OpenSubsection(name) : cp.CreateSubsection(name); App.IConfigurationSection section2 = section.ContainsSubsection(name2) ? section.OpenSubsection(name2) : section.CreateSubsection(name2); section2.WriteProperty(propName, "Hello, World!"); String cprofile = cad.GetSystemVariable("cprofile") as String; String path = Path.Combine(Db.HostApplicationServices.Current.RegistryProductRootKey, @"Profiles\" + cprofile); RegistryKey regKey = Registry.CurrentUser.OpenSubKey(path, false); RegistryKey regKey2 = regKey.OpenSubKey(name).OpenSubKey(name2); String value = regKey2.GetValue(propName, String.Empty) as String; ed.WriteMessage("Register: {0}\n", regKey2.Name); ed.WriteMessage("The register is successfully changed!\n"); } [Rtm.CommandMethod("cmd_2", Rtm.CommandFlags.Modal)] public void Command_2() { Ed.Editor ed = cad.DocumentManager.MdiActiveDocument.Editor; if (palette_set == null) { palette_set = new Win.PaletteSet("My Palette", new Guid("{49DBC66F-21BE-4D9F-A5A9-BA750543042E}")); palette_set.Load += new Win.PalettePersistEventHandler(palette_set_Load); palette_set.Save += new Win.PalettePersistEventHandler(palette_set_Save); } palette_set.KeepFocus = true; palette_set.Visible = true; } void palette_set_Load(object sender, Win.PalettePersistEventArgs e) { App.IConfigurationSection section = e.ConfigurationSection; App.IConfigurationSection subsection = null; App.IConfigurationSection subsection2 = null; const String name = "AAA"; const String name2 = "BBB"; if (!section.IsReadOnly) { subsection = section.ContainsSubsection(name) ? section.OpenSubsection(name) : section.CreateSubsection(name); if (!subsection.IsReadOnly) { subsection2 = subsection.ContainsSubsection(name2) ? subsection.OpenSubsection(name2) : subsection.CreateSubsection(name2); } Int32 x = (Int32)subsection2.ReadProperty("Location X", 300); Int32 y = (Int32)subsection2.ReadProperty("Location Y", 200); } } void palette_set_Save(object sender, Win.PalettePersistEventArgs e) { App.IConfigurationSection section = e.ConfigurationSection; App.IConfigurationSection subsection = null; App.IConfigurationSection subsection2 = null; const String name = "AAA"; const String name2 = "BBB"; if (!section.IsReadOnly) { subsection = section.ContainsSubsection(name) ? section.OpenSubsection(name) : section.CreateSubsection(name); if (!subsection.IsReadOnly) { subsection2 = subsection.ContainsSubsection(name2) ? subsection.OpenSubsection(name2) : subsection.CreateSubsection(name2); } subsection2.WriteProperty("Location X", palette_set.Location.X); subsection2.WriteProperty("Location Y", palette_set.Location.Y); } } public void Initialize() { Ed.Editor ed = cad.DocumentManager.MdiActiveDocument.Editor; ed.WriteMessage("The 'Hello World' is loaded... \n"); } public void Terminate() { // throw new NotImplementedException(); } }}
Александр Ривилис:
--- Цитата: Андрей Бушман от 04-12-2013, 16:08:36 ---3. Несмотря на п.2, палитра каким-то чудом запоминает свою позицию. Поиск по реестру ничего не даёт (искал по "ААА", "Location X", а так же по указанному GUID). Куда AutoCAD сохраняет эту информацию?
--- Конец цитаты ---
Может по имени палитры поищешь? Мне всегда казалось, что сохраняется эта информация сюда:
HKEY_CURRENT_USER\Software\Autodesk\AutoCAD\RXX.X\ACAD-YYYY:LLL\Profiles\<<Имя профиля>>\Dialogs
Андрей Бушман:
--- Цитата: Александр Ривилис от 05-12-2013, 03:13:33 ---Может по имени палитры поищешь? Мне всегда казалось, что сохраняется эта информация сюда:
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 [Выбрать] ---<Tool CLSID="{49DBC66F-21BE-4D9F-A5A9-BA750543042E}"> <CAdUiDockControlBar Orientation="-1" AllowDocking="1"> <FloatInfo Left="342" Top="310" Width="300" Height="300"/> <DockInfo Left="0" Top="792" Width="300" Height="798" MRUDockID="59420"/> </CAdUiDockControlBar> <CAdUiPaletteSet/> <AAA> <BBB/> </AAA></Tool>
Обратите внимание на то, что элементы AAA и BBB созданы за счёт выполнения метода palette_set_Load. Однако я регистрировал и метод palette_set_Save, который должен был при завершении работы AutoCAD дописывать туда два дополнительных элемента, но этого почему-то не происходит (зарегистрированный код не вызывается автокадом)...
Поскольку информация, связанная с палитрами записывается в XML фай, то сразу становится понятна причина сбоя... Я ведь изначально ожидал, что информация будет записываться в реестр и вложенному подразделу пытался задать имя "Sheet Set Viewer". В реестре такие имена допустимы, но не в XML - там в имени элемента не должно содержаться пробелов. Т.о. заменив имя подраздела на "Sheet_Set_Viewer", я тем самым устранил проблему. В XML это выглядит так:
--- Код - XML [Выбрать] ---<Tool CLSID="{E06974C1-B748-4D8A-B1CC-CB9AADA26B79}"> <CAdUiDockControlBar Orientation="-1" AllowDocking="1"> <FloatInfo Left="150" Top="200" Width="300" Height="300"/> <DockInfo Left="0" Top="396" Width="300" Height="798" MRUDockID="59420"/> </CAdUiDockControlBar> <CAdUiPaletteSet/> <Bushman> <Sheet_Set_Viewer/> </Bushman></Tool>
Отсюда вывод: если не хотите, чтобы в один прекрасный момент ваш код, использующий IConfigurationSection перестал работать, когда компания Autodesk вдруг решит часть настроек перенести из реестра в XML, то имена своим пользовательским разделам, подразделам и параметрам следует на всякий случай назначать без пробелов. :)
Т.о. вопрос, обозначенный в первом сообщении темы закрыт. Однако меня по прежнему интересует, почему выполняется мой код, зарегистрированный на событие Load и не выполняется код, зарегистрированный на событие Save?
Показываю простой исходный код, демонстрирующий проблему:
--- Код - C# [Выбрать] ---// © Andrey Bushman, 2013using System;using Microsoft.Win32; using cad = Autodesk.AutoCAD.ApplicationServices.Application;using App = Autodesk.AutoCAD.ApplicationServices;using Db = Autodesk.AutoCAD.DatabaseServices;using Ed = Autodesk.AutoCAD.EditorInput;using Rtm = Autodesk.AutoCAD.Runtime;using Win = Autodesk.AutoCAD.Windows;using System.IO; [assembly: Rtm.CommandClass(typeof(Bushman.CAD.Problems.Commands))][assembly: Rtm.ExtensionApplication(typeof(Bushman.CAD.Problems.Commands))] namespace Bushman.CAD.Problems { public class Commands : Rtm.IExtensionApplication { internal static Win.PaletteSet palette_set = null; [Rtm.CommandMethod("cmd_1", Rtm.CommandFlags.Modal)] public void Command_1() { Ed.Editor ed = cad.DocumentManager.MdiActiveDocument.Editor; App.IConfigurationSection cp = cad.UserConfigurationManager.OpenCurrentProfile(); const String name = "Bushman"; // This names can to contain the spaces const String name2 = "My Some Application"; const String propName = "Property 1"; // This settings will created in the registry (HKCU) App.IConfigurationSection section = cp.ContainsSubsection(name) ? cp.OpenSubsection(name) : cp.CreateSubsection(name); App.IConfigurationSection section2 = section.ContainsSubsection(name2) ? section.OpenSubsection(name2) : section.CreateSubsection(name2); section2.WriteProperty(propName, "Hello, World!"); String cprofile = cad.GetSystemVariable("cprofile") as String; String path = Db.HostApplicationServices.Current.UserRegistryProductRootKey + @"\Profiles\" + cprofile; using (RegistryKey regKey = Registry.CurrentUser.OpenSubKey(path, false)) { using (RegistryKey regKey2 = regKey.OpenSubKey(name).OpenSubKey(name2)) { String value = regKey2.GetValue(propName, String.Empty) as String; ed.WriteMessage("Register: {0}\n", regKey2.Name); ed.WriteMessage("The register is successfully changed!\n"); } } } [Rtm.CommandMethod("cmd_2", Rtm.CommandFlags.Modal)] public void Command_2() { Ed.Editor ed = cad.DocumentManager.MdiActiveDocument.Editor; if (palette_set == null) { // This settings will be saved into the // %AppData%\Autodesk\AutoCAD 2014\R19.1\enu\Support\Profiles\Unnamed Profile\Profile.aws // if the current profile is <<Unnamed Profile>>. palette_set = new Win.PaletteSet("My Palette", new Guid("{49DBC66F-21BE-4D9F-A5A9-BA750543042E}")); palette_set.Load += new Win.PalettePersistEventHandler(palette_set_Load); palette_set.Save += new Win.PalettePersistEventHandler(palette_set_Save); } palette_set.KeepFocus = true; palette_set.Visible = true; } // This names can't to contain the spaces! const String name = "AAA"; const String name2 = "BBB"; const String val_1_name = "Value_1"; const String val_2_name = "Value_2"; void palette_set_Load(object sender, Win.PalettePersistEventArgs e) { App.IConfigurationSection section = e.ConfigurationSection; App.IConfigurationSection subsection = null; App.IConfigurationSection subsection2 = null; if (!section.IsReadOnly) { subsection = section.ContainsSubsection(name) ? section.OpenSubsection(name) : section.CreateSubsection(name); if (!subsection.IsReadOnly) { subsection2 = subsection.ContainsSubsection(name2) ? subsection.OpenSubsection(name2) : subsection.CreateSubsection(name2); } Int32 val_1 = (Int32)subsection2.ReadProperty(val_1_name, 100); Int32 val_2 = (Int32)subsection2.ReadProperty(val_2_name, 200); } } void palette_set_Save(object sender, Win.PalettePersistEventArgs e) { App.IConfigurationSection section = e.ConfigurationSection; App.IConfigurationSection subsection = null; App.IConfigurationSection subsection2 = null; if (!section.IsReadOnly) { subsection = section.ContainsSubsection(name) ? section.OpenSubsection(name) : section.CreateSubsection(name); if (!subsection.IsReadOnly) { subsection2 = subsection.ContainsSubsection(name2) ? subsection.OpenSubsection(name2) : subsection.CreateSubsection(name2); } subsection2.WriteProperty(val_1_name, 700); subsection2.WriteProperty(val_2_name, 800); } } public void Initialize() { Ed.Editor ed = cad.DocumentManager.MdiActiveDocument.Editor; ed.WriteMessage("The 'Hello World' is loaded... \n"); } public void Terminate() { // throw new NotImplementedException(); } }}
На всякий случай прикрепляю исходники, настроенные на AutoCAD 2014 x64.
Спасибо.
Андрей Бушман:
Я попробовал выполнить сохранение настроек, подписавшись на событие Application.BeginQuit, но это не помогло. В комментариях я показал точку сбоя и своё предположение о его причине...
--- Код - C# [Выбрать] ---// © Andrey Bushman, 2013using System;using Microsoft.Win32; using cad = Autodesk.AutoCAD.ApplicationServices.Application;using App = Autodesk.AutoCAD.ApplicationServices;using Db = Autodesk.AutoCAD.DatabaseServices;using Ed = Autodesk.AutoCAD.EditorInput;using Rtm = Autodesk.AutoCAD.Runtime;using Win = Autodesk.AutoCAD.Windows;using System.IO; [assembly: Rtm.CommandClass(typeof(Bushman.CAD.Problems.Commands))][assembly: Rtm.ExtensionApplication(typeof(Bushman.CAD.Problems.Commands))] namespace Bushman.CAD.Problems { public class Commands : Rtm.IExtensionApplication { internal static Win.PaletteSet palette_set = null; [Rtm.CommandMethod("cmd_1", Rtm.CommandFlags.Modal)] public void Command_1() { Ed.Editor ed = cad.DocumentManager.MdiActiveDocument.Editor; App.IConfigurationSection cp = cad.UserConfigurationManager.OpenCurrentProfile(); const String name = "Bushman"; // This names can to contain the spaces const String name2 = "My Some Application"; const String propName = "Property 1"; // This settings will created in the registry (HKCU) App.IConfigurationSection section = cp.ContainsSubsection(name) ? cp.OpenSubsection(name) : cp.CreateSubsection(name); App.IConfigurationSection section2 = section.ContainsSubsection(name2) ? section.OpenSubsection(name2) : section.CreateSubsection(name2); section2.WriteProperty(propName, "Hello, World!"); String cprofile = cad.GetSystemVariable("cprofile") as String; String path = Db.HostApplicationServices.Current.UserRegistryProductRootKey + @"\Profiles\" + cprofile; using (RegistryKey regKey = Registry.CurrentUser.OpenSubKey(path, false)) { using (RegistryKey regKey2 = regKey.OpenSubKey(name).OpenSubKey(name2)) { String value = regKey2.GetValue(propName, String.Empty) as String; ed.WriteMessage("Register: {0}\n", regKey2.Name); ed.WriteMessage("The register is successfully changed!\n"); } } } [Rtm.CommandMethod("cmd_2", Rtm.CommandFlags.Modal)] public void Command_2() { Ed.Editor ed = cad.DocumentManager.MdiActiveDocument.Editor; if (palette_set == null) { // This settings will be saved into the // %AppData%\Autodesk\AutoCAD 2014\R19.1\enu\Support\Profiles\Unnamed Profile\Profile.aws // if the current profile is <<Unnamed Profile>>. palette_set = new Win.PaletteSet("My Palette", new Guid("{49DBC66F-21BE-4D9F-A5A9-BA750543042E}")); palette_set.Load += new Win.PalettePersistEventHandler(palette_set_Load); cad.BeginQuit += new EventHandler(cad_BeginQuit); } palette_set.KeepFocus = true; palette_set.Visible = true; } static App.IConfigurationSection _palette_set = null; void cad_BeginQuit(object sender, EventArgs e) { palette_set_Save(null, _palette_set); } // This names can't to contain the spaces! const String name = "AAA"; const String name2 = "BBB"; const String val_1_name = "Value_1"; const String val_2_name = "Value_2"; void palette_set_Load(object sender, Win.PalettePersistEventArgs e) { App.IConfigurationSection section = _palette_set = e.ConfigurationSection; App.IConfigurationSection subsection = null; App.IConfigurationSection subsection2 = null; if (!section.IsReadOnly) { subsection = section.ContainsSubsection(name) ? section.OpenSubsection(name) : section.CreateSubsection(name); if (!subsection.IsReadOnly) { subsection2 = subsection.ContainsSubsection(name2) ? subsection.OpenSubsection(name2) : subsection.CreateSubsection(name2); } Int32 val_1 = (Int32)subsection2.ReadProperty(val_1_name, 100); Int32 val_2 = (Int32)subsection2.ReadProperty(val_2_name, 200); } } void palette_set_Save(object sender, App.IConfigurationSection section) { App.IConfigurationSection subsection = null; App.IConfigurationSection subsection2 = null; if (section != null && !section.IsReadOnly) { // TODO: Problem is here. // Here execution of code interrupts... Maybe IConfigurationSection is disposed already... subsection = section.ContainsSubsection(name) ? section.OpenSubsection(name) : section.CreateSubsection(name); if (!subsection.IsReadOnly) { subsection2 = subsection.ContainsSubsection(name2) ? subsection.OpenSubsection(name2) : subsection.CreateSubsection(name2); } subsection2.WriteProperty(val_1_name, 700); subsection2.WriteProperty(val_2_name, 800); } } public void Initialize() { Ed.Editor ed = cad.DocumentManager.MdiActiveDocument.Editor; ed.WriteMessage("The 'Hello World' is loaded... \n"); } public void Terminate() { // throw new NotImplementedException(); } }}
Навигация
Перейти к полной версии