Создание и настройка динамических блоков в чертеже без его открытия

Автор Тема: Создание и настройка динамических блоков в чертеже без его открытия  (Прочитано 14796 раз)

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

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

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Всем хороших выходных!
Столкнулся с очередной проблемой. Приложение открывает существующие чертежи в фоне (создаю новую базу данных и читаю в нее чертеж), копирует в них определения динамических блоков из чертежа-шаблона и настраивает их динамические параметры. Так вот, если использовать обыкновенную транзакцию при работе с блоками, то блоки выглядят после этого "как надо". Но если обрабатывать блоки без транзакции, то при открытии обработанного чертежа можно увидеть такую картину: параметры блокам заданы, но их отображение не изменилось. Оно остается таким, как будто динамический блок только что вставили. При попытке изменить динпараметры, блок просто "разваливается". Казалось бы, никакой проблемы - используем транзакцию и радуемся. Но! При обработке больших чертежей, в какой-то случайный момент вываливается исключение System.AccessViolationException без указания места, в котором это исключение возникло. Без транзакции исключений не возникает, но и результат обработки не тот, что нужен. Как быть? Возможно ли такое, что нельзя в фоне работать с динамическими блоками?
Я пока вижу два решения:
Первое - открывать каждый обрабатываемый чертеж как документ. Это решило бы проблему, но время обработки увеличится очень сильно.
Второе - использовать AcCoreConsole. Но нет уверенности, что в нем не будет каких-то еще проблем.
Возможно, есть какое-то еще решение этой проблемы?

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

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

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Понял. Сделаю тестовый проект с примерами чертежей. Но уже не сегодня :)

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Вы не поверите... В тестовом проекте и чертеже все работает без проблем. Что с транзакцией, что с эмуляцией - динпараметры задаются корректно. Буду искать, где намудрил в рабочем проекте.

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
А нет! Таки нашел сочетание сбойное! Оказывается, работу рушат атрибуты.
Как это выглядит:

Тестовый код:
Код - C# [Выбрать]
  1. using Autodesk.AutoCAD.ApplicationServices;
  2. using Autodesk.AutoCAD.DatabaseServices;
  3. using Autodesk.AutoCAD.EditorInput;
  4. using Autodesk.AutoCAD.Geometry;
  5. using Autodesk.AutoCAD.Runtime;
  6. using System;
  7. using System.Collections.Generic;
  8. using System.IO;
  9. using System.Linq;
  10.  
  11. namespace AcadTest
  12. {
  13.     public class DynBlockTest
  14.     {
  15.         public static RXClass AttDefRXCLass = RXClass.GetClass(typeof(AttributeDefinition));
  16.  
  17.         static int counter = 0;        
  18.  
  19.         [CommandMethod("TestDynBlockBackgroundPaste")]
  20.         public void InsertAndSettings()
  21.         {
  22.             Document adoc = Application.DocumentManager.MdiActiveDocument;
  23.             Editor ed = adoc.Editor;
  24.             Database db = adoc.Database;
  25.  
  26.             PromptEntityOptions entOpts = new PromptEntityOptions("\nSelect dynamic block: ");
  27.             entOpts.SetRejectMessage("This is not block!");
  28.             entOpts.AddAllowedClass(typeof(BlockReference), true);
  29.  
  30.             PromptEntityResult entRes = ed.GetEntity(entOpts);
  31.             if (entRes.Status != PromptStatus.OK) return;
  32.  
  33.             ObjectId bTabRecId = ObjectId.Null;
  34.             Dictionary<string, object> blkDynProps = new Dictionary<string, object>();
  35.             Dictionary<string, string> attribs = new Dictionary<string, string>();
  36.  
  37.             using (Transaction tr = db.TransactionManager.StartTransaction())
  38.             {
  39.                 BlockReference bref = tr.GetObject
  40.                     (entRes.ObjectId, OpenMode.ForRead) as BlockReference;
  41.                 if (bref.IsDynamicBlock)
  42.                 {
  43.                     bTabRecId = bref.DynamicBlockTableRecord;
  44.                     foreach (DynamicBlockReferenceProperty dynProp
  45.                         in bref.DynamicBlockReferencePropertyCollection)
  46.                     {
  47.                         blkDynProps[dynProp.PropertyName] = dynProp.Value;
  48.                     }
  49.  
  50.                     foreach (ObjectId attRefId in bref.AttributeCollection)
  51.                     {
  52.                         AttributeReference attRef = tr.GetObject
  53.                             (attRefId, OpenMode.ForRead) as AttributeReference;
  54.                         attribs[attRef.Tag] = attRef.TextString;
  55.                     }
  56.                 }
  57.  
  58.                 tr.Commit();
  59.             }
  60.  
  61.             if (bTabRecId.IsNull || blkDynProps.Count == 0)
  62.             {
  63.                 ed.WriteMessage("\nBlock without dynamic props! Exit.");
  64.                 return;
  65.             }
  66.  
  67.             if (attribs.Count == 0)
  68.             {
  69.                 ed.WriteMessage("\nBlock without attribs! Exit.");
  70.                 return;
  71.             }
  72.  
  73.             string dir = Path.GetDirectoryName(adoc.Name);
  74.  
  75.             PromptSaveFileOptions saveFileOpt = new PromptSaveFileOptions("Drawing for save: ");
  76.             saveFileOpt.Filter = "Drawing (*.dwg)|*.dwg";
  77.             saveFileOpt.InitialDirectory = dir;
  78.             saveFileOpt.InitialFileName = $"DynBlkTarget{++counter}.dwg";
  79.             PromptFileNameResult saveFileRes = ed.GetFileNameForSave(saveFileOpt);
  80.  
  81.             //PromptOpenFileOptions openFileOpt = new PromptOpenFileOptions("Drawing for paste block: ");
  82.             //openFileOpt.Filter = "Drawing (*.dwg)|*.dwg";
  83.             //openFileOpt.InitialDirectory = dir;
  84.             //openFileOpt.InitialFileName = "DynBlkTarget.dwg";
  85.             //PromptFileNameResult openFileRes = ed.GetFileNameForOpen(openFileOpt);
  86.  
  87.             //string openFileName = openFileRes.StringResult;
  88.             string newFilePath =
  89.                 //Path.Combine
  90.                 //    (Path.GetDirectoryName(openFileName),
  91.                 //    Path.GetFileNameWithoutExtension(openFileName) + "1.dwg");
  92.                 saveFileRes.StringResult;
  93.  
  94.             PromptKeywordOptions keyOpts = new PromptKeywordOptions("\nUse transaction?");
  95.             keyOpts.Keywords.Add("Yes");
  96.             keyOpts.Keywords.Add("No");
  97.             keyOpts.Message += keyOpts.Keywords.GetDisplayString(true);
  98.  
  99.             PromptResult keyRes = ed.GetKeywords(keyOpts);
  100.             if (keyRes.Status != PromptStatus.OK) return;
  101.  
  102.             bool useTrans = keyRes.StringResult == "Yes";
  103.  
  104.             using (Database newDb = new Database(true, true))
  105.             {
  106.                 //newDb.ReadDwgFile(openFileName,
  107.                 //        FileOpenMode.OpenForReadAndAllShare, true, "");
  108.                 ObjectIdCollection ids = new ObjectIdCollection();
  109.                 ids.Add(bTabRecId);
  110.                 IdMapping mapping = new IdMapping();
  111.                 newDb.WblockCloneObjects(ids, newDb.BlockTableId,
  112.                     mapping, DuplicateRecordCloning.Replace, false);
  113.  
  114.                 ObjectId newBTabRecId = mapping[bTabRecId].Value;
  115.  
  116.                 Transaction tr = useTrans ?
  117.                     newDb.TransactionManager.StartTransaction()
  118.                     : newDb.TransactionManager.StartOpenCloseTransaction();
  119.  
  120.                 using (tr)
  121.                 {
  122.                     BlockReference blkRef = new BlockReference(Point3d.Origin, newBTabRecId);
  123.  
  124.                     ObjectId mSpaceId = SymbolUtilityServices.GetBlockModelSpaceId(newDb);
  125.                     BlockTableRecord mSpace = tr.GetObject
  126.                         (mSpaceId, OpenMode.ForWrite) as BlockTableRecord;
  127.                     mSpace.AppendEntity(blkRef);
  128.                     tr.AddNewlyCreatedDBObject(blkRef, true);
  129.  
  130.                     BlockTableRecord blkRec = tr.GetObject
  131.                         (newBTabRecId, OpenMode.ForRead) as BlockTableRecord;
  132.  
  133.                     foreach (ObjectId attDefId in blkRec)
  134.                     {
  135.                         if (!attDefId.ObjectClass.Equals(AttDefRXCLass)) continue;
  136.  
  137.                         AttributeDefinition attDef = tr.GetObject
  138.                             (attDefId, OpenMode.ForRead) as AttributeDefinition;
  139.  
  140.                         if (!attDef.Constant)
  141.                         {
  142.                             AttributeReference attRef = new AttributeReference();
  143.                             attRef.SetAttributeFromBlock(attDef, blkRef.BlockTransform);
  144.                             if (!attDef.HasFields
  145.                                 && attribs.ContainsKey(attDef.Tag))
  146.                             {
  147.                                 attRef.TextString = attribs[attDef.Tag];
  148.                             }
  149.                             blkRef.AttributeCollection.AppendAttribute(attRef);
  150.                             tr.AddNewlyCreatedDBObject(attRef, true);
  151.                         }
  152.  
  153.                     }
  154.  
  155.                     foreach (DynamicBlockReferenceProperty dynProp
  156.                         in blkRef.DynamicBlockReferencePropertyCollection)
  157.                     {
  158.                         KeyValuePair<string, object> propData = blkDynProps
  159.                             .FirstOrDefault(item => item.Key.Equals
  160.                             (dynProp.PropertyName, StringComparison.InvariantCultureIgnoreCase));
  161.                         if (propData.Value != null && dynProp.PropertyName != "Origin")
  162.                         {
  163.                             try
  164.                             {
  165.                                 dynProp.Value = propData.Value;
  166.                             }
  167.                             catch
  168.                             {
  169.  
  170.                             }
  171.                         }
  172.                     }
  173.  
  174.                     tr.Commit();
  175.                 }
  176.                 newDb.SaveAs(newFilePath, DwgVersion.Current);
  177.             }
  178.  
  179.             Document newDoc = Application.DocumentManager.Open(newFilePath, false);
  180.             Application.DocumentManager.MdiActiveDocument = newDoc;
  181.         }
  182.     }
  183. }
  184.  
Тестовый чертеж с блоком - во вложении

Отмечено как Решение Дмитрий Загорулькин 05-06-2017, 12:28:39

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Проверяй. Я когда-то тебе говорил, что особенность использования Open/Close и отличие от транзакции в том, что следует побыстрее закрывать неиспользованные объекты.
Код - C# [Выбрать]
  1. using Autodesk.AutoCAD.ApplicationServices;
  2. using Autodesk.AutoCAD.DatabaseServices;
  3. using Autodesk.AutoCAD.EditorInput;
  4. using Autodesk.AutoCAD.Geometry;
  5. using Autodesk.AutoCAD.Runtime;
  6. using System;
  7. using System.Collections.Generic;
  8. using System.IO;
  9. using System.Linq;
  10.  
  11. #pragma warning disable 0618
  12.  
  13. namespace AcadTest
  14. {
  15.   public class DynBlockTest
  16.   {
  17.     public static RXClass AttDefRXCLass = RXClass.GetClass(typeof(AttributeDefinition));
  18.  
  19.     static int counter = 0;
  20.  
  21.     [CommandMethod("TestDynBlockBackgroundPaste")]
  22.     public void InsertAndSettings()
  23.     {
  24.       Document adoc = Application.DocumentManager.MdiActiveDocument;
  25.       Editor ed = adoc.Editor;
  26.       Database db = adoc.Database;
  27.  
  28.       PromptEntityOptions entOpts = new PromptEntityOptions("\nSelect dynamic block: ");
  29.       entOpts.SetRejectMessage("This is not block!");
  30.       entOpts.AddAllowedClass(typeof(BlockReference), true);
  31.  
  32.       PromptEntityResult entRes = ed.GetEntity(entOpts);
  33.       if (entRes.Status != PromptStatus.OK) return;
  34.  
  35.       ObjectId bTabRecId = ObjectId.Null;
  36.       Dictionary<string, object> blkDynProps = new Dictionary<string, object>();
  37.       Dictionary<string, string> attribs = new Dictionary<string, string>();
  38.  
  39.       using (Transaction tr = db.TransactionManager.StartTransaction())
  40.       {
  41.         BlockReference bref = tr.GetObject
  42.             (entRes.ObjectId, OpenMode.ForRead) as BlockReference;
  43.         if (bref.IsDynamicBlock)
  44.         {
  45.           bTabRecId = bref.DynamicBlockTableRecord;
  46.           foreach (DynamicBlockReferenceProperty dynProp
  47.               in bref.DynamicBlockReferencePropertyCollection)
  48.           {
  49.             blkDynProps[dynProp.PropertyName] = dynProp.Value;
  50.           }
  51.  
  52.           foreach (ObjectId attRefId in bref.AttributeCollection)
  53.           {
  54.             AttributeReference attRef = tr.GetObject
  55.                 (attRefId, OpenMode.ForRead) as AttributeReference;
  56.             attribs[attRef.Tag] = attRef.TextString;
  57.           }
  58.         }
  59.  
  60.         tr.Commit();
  61.       }
  62.  
  63.       if (bTabRecId.IsNull || blkDynProps.Count == 0)
  64.       {
  65.         ed.WriteMessage("\nBlock without dynamic props! Exit.");
  66.         return;
  67.       }
  68.  
  69.       if (attribs.Count == 0)
  70.       {
  71.         ed.WriteMessage("\nBlock without attribs! Exit.");
  72.         return;
  73.       }
  74.  
  75.       string dir = Path.GetDirectoryName(adoc.Name);
  76.  
  77.       PromptSaveFileOptions saveFileOpt = new PromptSaveFileOptions("Drawing for save: ");
  78.       saveFileOpt.Filter = "Drawing (*.dwg)|*.dwg";
  79.       saveFileOpt.InitialDirectory = dir;
  80.       saveFileOpt.InitialFileName = $"DynBlkTarget{++counter}.dwg";
  81.       PromptFileNameResult saveFileRes = ed.GetFileNameForSave(saveFileOpt);
  82.  
  83.       //PromptOpenFileOptions openFileOpt = new PromptOpenFileOptions("Drawing for paste block: ");
  84.       //openFileOpt.Filter = "Drawing (*.dwg)|*.dwg";
  85.       //openFileOpt.InitialDirectory = dir;
  86.       //openFileOpt.InitialFileName = "DynBlkTarget.dwg";
  87.       //PromptFileNameResult openFileRes = ed.GetFileNameForOpen(openFileOpt);
  88.  
  89.       //string openFileName = openFileRes.StringResult;
  90.       string newFilePath =
  91.           //Path.Combine
  92.           //    (Path.GetDirectoryName(openFileName),
  93.           //    Path.GetFileNameWithoutExtension(openFileName) + "1.dwg");
  94.           saveFileRes.StringResult;
  95.  
  96.       PromptKeywordOptions keyOpts = new PromptKeywordOptions("\nUse transaction?");
  97.       keyOpts.Keywords.Add("Yes");
  98.       keyOpts.Keywords.Add("No");
  99.       keyOpts.Message += keyOpts.Keywords.GetDisplayString(true);
  100.  
  101.       PromptResult keyRes = ed.GetKeywords(keyOpts);
  102.       if (keyRes.Status != PromptStatus.OK) return;
  103.  
  104.       bool useTrans = keyRes.StringResult == "Yes";
  105.       // Database oldDb = HostApplicationServices.WorkingDatabase;
  106.       using (Database newDb = new Database(true, false))
  107.       {
  108.         // HostApplicationServices.WorkingDatabase = newDb;
  109.         //newDb.ReadDwgFile(openFileName,
  110.         //        FileOpenMode.OpenForReadAndAllShare, true, "");
  111.         ObjectIdCollection ids = new ObjectIdCollection();
  112.         ids.Add(bTabRecId);
  113.         IdMapping mapping = new IdMapping();
  114.         newDb.WblockCloneObjects(ids, newDb.BlockTableId,
  115.             mapping, DuplicateRecordCloning.Replace, false);
  116.  
  117.         ObjectId newBTabRecId = mapping[bTabRecId].Value;
  118.  
  119.         Transaction tr = useTrans ?
  120.             newDb.TransactionManager.StartTransaction()
  121.             : newDb.TransactionManager.StartOpenCloseTransaction();
  122.  
  123.         using (tr)
  124.         {
  125.           BlockReference blkRef = new BlockReference(Point3d.Origin, newBTabRecId);
  126.  
  127.           ObjectId mSpaceId = SymbolUtilityServices.GetBlockModelSpaceId(newDb);
  128.           BlockTableRecord mSpace = tr.GetObject
  129.               (mSpaceId, OpenMode.ForWrite) as BlockTableRecord;
  130.           mSpace.AppendEntity(blkRef);
  131.           tr.AddNewlyCreatedDBObject(blkRef, true);
  132.  
  133.           BlockTableRecord blkRec = tr.GetObject
  134.               (newBTabRecId, OpenMode.ForRead) as BlockTableRecord;
  135.  
  136.           foreach (ObjectId attDefId in blkRec)
  137.           {
  138.             if (!attDefId.ObjectClass.Equals(AttDefRXCLass)) continue;
  139.  
  140.             AttributeDefinition attDef = tr.GetObject
  141.                 (attDefId, OpenMode.ForRead) as AttributeDefinition;
  142.  
  143.             if (!attDef.Constant)
  144.             {
  145.               AttributeReference attRef = new AttributeReference();
  146.               attRef.SetAttributeFromBlock(attDef, blkRef.BlockTransform);
  147.               if (!attDef.HasFields
  148.                   && attribs.ContainsKey(attDef.Tag))
  149.               {
  150.                 attRef.TextString = attribs[attDef.Tag];
  151.               }
  152.               blkRef.AttributeCollection.AppendAttribute(attRef);
  153.               tr.AddNewlyCreatedDBObject(attRef, true);
  154.               // Атрибут должен быть закрыт перед
  155.               // присвоением динамических свойств блоку
  156.               if (!useTrans) attRef.Close();
  157.  
  158.             }
  159.           }
  160.  
  161.           // BlockTableRecord нашего блока должна быть закрыта
  162.           // перед присвоением динамических свойств блоку
  163.           if (!useTrans) blkRec.Close();
  164.  
  165.           DynamicBlockReferencePropertyCollection dynProps =
  166.             blkRef.DynamicBlockReferencePropertyCollection;
  167.  
  168.           foreach (DynamicBlockReferenceProperty dynProp in dynProps)
  169.           {
  170.             KeyValuePair<string, object> propData = blkDynProps
  171.                 .FirstOrDefault(item => item.Key.Equals
  172.                 (dynProp.PropertyName, StringComparison.InvariantCultureIgnoreCase));
  173.             if (propData.Value != null && dynProp.PropertyName != "Origin")
  174.             {
  175.               try
  176.               {
  177.                 dynProp.Value = propData.Value;
  178.               }
  179.               catch (System.Exception ex)
  180.               {
  181.                 Application.DocumentManager.MdiActiveDocument.
  182.                   Editor.WriteMessage("\n{0}", ex);
  183.               }
  184.             }
  185.           }
  186.  
  187.           tr.Commit();
  188.         }
  189.         newDb.SaveAs(newFilePath, DwgVersion.Current);
  190.       }
  191.       // HostApplicationServices.WorkingDatabase = oldDb;
  192.  
  193.       Document newDoc = Application.DocumentManager.Open(newFilePath, false);
  194.       Application.DocumentManager.MdiActiveDocument = newDoc;
  195.     }
  196.   }
  197. }
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Проверил - все отлично работает! Спасибо!

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Словил еще две проблемы с атрибутами.
Первая - если в значение по умолчанию атрибута вставлено поле, ссылающееся на значение динпараметра этого блока (оказывается, и так можно делать! :o), то в результате работы кода в атрибуте вместо значения будут решетки. Как это выглядит:

Причем, без разницы как делать - с транзакцией или без нее. Результат от этого не меняется.
Поборол это таким способом: после вставки блока и задания ему динсвойств и атрибутов, повторно, для каждого атрибута с полем выполняю метод AttributeReference.SetAttributeFromBlock(AttributeDefinition, Matrix3d). Возможно, что тут по-другому никак.
Код - C# [Выбрать]
  1. using Autodesk.AutoCAD.ApplicationServices;
  2. using Autodesk.AutoCAD.DatabaseServices;
  3. using Autodesk.AutoCAD.EditorInput;
  4. using Autodesk.AutoCAD.Geometry;
  5. using Autodesk.AutoCAD.Runtime;
  6. using System;
  7. using System.Collections.Generic;
  8. using System.IO;
  9. using System.Linq;
  10.  
  11. #pragma warning disable 0618
  12.  
  13. namespace AcadTest
  14. {
  15.     public class DynBlockTest
  16.     {
  17.         public static RXClass AttDefRXCLass = RXClass.GetClass(typeof(AttributeDefinition));
  18.  
  19.         static int counter = 0;
  20.  
  21.         [CommandMethod("TestDynBlockBackgroundPaste1")]
  22.         public void InsertAndSettings()
  23.         {
  24.             Document adoc = Application.DocumentManager.MdiActiveDocument;
  25.             Editor ed = adoc.Editor;
  26.             Database db = adoc.Database;
  27.  
  28.             PromptEntityOptions entOpts = new PromptEntityOptions("\nSelect dynamic block: ");
  29.             entOpts.SetRejectMessage("This is not block!");
  30.             entOpts.AddAllowedClass(typeof(BlockReference), true);
  31.  
  32.             PromptEntityResult entRes = ed.GetEntity(entOpts);
  33.             if (entRes.Status != PromptStatus.OK) return;
  34.  
  35.             ObjectId bTabRecId = ObjectId.Null;
  36.             Dictionary<string, object> blkDynProps = new Dictionary<string, object>();
  37.             Dictionary<string, string> attribs = new Dictionary<string, string>();
  38.  
  39.             using (Transaction tr = db.TransactionManager.StartTransaction())
  40.             {
  41.                 BlockReference bref = tr.GetObject
  42.                     (entRes.ObjectId, OpenMode.ForRead) as BlockReference;
  43.                 if (bref.IsDynamicBlock)
  44.                 {
  45.                     bTabRecId = bref.DynamicBlockTableRecord;
  46.                     foreach (DynamicBlockReferenceProperty dynProp
  47.                         in bref.DynamicBlockReferencePropertyCollection)
  48.                     {
  49.                         blkDynProps[dynProp.PropertyName] = dynProp.Value;
  50.                     }
  51.  
  52.                     foreach (ObjectId attRefId in bref.AttributeCollection)
  53.                     {
  54.                         AttributeReference attRef = tr.GetObject
  55.                             (attRefId, OpenMode.ForRead) as AttributeReference;
  56.                         attribs[attRef.Tag] = attRef.TextString;
  57.                     }
  58.                 }
  59.  
  60.                 tr.Commit();
  61.             }
  62.  
  63.             if (bTabRecId.IsNull || blkDynProps.Count == 0)
  64.             {
  65.                 ed.WriteMessage("\nBlock without dynamic props! Exit.");
  66.                 return;
  67.             }
  68.  
  69.             if (attribs.Count == 0)
  70.             {
  71.                 ed.WriteMessage("\nBlock without attribs! Exit.");
  72.                 return;
  73.             }
  74.  
  75.             string dir = Path.GetDirectoryName(adoc.Name);
  76.  
  77.             PromptSaveFileOptions saveFileOpt = new PromptSaveFileOptions("Drawing for save: ");
  78.             saveFileOpt.Filter = "Drawing (*.dwg)|*.dwg";
  79.             saveFileOpt.InitialDirectory = dir;
  80.             saveFileOpt.InitialFileName = $"DynBlkTarget{++counter}.dwg";
  81.             PromptFileNameResult saveFileRes = ed.GetFileNameForSave(saveFileOpt);
  82.             string newFilePath = saveFileRes.StringResult;
  83.  
  84.             PromptKeywordOptions keyOpts = new PromptKeywordOptions("\nUse transaction?");
  85.             keyOpts.Keywords.Add("Yes");
  86.             keyOpts.Keywords.Add("No");
  87.             keyOpts.Message += keyOpts.Keywords.GetDisplayString(true);
  88.  
  89.             PromptResult keyRes = ed.GetKeywords(keyOpts);
  90.             if (keyRes.Status != PromptStatus.OK) return;
  91.  
  92.             bool useTrans = keyRes.StringResult == "Yes";
  93.             using (Database newDb = new Database(true, false))
  94.             {
  95.                 ObjectIdCollection ids = new ObjectIdCollection();
  96.                 ids.Add(bTabRecId);
  97.                 IdMapping mapping = new IdMapping();
  98.                 newDb.WblockCloneObjects(ids, newDb.BlockTableId,
  99.                     mapping, DuplicateRecordCloning.Replace, false);
  100.  
  101.                 ObjectId newBTabRecId = mapping[bTabRecId].Value;
  102.  
  103.                 Transaction tr = useTrans ?
  104.                     newDb.TransactionManager.StartTransaction()
  105.                     : newDb.TransactionManager.StartOpenCloseTransaction();
  106.  
  107.                 ObjectId bRefId;
  108.  
  109.                 using (tr)
  110.                 {
  111.                     BlockReference blkRef = new BlockReference(Point3d.Origin, newBTabRecId);
  112.  
  113.                     ObjectId mSpaceId = SymbolUtilityServices.GetBlockModelSpaceId(newDb);
  114.                     BlockTableRecord mSpace = tr.GetObject
  115.                         (mSpaceId, OpenMode.ForWrite) as BlockTableRecord;
  116.                     bRefId = mSpace.AppendEntity(blkRef);
  117.                     tr.AddNewlyCreatedDBObject(blkRef, true);
  118.  
  119.                     BlockTableRecord blkRec = tr.GetObject
  120.                         (newBTabRecId, OpenMode.ForRead) as BlockTableRecord;
  121.  
  122.                     foreach (ObjectId attDefId in blkRec)
  123.                     {
  124.                         if (!attDefId.ObjectClass.Equals(AttDefRXCLass)) continue;
  125.  
  126.                         AttributeDefinition attDef = tr.GetObject
  127.                             (attDefId, OpenMode.ForRead) as AttributeDefinition;
  128.  
  129.                         if (!attDef.Constant)
  130.                         {
  131.                             AttributeReference attRef = new AttributeReference();
  132.                             attRef.SetAttributeFromBlock(attDef, blkRef.BlockTransform);
  133.                             if (!attDef.HasFields
  134.                                 && attribs.ContainsKey(attDef.Tag))
  135.                             {
  136.                                 attRef.TextString = attribs[attDef.Tag];
  137.                             }
  138.                             blkRef.AttributeCollection.AppendAttribute(attRef);
  139.                             tr.AddNewlyCreatedDBObject(attRef, true);
  140.                             // Атрибут должен быть закрыт перед
  141.                             // присвоением динамических свойств блоку
  142.                             if (!useTrans) attRef.Close();
  143.  
  144.                         }
  145.                     }
  146.  
  147.                     // BlockTableRecord нашего блока должна быть закрыта
  148.                     // перед присвоением динамических свойств блоку
  149.                     if (!useTrans) blkRec.Close();
  150.  
  151.                     DynamicBlockReferencePropertyCollection dynProps =
  152.                       blkRef.DynamicBlockReferencePropertyCollection;
  153.  
  154.                     foreach (DynamicBlockReferenceProperty dynProp in dynProps)
  155.                     {
  156.                         KeyValuePair<string, object> propData = blkDynProps
  157.                             .FirstOrDefault(item => item.Key.Equals
  158.                             (dynProp.PropertyName, StringComparison.InvariantCultureIgnoreCase));
  159.                         if (propData.Value != null && dynProp.PropertyName != "Origin")
  160.                         {
  161.                             try
  162.                             {
  163.                                 dynProp.Value = propData.Value;
  164.                             }
  165.                             catch (System.Exception ex)
  166.                             {
  167.                                 Application.DocumentManager.MdiActiveDocument.
  168.                                   Editor.WriteMessage("\n{0}", ex);
  169.                             }
  170.                         }
  171.                     }
  172.  
  173.                     tr.Commit();
  174.                 }
  175.  
  176.                 // Дополнительная обработка атрибутов, ссылающихся
  177.                 // полем на значения динпараметров блока
  178.  
  179.                 ObjectId bTabRecId1;
  180.                 ObjectId[] attRefIds;
  181.                 Matrix3d blkTransform;
  182.  
  183.                 using (BlockReference blkRef = bRefId.Open(OpenMode.ForRead) as BlockReference)
  184.                 {
  185.                     bTabRecId1 = blkRef.BlockTableRecord;
  186.                     attRefIds = blkRef.AttributeCollection.Cast<ObjectId>().ToArray();
  187.                     blkTransform = blkRef.BlockTransform;
  188.                 }
  189.  
  190.                 Dictionary<string, ObjectId> attDefDict = new Dictionary<string, ObjectId>();
  191.  
  192.                 using (BlockTableRecord blkTabRec = bTabRecId1.Open(OpenMode.ForRead) as BlockTableRecord)
  193.                 {
  194.                     ObjectId[] attDefIds = blkTabRec.Cast<ObjectId>().Where(id => id.ObjectClass.Equals(AttDefRXCLass)).ToArray();
  195.                     foreach (ObjectId attDefId in attDefIds)
  196.                     {
  197.                         using (AttributeDefinition attDef = attDefId.Open(OpenMode.ForRead) as AttributeDefinition)
  198.                         {
  199.                             attDefDict[attDef.Tag] = attDefId;
  200.                         }
  201.                     }
  202.                 }
  203.  
  204.                 foreach (ObjectId attRefId in attRefIds)
  205.                 {
  206.                     using (AttributeReference attRef = attRefId.Open(OpenMode.ForRead) as AttributeReference)
  207.                     {
  208.                         if (attRef.HasFields && attDefDict.ContainsKey(attRef.Tag))
  209.                         {
  210.                             using (AttributeDefinition attDef = attDefDict[attRef.Tag].Open(OpenMode.ForRead) as AttributeDefinition)
  211.                             {
  212.                                 attRef.UpgradeOpen();
  213.                                 attRef.SetAttributeFromBlock(attDef, blkTransform);
  214.                                 attRef.DowngradeOpen();
  215.                             }
  216.                         }
  217.                     }
  218.                 }
  219.  
  220.                 newDb.SaveAs(newFilePath, DwgVersion.Current);
  221.             }
  222.  
  223.             Document newDoc = Application.DocumentManager.Open(newFilePath, false);
  224.             Application.DocumentManager.MdiActiveDocument = newDoc;
  225.         }
  226.     }
  227. }
  228.  
А вот вторую проблему никак не победить пока. Один-единственный атрибут реального, не тестового блока (их там с полтора десятка) после экспорта в другой чертеж "уползает" то влево, то вправо. И, что самое обидное, никак не получается воспроизвести это поведение на тестовом блоке.

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Получилось создать тестовый блок, на котором воспроизводится проблема №2 из предыдущего сообщения.
Видео:

Никак не получается одолеть эту напасть. Может быть, у вас будут какие-нибудь идеи?

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
В итоге, Google и Kean Walmsley помогли решить этот вопрос. Ответ тут, под заголовком "Update 2": http://through-the-interface.typepad.com/through_the_interface/2007/07/updating-a-sp-1.html?cid=6a00d83452464869e2010536eec215970b:
Цитировать
The above code does not realign attributes after editing their values: if your attributes are anything other than left-justified, you will need to make a call to AdjustAlignment on the attribute reference after editing it.
There's a trick to this: you need to make sure the working database is set to the drawing you're working on, as well as passing it as an argument to the function.
You could set the working database early in the code, or insert this code to do it locally (the choice is yours):
Код - C# [Выбрать]
  1.   ar.TextString = attbValue;
  2.   // Begin alignment code
  3.   Database wdb = HostApplicationServices.WorkingDatabase;
  4.   HostApplicationServices.WorkingDatabase = db;
  5.   ar.AdjustAlignment(db);
  6.   HostApplicationServices.WorkingDatabase = wdb;
  7.   // End alignment code
  8.   ar.DowngradeOpen();
I've left the line before and the line after in the above snippet, so it should be clear where the code needs inserting.
« Последнее редактирование: 11-07-2019, 17:40:26 от Дмитрий Загорулькин »

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
В итоге, Google и Kean Walmsley помогли решить этот вопрос. Ответ тут, под заголовком "Update 2": http://through-the-interface.typepad.com/through_the_interface/2007/07/updating-a-sp-1.html?cid=6a00d83452464869e2010536eec215970b
А ведь мы это когда-то на форуме обсуждали. Это касается не только атрибутов, но и текстов, размеров и т.д.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Владимир Шу

  • ADN Club
  • *****
  • Сообщений: 611
  • Карма: 155
    • ПГСу Бложик
По совету Димы (https://adn-cis.org/forum/index.php?topic=9225.msg48021#msg48021 ), посмотрел эту тему.
Взял код из 7 сообщения и слегка доработал напильником, убрав атрибуты, в блоках с которыми я работаю их нет.

Собственно вот код:
Код - C# [Выбрать]
  1. using Autodesk.AutoCAD.ApplicationServices;
  2. using Autodesk.AutoCAD.DatabaseServices;
  3. using Autodesk.AutoCAD.EditorInput;
  4. using Autodesk.AutoCAD.Geometry;
  5. using Autodesk.AutoCAD.Runtime;
  6. using System;
  7. using System.Collections.Generic;
  8. using System.IO;
  9. using System.Linq;
  10.  
  11. #pragma warning disable 0618
  12.  
  13. namespace ADN_DZ_BlockCopy
  14. {
  15.   public class DynBlockTest
  16.   {
  17.     static int counter = 0;
  18.  
  19.     [CommandMethod("xxx")]
  20.     public void InsertAndSettings()
  21.     {
  22.       Document adoc = Application.DocumentManager.MdiActiveDocument;
  23.       Editor ed = adoc.Editor;
  24.       Database db = adoc.Database;
  25.  
  26.       PromptEntityOptions entOpts = new PromptEntityOptions("\nSelect dynamic block: ");
  27.       entOpts.SetRejectMessage("This is not block!");
  28.       entOpts.AddAllowedClass(typeof(BlockReference), true);
  29.  
  30.       PromptEntityResult entRes = ed.GetEntity(entOpts);
  31.       if (entRes.Status != PromptStatus.OK) return;
  32.  
  33.       ObjectId bTabRecId = ObjectId.Null;
  34.       Dictionary<string, object> blkDynProps = new Dictionary<string, object>();
  35.       Dictionary<string, string> attribs = new Dictionary<string, string>();
  36.  
  37.       using (Transaction tr = db.TransactionManager.StartTransaction())
  38.       {
  39.         BlockReference bref = tr.GetObject
  40.             (entRes.ObjectId, OpenMode.ForRead) as BlockReference;
  41.         if (bref.IsDynamicBlock)
  42.         {
  43.           bTabRecId = bref.DynamicBlockTableRecord;
  44.           foreach (DynamicBlockReferenceProperty dynProp
  45.               in bref.DynamicBlockReferencePropertyCollection)
  46.           {
  47.             blkDynProps[dynProp.PropertyName] = dynProp.Value;
  48.           }
  49.         }
  50.         tr.Commit();
  51.       }
  52.  
  53.       if (bTabRecId.IsNull || blkDynProps.Count == 0)
  54.       {
  55.         ed.WriteMessage("\nBlock without dynamic props! Exit.");
  56.         return;
  57.       }
  58.  
  59.       string dir = Path.GetDirectoryName(adoc.Name);
  60.  
  61.       PromptSaveFileOptions saveFileOpt = new PromptSaveFileOptions("Drawing for save: ");
  62.       saveFileOpt.Filter = "Drawing (*.dwg)|*.dwg";
  63.       saveFileOpt.InitialDirectory = dir;
  64.       saveFileOpt.InitialFileName = $"DynBlkTarget{++counter}.dwg";
  65.       PromptFileNameResult saveFileRes = ed.GetFileNameForSave(saveFileOpt);
  66.       string newFilePath = saveFileRes.StringResult;
  67.  
  68.       PromptKeywordOptions keyOpts = new PromptKeywordOptions("\nUse transaction?");
  69.       keyOpts.Keywords.Add("Yes");
  70.       keyOpts.Keywords.Add("No");
  71.       keyOpts.Message += keyOpts.Keywords.GetDisplayString(true);
  72.  
  73.       PromptResult keyRes = ed.GetKeywords(keyOpts);
  74.       if (keyRes.Status != PromptStatus.OK) return;
  75.  
  76.       bool useTrans = keyRes.StringResult == "Yes";
  77.       using (Database newDb = new Database(true, false))
  78.       {
  79.         ObjectIdCollection ids = new ObjectIdCollection();
  80.         ids.Add(bTabRecId);
  81.         IdMapping mapping = new IdMapping();
  82.         newDb.WblockCloneObjects(ids, newDb.BlockTableId,
  83.             mapping, DuplicateRecordCloning.Replace, false);
  84.  
  85.         ObjectId newBTabRecId = mapping[bTabRecId].Value;
  86.  
  87.         Transaction tr = useTrans ?
  88.             newDb.TransactionManager.StartTransaction()
  89.             : newDb.TransactionManager.StartOpenCloseTransaction();
  90.  
  91.         ObjectId bRefId;
  92.  
  93.         using (tr)
  94.         {
  95.           BlockReference blkRef = new BlockReference(Point3d.Origin, newBTabRecId);
  96.  
  97.           ObjectId mSpaceId = SymbolUtilityServices.GetBlockModelSpaceId(newDb);
  98.           BlockTableRecord mSpace = tr.GetObject
  99.               (mSpaceId, OpenMode.ForWrite) as BlockTableRecord;
  100.           bRefId = mSpace.AppendEntity(blkRef);
  101.           tr.AddNewlyCreatedDBObject(blkRef, true);
  102.  
  103.           BlockTableRecord blkRec = tr.GetObject
  104.               (newBTabRecId, OpenMode.ForRead) as BlockTableRecord;
  105.  
  106.           // BlockTableRecord нашего блока должна быть закрыта
  107.           // перед присвоением динамических свойств блоку
  108.           if (!useTrans) blkRec.Close();
  109.  
  110.           DynamicBlockReferencePropertyCollection dynProps =
  111.             blkRef.DynamicBlockReferencePropertyCollection;
  112.  
  113.           foreach (DynamicBlockReferenceProperty dynProp in dynProps)
  114.           {
  115.             KeyValuePair<string, object> propData = blkDynProps
  116.                 .FirstOrDefault(item => item.Key.Equals
  117.                 (dynProp.PropertyName, StringComparison.InvariantCultureIgnoreCase));
  118.             if (propData.Value != null && dynProp.PropertyName != "Origin")
  119.             {
  120.               try
  121.               {
  122.                 dynProp.Value = propData.Value;
  123.               }
  124.               catch (System.Exception ex)
  125.               {
  126.                 Application.DocumentManager.MdiActiveDocument.
  127.                   Editor.WriteMessage("\n{0}", ex);
  128.               }
  129.             }
  130.           }
  131.           tr.Commit();
  132.         }
  133.         newDb.SaveAs(newFilePath, DwgVersion.Current);
  134.       }
  135.       Document newDoc = Application.DocumentManager.Open(newFilePath, false);
  136.       Application.DocumentManager.MdiActiveDocument = newDoc;
  137.     }
  138.   }
  139. }

Во вложение файл с несколькими блоками. Существенного отличия в блоках я не вижу.
Если попытаться с помощью кода скопировать любой блок под зеленым текстом, то все копируется.
Если попытаться скопировать блок под красным текстом, автокад падает.

Если блок под красным текстом ресетнуть и динамические свойства не трогать, то блок нормально копируется.
Если блок под красным текстом ресетнуть и изменить только дин. св-во "k", то блок нормально копируется.
Если блок под красным текстом ресетнуть и изменить любое дин. св-во, кроме "k", то автокад падает.

Собственно вопрос, что не так с этим блоком и как поменять код, что бы автокад не падал?
Код падает и на ADT 2017 и по отзыву пользователя на чистом 2021 автокаде так же падает.

ЗЫ.
Собственно из-за этого блока и не работал Прогресс бар в указанной выше теме.

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
А если вот такой метод попробовать? https://adn-cis.org/forum/index.php?topic=9353.msg39241#msg39241
Это сейчас мой основной по вставке блоков, пока сбоев вроде не давал.

Оффлайн Владимир Шу

  • ADN Club
  • *****
  • Сообщений: 611
  • Карма: 155
    • ПГСу Бложик
Это сейчас мой основной по вставке блоков, пока сбоев вроде не давал.
Увы. Вот код с помощью которого вызываю метод CreateBlockReference() (строчки 60, 61), поведение точно такое же, на красном падает.
Код - C# [Выбрать]
  1. static int counter = 0;
  2.     [CommandMethod("zzz")]
  3.     public void InsertAndSettingsZZZ()
  4.     {
  5.       Document adoc = Application.DocumentManager.MdiActiveDocument;
  6.       Editor ed = adoc.Editor;
  7.       Database db = adoc.Database;
  8.  
  9.       PromptEntityOptions entOpts = new PromptEntityOptions("\nSelect dynamic block: ");
  10.       entOpts.SetRejectMessage("This is not block!");
  11.       entOpts.AddAllowedClass(typeof(BlockReference), true);
  12.  
  13.       PromptEntityResult entRes = ed.GetEntity(entOpts);
  14.       if (entRes.Status != PromptStatus.OK) return;
  15.  
  16.       ObjectId bTabRecId = ObjectId.Null;
  17.       Dictionary<string, object> blkDynProps = new Dictionary<string, object>();
  18.       Dictionary<string, string> attribs = new Dictionary<string, string>();
  19.  
  20.       using (Transaction tr = db.TransactionManager.StartTransaction())
  21.       {
  22.         BlockReference bref = tr.GetObject
  23.             (entRes.ObjectId, OpenMode.ForRead) as BlockReference;
  24.         if (bref.IsDynamicBlock)
  25.         {
  26.           bTabRecId = bref.DynamicBlockTableRecord;
  27.           foreach (DynamicBlockReferenceProperty dynProp
  28.               in bref.DynamicBlockReferencePropertyCollection)
  29.           {
  30.             blkDynProps[dynProp.PropertyName] = dynProp.Value;
  31.           }
  32.         }
  33.         tr.Commit();
  34.       }
  35.  
  36.       if (bTabRecId.IsNull || blkDynProps.Count == 0)
  37.       {
  38.         ed.WriteMessage("\nBlock without dynamic props! Exit.");
  39.         return;
  40.       }
  41.  
  42.       string dir = Path.GetDirectoryName(adoc.Name);
  43.       PromptSaveFileOptions saveFileOpt = new PromptSaveFileOptions("Drawing for save: ");
  44.       saveFileOpt.Filter = "Drawing (*.dwg)|*.dwg";
  45.       saveFileOpt.InitialDirectory = dir;
  46.       saveFileOpt.InitialFileName = $"DynBlkTarget{++counter}.dwg";
  47.       PromptFileNameResult saveFileRes = ed.GetFileNameForSave(saveFileOpt);
  48.       string newFilePath = saveFileRes.StringResult;
  49.  
  50.       using (Database newDb = new Database(true, false))
  51.       {
  52.         ObjectIdCollection ids = new ObjectIdCollection();
  53.         ids.Add(bTabRecId);
  54.         IdMapping mapping = new IdMapping();
  55.         newDb.WblockCloneObjects(ids, newDb.BlockTableId,
  56.             mapping, DuplicateRecordCloning.Replace, false);
  57.  
  58.         ObjectId newBTabRecId = mapping[bTabRecId].Value;
  59.  
  60.         var bRefId = Class2.CreateBlockReference(Point3d.Origin,
  61.           newBTabRecId, newDb.CurrentSpaceId, newDb.LayerZero, 1, blkDynProps, attribs);
  62.  
  63.         newDb.SaveAs(newFilePath, DwgVersion.Current);
  64.       }
  65.       Document newDoc = Application.DocumentManager.Open(newFilePath, false);
  66.       Application.DocumentManager.MdiActiveDocument = newDoc;
  67.     }

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Хм... Есть подозрение, что проблема где-то в передаче определения блока в новую базу. Попробую вечером поковырять.

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Владимир Шу,
Обратил внимание на две вещи:
1) Количество динамических свойств у блока под красным текстом на два больше чем у двух других
2) В нём имеется два свойства, в имени которых есть пробел: "B_shiftMiddle X" и "B_shiftMiddle Y"
Возможно это как-то связано.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Владимир Шу

  • ADN Club
  • *****
  • Сообщений: 611
  • Карма: 155
    • ПГСу Бложик
Количество динамических свойств у блока под красным текстом на два больше чем у двух других
1. Которые я не трогаю и не меняю, т.к. они  в другой видимости, более того, залез и удалил это свойство, все равно падает.
2. Название дин. свойства "B_shiftMiddle", а Х и Y через пробел это автокад дорисовывает, это координаты точки.

Оффлайн Владимир Шу

  • ADN Club
  • *****
  • Сообщений: 611
  • Карма: 155
    • ПГСу Бложик
Хм... Есть подозрение, что проблема где-то в передаче определения блока в новую базу. Попробую вечером поковырять.
Неа, но есть нюанс....
Я еще порезал твой код и теперь размножаю этот блок внутри того же файла
И все работает, ровно до тех пор, пока не включишь прогресс бар.
т.е. в том виде в котором код в этом топике, блок размножается и автокад не падает, но стоит раскоментировать строки с прогресс баром и получаю не фатал, а уже надоевшую до боли картинку:


Т.е. есть какая то проблема и с переносом описания блока и с самим блоком что-то не так.

Код - C# [Выбрать]
  1.     [CommandMethod("aaa")]
  2.     public void InsertAndSettingsAAA()
  3.     {
  4.       Document adoc = Application.DocumentManager.MdiActiveDocument;
  5.       Editor ed = adoc.Editor;
  6.       Database db = adoc.Database;
  7.  
  8.       PromptEntityOptions entOpts = new PromptEntityOptions("\nSelect dynamic block: ");
  9.       entOpts.SetRejectMessage("This is not block!");
  10.       entOpts.AddAllowedClass(typeof(BlockReference), true);
  11.  
  12.       PromptEntityResult entRes = ed.GetEntity(entOpts);
  13.       if (entRes.Status != PromptStatus.OK) return;
  14.  
  15.       ObjectId bTabRecId = ObjectId.Null;
  16.       Dictionary<string, object> blkDynProps = new Dictionary<string, object>();
  17.       Dictionary<string, string> attribs = new Dictionary<string, string>();
  18.  
  19.       using (Transaction tr = db.TransactionManager.StartTransaction())
  20.       {
  21.         BlockReference bref = tr.GetObject
  22.             (entRes.ObjectId, OpenMode.ForRead) as BlockReference;
  23.         if (bref.IsDynamicBlock)
  24.         {
  25.           bTabRecId = bref.DynamicBlockTableRecord;
  26.           foreach (DynamicBlockReferenceProperty dynProp
  27.               in bref.DynamicBlockReferencePropertyCollection)
  28.           {
  29.             blkDynProps[dynProp.PropertyName] = dynProp.Value;
  30.           }
  31.         }
  32.         tr.Commit();
  33.       }
  34.  
  35.       if (bTabRecId.IsNull || blkDynProps.Count == 0)
  36.       {
  37.         ed.WriteMessage("\nBlock without dynamic props! Exit.");
  38.         return;
  39.       }
  40.       //var pm = new ProgressMeter();
  41.       //pm.SetLimit(50);
  42.       //pm.Start("Создание и редактирование блоков");
  43.  
  44.       for (int i = 0; i < 50; i++)
  45.       {
  46.         var bRefId = Class2.CreateBlockReference(new Point3d(0, i * 1000, 0),
  47.           bTabRecId, db.CurrentSpaceId, db.LayerZero, 1, blkDynProps, attribs);
  48.  
  49.         //pm.MeterProgress();
  50.         //System.Windows.Forms.Application.DoEvents();
  51.       }
  52.       //pm.Stop();
  53.     }

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Меня смущает массив внутри блока. Массив - относительно новый объект AutoCAD. А в проблемном блоке применяется динамическая операция к массиву. В двух других, насколько я понял, такого нет. Возможно, что это такой баг программной работы с динамическим блоком с массивом внутри, который участвует в динамических операциях.
Массив сам по себе - это тоже динамический блок, только особым образом самим автокадом обрабатывается:
((-1 . <Имя объекта: 15fa5d22ef0>) (0 . "INSERT") (5 . "114D7") (102 . "{ACAD_REACTORS") (330 . <Имя объекта: 15fa5d40890>) (102 . "}") (330 . <Имя объекта: 15f9439e1f0>) (100 . "AcDbEntity") (67 . 0) (410 . "Model") (8 . "0") (100 . "AcDbBlockReference") (2 . "*U69") (10 -7.10543e-15 35.0 0.0) (41 . 1.0) (42 . 1.0) (43 . 1.0) (50 . 0.0) (70 . 0) (71 . 0) (44 . 0.0) (45 . 0.0) (210 0.0 0.0 1.0))
И получается, что надо скомбинировать две динамики, да ещё и в неактивном документе, вне редактора. Думаю, проблема в этом.
Или, как вариант, проблема возникает при копировании определения блока. Получается, надо скопировать определение самого блока, плюс определение блока массива. Да ещё и с конкретной динамической вариацией. Возможно, API такого просто не умеет, либо делает неправильно.

Оффлайн Владимир Шу

  • ADN Club
  • *****
  • Сообщений: 611
  • Карма: 155
    • ПГСу Бложик
Дим, там рядом блок "Верхняя юбка B-B(Правая)", там тоже есть массив и этот блок работает нормально.

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
А в проблемном блоке применяется динамическая операция к массиву. В двух других, насколько я понял, такого нет.
Вот в чём может быть разница.
Можешь выложить готовый тестовый проект для воспроизведения бага? Попробую погонять отладкой.

Оффлайн Владимир Шу

  • ADN Club
  • *****
  • Сообщений: 611
  • Карма: 155
    • ПГСу Бложик
А может и из-за массива.... делал проект для форума и решил потестировать перед отправкой.... один из ранее работавших блоков отказался работать и теперь вешает автокад. Блин, как это работает!??!?!

Проект и тестовый файл прилагаю.


ЗЫ.
Залез ковыряться в блок.... я конечно тупенький, но КАК ЭТО СДЕЛАНО?!? Каким образом удалось связать пользовательские параметры динамического блока с настройками массива, еще и так, что бы это работало?!?

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Я тоже такое впервые вижу. А это сторонние блоки? Может быть, это какое-то недокументированное поведение массива внутри блока.

Оффлайн Владимир Шу

  • ADN Club
  • *****
  • Сообщений: 611
  • Карма: 155
    • ПГСу Бложик
Я не знаю, мне эти блоки прислали. Я спросил у пользователя, как это сделано, может расскажет.
Мне стоило не торопиться, а самому поискать: https://forum.dwg.ru/showthread.php?t=140841
Цитировать
Кратко: создать в редакторе блоков переменную и в массиве в величину шага вбить эту переменную вместо числа. Вводить потом в свойствах.

Создал по этой подсказке блок и автокад ложится.
Наверное можно сказать, что причину нашли, теперь вопрос что делать?
« Последнее редактирование: 19-04-2021, 08:03:58 от Владимир Шу »

Оффлайн Владимир Шу

  • ADN Club
  • *****
  • Сообщений: 611
  • Карма: 155
    • ПГСу Бложик
Александр Наумович, я догадываюсь, что силами нашего форума эту задачу не решить, собственно не могли бы Вы переправить этот вопрос в автодеск?
Чёртика выпустили из табакерки и этих блоков с каждым днем будет все больше и как то с ними нужно работать. Тестовый проект и файл с блоками выложены несколькими сообщениями ранее.

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Александр Наумович, я догадываюсь, что силами нашего форума эту задачу не решить, собственно не могли бы Вы переправить этот вопрос в автодеск?
Чёртика выпустили из табакерки и этих блоков с каждым днем будет все больше и как то с ними нужно работать. Тестовый проект и файл с блоками выложены несколькими сообщениями ранее.
Я могу переправить вопрос в ADN DevHelp при выполнении следующих условий:
1. Ты создаёшь тестовый проект с нуля (без никаких package, SafeOpen и т.д.) - никто с той стороны не будет разбираться с этим. Код должен быть максимально простым. Комментарии, если они нужны, на английском.
2. Проект должен быть для последних версий AutoCAD. Если ошибка не будет воспроизводится в AutoCAD 2022 - отправлять бесполезно. Это будет значить, что ошибку нашли и исправили и к старым версиям возвращаться не будут.
3. Ты объясняешь подробно что должно быть и что не так и записываешь видео при помощи Autodesk Screencast в одной из трех последних версий AutoCAD.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Владимир Шу

  • ADN Club
  • *****
  • Сообщений: 611
  • Карма: 155
    • ПГСу Бложик
Хорошо, за праздники подготовлю.
небольшое уточнение: Использовать официальный Nuget пакет так же нельзя?

Оффлайн Владимир Шу

  • ADN Club
  • *****
  • Сообщений: 611
  • Карма: 155
    • ПГСу Бложик
Если ошибка не будет воспроизводится в AutoCAD 2022 - отправлять бесполезно.
ОС: ставил с образа Win10_20H2_v2_Russian_x64.iso скаченного с сайта MS
Autocad: ставил с веб установщика AutoCAD_2022_English_Win_64bit_di_en-US_setup_webinstall.exe с 30 дневным тестом.

Ошибка не воспроизводится, код из 21 сообщения работает стабильно, хоть с прогресс баром, хоть без него, хоть с тестовым файлом, хоть с вновь созданным блоком. За два десятка прогонов и попыток, уронить автокад не удалось. Так что записывать видео не стал и вопрос с отправкой в ADN снимается. Увы.

И если я правильно понимаю, то пока единственный выход для меня, с моим 2017, это проверять определение блока на наличие в нем массива (bool = AssocArray.IsAssociativeArray(ObjectId)) и если он там есть, то информировать об этом пользователя и игнорировать эти блоки, но это как то не правильно, т.к. массив может не иметь связей с параметрами блока... а как проверить наличие связей я пока не понял, "будем искать" и буду благодарен за подсказки.

Оффлайн brook

  • ADN OPEN
  • Сообщений: 15
  • Карма: 0
Дмитрий Загорулькин,
а можно где-то посмотреть, как формируется  тип object для разных динамических свойств? я про вашу прекрасную функцию в этой теме, она мне всем подходит. она принимает на вход в том числе список значений динамического блока в виде словаря  Dictionary<string, object> dynamicPropsValues
насколько я понимаю, этот тип object может выглядеть по-разному для разных динамических свойств. мне нужно в основном растягивание Distance и параметры видимости, (но видимость меня заработала просто приведением типа, возможно это запрещённый приём).
как узнать, как формируется этот тип для разных динамических свойств?
или единственная возможность играть в угадайку свойствами "DynamicBlockReferenceProperty"? даже если я выясню, какие именно значения этих свойств мне нужны, я что-то не совсем догоняю, как мне сформировать object в каждом конкретном случае...

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
brook,
Допустимые типы, описываются свойством DynamicBlockReferenceProperty.PropertyTypeCode (которое соответствует свойству AcDbDynBlockReferenceProperty::propertyType в ObjectARX и соответственно имеет тип AcDb::DwgDataType):

Код - C++ [Выбрать]
  1. enum DwgDataType {
  2.   kDwgNull = 0,
  3.   kDwgReal = 1,
  4.   kDwgInt32 = 2,
  5.   kDwgInt16 = 3,
  6.   kDwgInt8 = 4,
  7.   kDwgText = 5,
  8.   kDwgBChunk = 6,
  9.   kDwgHandle = 7,
  10.   kDwgHardOwnershipId = 8,
  11.   kDwgSoftOwnershipId = 9,
  12.   kDwgHardPointerId = 10,
  13.   kDwgSoftPointerId = 11,
  14.   kDwg3Real = 12,
  15.   kDwgInt64 = 13,
  16.   kDwgNotRecognized = 19
  17. };
Ну а массив допустимых значений для свойства DynamicBlockReferenceProperty возвращает метод GetAllowedValues()
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Как узнать, как формируется этот тип для разных динамических свойств?
Я в отладке смотрел. Ставил точку остановки в том месте где код пробегался по коллекции динамических свойств блока и изучал где какой тип и какие значения.