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

ADN Club => AutoCAD .NET API => Тема начата: Андрей Бушман от 07-10-2014, 13:56:33

Название: Аудит после переключения на созданный лист в конкретном файле
Отправлено: Андрей Бушман от 07-10-2014, 13:56:33
AutoCAD 2012 Enu x64 SP2
Windows 7 x64 Rus SP1

Имеется следующий код "Hello, World!":
Код - C# [Выбрать]
  1. /* © Андрей Бушман, 2014
  2.  * Commands.cs
  3.  */
  4. using System;
  5. using System.Collections.Generic;
  6. using System.Linq;
  7. using System.Text;
  8.  
  9. #if AUTOCAD
  10. using cad = Autodesk.AutoCAD.ApplicationServices.Application;
  11. using Ap = Autodesk.AutoCAD.ApplicationServices;
  12. using Db = Autodesk.AutoCAD.DatabaseServices;
  13. using Ed = Autodesk.AutoCAD.EditorInput;
  14. using Gm = Autodesk.AutoCAD.Geometry;
  15. using Rt = Autodesk.AutoCAD.Runtime;
  16. using Hs = Autodesk.AutoCAD.DatabaseServices.HostApplicationServices;
  17. using Us = Autodesk.AutoCAD.DatabaseServices.SymbolUtilityServices;
  18. #endif
  19.  
  20. [assembly: Rt.CommandClass(typeof(Bushman.CAD.Samples.LayoutSample.Commands))]
  21.  
  22. namespace Bushman.CAD.Samples.LayoutSample {
  23.  
  24.     public sealed class Commands {
  25.         [Rt.CommandMethod("test", Rt.CommandFlags.Modal)]
  26.         public void Test() {
  27.             Ap.Document doc = cad.DocumentManager.MdiActiveDocument;
  28.             if (null == doc)
  29.                 return;
  30.             using (doc.LockDocument()) {
  31.                 Ed.Editor ed = doc.Editor;
  32.                 Db.Database db = doc.Database;
  33.                 Db.LayoutManager lm = Db.LayoutManager.Current;
  34.  
  35.                 String layout_name = "My_Layout";
  36.  
  37.                 if (!lm.GetLayoutId(layout_name).IsNull) {
  38.                     ed.WriteMessage("Лист \"{0}\" уже существует. Операция прервана.\n",
  39.                         layout_name);
  40.                     return;
  41.                 }
  42.                 Db.ObjectId layout_id = lm.CreateLayout(layout_name);
  43.                 using (Db.Transaction tr = db.TransactionManager.StartTransaction()) {
  44.                     Db.Layout layout = tr.GetObject(layout_id, Db.OpenMode.ForWrite)
  45.                         as Db.Layout;
  46.                     layout.Initialize();
  47.                     lm.CurrentLayout = layout_name;
  48.                     tr.Commit();
  49.                 }
  50.             }
  51.         }
  52.     }
  53. }
Если запускаю его в новом чертеже, созданном на основе шаблона acadiso.dwt, то после выполнения команды audit никаких ошибок не найдено.
Однако имеется некий пользовательский файл (переданный мне для тестирования), в котором по завершению работы команды test, команда audit находит две ошибки:
Цитировать
Command: audit
Fix any errors detected? [Yes/No] <N>:
Auditing Header
Auditing Tables
Auditing Entities Pass 1
Pass 1 300     objects auditedAcDbViewport(76A60)
           Paperspace vport layer Not "0"               "0"
AcDbViewport(76A60)               was not repaired.

Auditing Entities Pass 2

Pass 2 300     objects auditedAcDbViewport(76A60)
           Paperspace vport layer Not "0"               "0"
AcDbViewport(76A60)               was not repaired.
Auditing Blocks
 2       Blocks audited
Total errors found 2 fixed 0
Erased 0 objects
До запуска команды test в этом чертеже аудит ошибок не находит. Файл прикреплён ниже и содержит прокси-графику. Recovery находит и исправляет в файле одну ошибку, не выявленную аудитом (как я понял - объекты СПДС GraphiCS), однако после test по прежнему аудит находит две ошибки.

У кого какие идеи по поводу причины такого поведения?

Спасибо.
Название: Re: Аудит после переключения на созданный лист в конкретном файле
Отправлено: Александр Ривилис от 07-10-2014, 14:34:07
Не знаю с чем это связано, но переключение текущего слоя с "Размеры" на "0" приводит к тому, что после этого программа отрабатывает нормально и после неё _AUDIT ошибок не находит. Предварительно файл я его переименовал (у меня его имя начиналось с пробела) и удалил прокси-объекты (их было три штуки).
Название: Re: Аудит после переключения на созданный лист в конкретном файле
Отправлено: Андрей Бушман от 07-10-2014, 15:06:30
Предварительно файл я его переименовал (у меня его имя начиналось с пробела) и удалил прокси-объекты (их было три штуки).
Я не трогаю прокси. Но если предварительно переключиться на слой 0, то аудит действительно не находит ошибок.
Название: Re: Аудит после переключения на созданный лист в конкретном файле
Отправлено: Дмитрий Загорулькин от 07-10-2014, 15:08:58
Ошибка не возникает, если убрать строчку:
Код - C# [Выбрать]
  1. layout.Initialize();
Название: Re: Аудит после переключения на созданный лист в конкретном файле
Отправлено: Александр Ривилис от 07-10-2014, 15:12:35
Ошибка не возникает, если убрать строчку:
Код - C#: [Выделить]

    layout.Initialize();
Как раз layout.Initialize() создаёт ViewPort и помещает его на текущий слой, а _AUDIT это не нравится - он хочет чтобы ViewPort был на слое "0".
Название: Re: Аудит после переключения на созданный лист в конкретном файле
Отправлено: Дмитрий Загорулькин от 07-10-2014, 15:16:14
Этот ViewPort кривой какой-то создается. Я попробовал выделить его лиспом по метке, которую выдает AUDIT - подсветились четыре ручки в пустом месте листа. При этом, самого видового экрана не было видно.
Может быть, нельзя в одной транзакции инициализировать и делать лист текущим?
Название: Re: Аудит после переключения на созданный лист в конкретном файле
Отправлено: Александр Ривилис от 07-10-2014, 15:19:57
Может быть, нельзя в одной транзакции инициализировать и делать лист текущим?
Вполне возможно, что ты прав.
Название: Re: Аудит после переключения на созданный лист в конкретном файле
Отправлено: Дмитрий Загорулькин от 07-10-2014, 15:21:57
Не, не угадал. Попробовал вынести из транзакции назначение нового листа текущим - не помогло.
Название: Re: Аудит после переключения на созданный лист в конкретном файле
Отправлено: Андрей Бушман от 07-10-2014, 15:23:32
Вполне возможно, что ты прав.
Похоже, что не прав:
Код - C# [Выбрать]
  1. Db.ObjectId layout_id = lm.CreateLayout(layout_name);
  2. using (Db.Transaction tr = db.TransactionManager.StartTransaction()) {
  3.     Db.Layout layout = tr.GetObject(layout_id, Db.OpenMode.ForWrite)
  4.         as Db.Layout;
  5.     layout.Initialize();
  6.     // lm.CurrentLayout = layout_name;
  7.     tr.Commit();
  8. }
  9.  
  10. using (Db.Transaction tr = db.TransactionManager.StartTransaction()) {
  11.     Db.Layout layout = tr.GetObject(layout_id, Db.OpenMode.ForWrite)
  12.         as Db.Layout;                    
  13.     lm.CurrentLayout = layout_name;
  14.     tr.Commit();
  15. }
не помогло.
Название: Re: Аудит после переключения на созданный лист в конкретном файле
Отправлено: Андрей Бушман от 07-10-2014, 15:25:24
Этот ViewPort кривой какой-то создается. Я попробовал выделить его лиспом по метке, которую выдает AUDIT - подсветились четыре ручки в пустом месте листа.
Да, что-то подобное и я наблюдал один раз. Затем я в настройках диалогового окна Options отключил автоматическое создание видового экрана при создании нового листа. Но это не помогло - аудит всё равно ругается. Поэтому и создал эту тему.
Название: Re: Аудит после переключения на созданный лист в конкретном файле
Отправлено: Андрей Бушман от 07-10-2014, 15:28:10
Похоже, что при помощи этого файла, невзначай, вскрылся какой-то очередной баг API.
Название: Re: Аудит после переключения на созданный лист в конкретном файле
Отправлено: Андрей Бушман от 07-10-2014, 15:33:21
Вот такой код в обозначенном файле ошибок аудита не даёт:
Код - C# [Выбрать]
  1. /* © Андрей Бушман, 2014
  2.  * Commands.cs
  3.  */
  4. using System;
  5. using System.Collections.Generic;
  6. using System.Linq;
  7. using System.Text;
  8.  
  9. #if AUTOCAD
  10. using cad = Autodesk.AutoCAD.ApplicationServices.Application;
  11. using Ap = Autodesk.AutoCAD.ApplicationServices;
  12. using Db = Autodesk.AutoCAD.DatabaseServices;
  13. using Ed = Autodesk.AutoCAD.EditorInput;
  14. using Gm = Autodesk.AutoCAD.Geometry;
  15. using Rt = Autodesk.AutoCAD.Runtime;
  16. using Hs = Autodesk.AutoCAD.DatabaseServices.HostApplicationServices;
  17. using Us = Autodesk.AutoCAD.DatabaseServices.SymbolUtilityServices;
  18. #endif
  19.  
  20. [assembly: Rt.CommandClass(typeof(Bushman.CAD.Samples.LayoutSample.Commands))]
  21.  
  22. namespace Bushman.CAD.Samples.LayoutSample {
  23.  
  24.     public sealed class Commands {
  25.         [Rt.CommandMethod("test", Rt.CommandFlags.Modal)]
  26.         public void Test() {
  27.             Ap.Document doc = cad.DocumentManager.MdiActiveDocument;
  28.             if (null == doc)
  29.                 return;
  30.             using (doc.LockDocument()) {
  31.                 Ed.Editor ed = doc.Editor;
  32.                 Db.Database db = doc.Database;
  33.                 Db.LayoutManager lm = Db.LayoutManager.Current;
  34.  
  35.                 String layout_name = "My_Layout";
  36.  
  37.                 if (!lm.GetLayoutId(layout_name).IsNull) {
  38.                     ed.WriteMessage("Лист \"{0}\" уже существует. Операция прервана.\n",
  39.                         layout_name);
  40.                     return;
  41.                 }
  42.                 Db.ObjectId layout_id = lm.CreateLayout(layout_name);
  43.                 using (Db.Transaction tr = db.TransactionManager.StartTransaction()) {
  44.                     Db.Layout layout = tr.GetObject(layout_id, Db.OpenMode.ForWrite)
  45.                         as Db.Layout;
  46.                     Db.ObjectId prew_layer_id = db.Clayer;
  47.                     db.Clayer = db.LayerZero;
  48.                     layout.Initialize();
  49.                     db.Clayer = prew_layer_id;
  50.                     lm.CurrentLayout = layout_name;
  51.                     tr.Commit();
  52.                 }
  53.             }
  54.         }
  55.     }
  56. }
Название: Re: Аудит после переключения на созданный лист в конкретном файле
Отправлено: Андрей Бушман от 07-10-2014, 15:43:23
В 2015-м AutoCAD ситуация та же самая.
Название: Re: Аудит после переключения на созданный лист в конкретном файле
Отправлено: Дмитрий Загорулькин от 07-10-2014, 15:43:49
Ошибок AUDITа не дает, но лист пустой показывает, пока не переключишься на другой и не вернешься в него снова.
Попробуй без инициализации - увидишь разницу.
Название: Re: Аудит после переключения на созданный лист в конкретном файле
Отправлено: Андрей Бушман от 07-10-2014, 15:46:46
но лист пустой показывает, пока не переключишься на другой и не вернешься в него снова.
у меня он пустой и после переключения между листами.
Цитировать
Попробуй без инициализации - увидишь разницу.
в 2015-м разницы не вижу (сейчас перенастроен проект на эту версию).
Название: Re: Аудит после переключения на созданный лист в конкретном файле
Отправлено: Дмитрий Загорулькин от 07-10-2014, 15:55:04
Ну может быть дело в том, что я в Civil проверяю. У меня так:
С инициализацией:
https://screencast.autodesk.com/main/details/a0f449ab-6b81-414c-8963-0e43773f80cf
Без нее:
https://screencast.autodesk.com/main/details/c4e4ae9c-d406-42a5-a444-09c864b92525
Название: Re: Аудит после переключения на созданный лист в конкретном файле
Отправлено: Александр Ривилис от 07-10-2014, 21:46:25
Балдею я от этого Civil 3D 2015. Обрати внимание на количество проверенных командой _AUDIT объектов и количеством из них в пространстве модели.
Название: Re: Аудит после переключения на созданный лист в конкретном файле
Отправлено: Александр Ривилис от 08-10-2014, 01:35:11
Отправил запрос в ADN DevHelp. Полностью проект, картинку с _AUDIT до запуска команды TEST, картинку с _AUDIT после команды и сам чертеж. Ну и просьбу пояснить что не так, и как в коде можно избежать появления таких ошибок.
Название: Re: Аудит после переключения на созданный лист в конкретном файле
Отправлено: Андрей Бушман от 08-10-2014, 10:23:47
Спасибо. :)
Название: Re: Аудит после переключения на созданный лист в конкретном файле
Отправлено: Александр Ривилис от 16-10-2014, 15:25:48
Предложили такой выход из ситуации:
Код - C# [Выбрать]
  1. AcDb.ObjectId layout_id = lm.CreateLayout(layout_name); // Create New Layout
  2.  
  3. lm.CurrentLayout = layout_name;
  4.  
  5. using (AcDb.Transaction tr = db.TransactionManager.StartTransaction())
  6. {
  7.   AcDb.Layout layout = tr.GetObject(layout_id, AcDb.OpenMode.ForRead) as AcDb.Layout;
  8.   ///////////////////////////////////////////
  9.   // Now check layout is initialized or not.
  10.   // If not then initialize it
  11.   ///////////////////////////////////////////
  12.   if (layout.GetViewports().Count == 0) {
  13.     layout.UpgradeOpen();
  14.     layout.Initialize();
  15.   }
  16.   tr.Commit();
  17. }
Т.е. сначала переключится на новый лист, а уже потом его инициализировать. Насколько работоспособен этот workaround я еще не проверял. Я попросил уточнить что именно в этом чертеже такое особенное, что приводит к ошибкам. Цель - иметь возможность заранее проверить приведет ли инициализация к ошибке или нет.