Counting the RegAppIds for a specific AutoCAD drawing and its external references using .NET

This post extends the code shown in the last – very similarly named – post, to work on a specified drawing, that – very importantly – does not get loaded into the AutoCAD editor. Step 2 in the list for this series:

  1. Implement a command to collect RegAppId information for the active document
  2. Extend this command to work on a drawing not loaded in the editor
  3. Save our RegAppId information to some persistent location (XML)
  4. Create a modified version of ScriptPro 2.0 (one of our Plugins of the Month) to call our command without opening the drawing

The code starts by prompting the user for the path to the main drawing to load (which will eventually be provided by the modified ScriptPro 2.0 application, so no need to use a dialog), before attempting to load the file into a side database and resolve any xrefs it contains. The main loop is as before with a new catch statement taking care of any exceptions thrown during drawing load.

Here's the updated C# code, with modified lines in red (and here's the updated source file):

    1 using Autodesk.AutoCAD.ApplicationServices;

    2 using Autodesk.AutoCAD.DatabaseServices;

    3 using Autodesk.AutoCAD.EditorInput;

    4 using Autodesk.AutoCAD.Runtime;

    5 using System.Collections.Generic;

    6 using System.IO;

    7 using System;

    8 

    9 namespace XrefRegApps

   10 {

   11   public class Commands

   12   {

   13     [CommandMethod("XRA")]

   14     public void ExternalReferenceRegisteredApps()

   15     {

   16       Document doc =

   17           Application.DocumentManager.MdiActiveDocument;

   18       Database db = doc.Database;

   19       Editor ed = doc.Editor;

   20 

   21       // Prompt the user for the path to a DWG to test

   22 

   23       PromptStringOptions pso =

   24         new PromptStringOptions(

   25           "\nEnter path to root drawing file: "

   26         );

   27       pso.AllowSpaces = true;

   28       PromptResult pr = ed.GetString(pso);

   29       if (pr.Status != PromptStatus.OK)

   30         return;

   31 

   32       if (!File.Exists(pr.StringResult))

   33       {

   34         ed.WriteMessage("\nFile does not exist.");

   35         return;

   36       }

   37 

   38       try

   39       {

   40         // Load the DWG into a side database

   41 

   42         Database mainDb = new Database(false, true);

   43         using (mainDb)

   44         {

   45           mainDb.ReadDwgFile(

   46             pr.StringResult,

   47             FileOpenMode.OpenForReadAndAllShare,

   48             true,

   49             null

   50           );

   51 

   52           // We need an additional step to resolve Xrefs

   53 

   54           mainDb.ResolveXrefs(false, false);

   55 

   56           // Get the XrefGraph for the specified database

   57 

   58           XrefGraph xg = mainDb.GetHostDwgXrefGraph(true);

   59 

   60           // Loop through the nodes in the graph

   61 

   62           for (int i = 0; i < xg.NumNodes; i++)

   63           {

   64             // Get each node and check its status

   65 

   66             XrefGraphNode xgn = xg.GetXrefNode(i);

   67 

   68             switch (xgn.XrefStatus)

   69             {

   70               // If Un*, print a message

   71 

   72               case XrefStatus.Unresolved:

   73                 ed.WriteMessage(

   74                   "\nUnresolved xref \"{0}\"", xgn.Name

   75                 );

   76                 break;

   77               case XrefStatus.Unloaded:

   78                 ed.WriteMessage(

   79                   "\nUnloaded xref \"{0}\"", xgn.Name

   80                 );

   81                 break;

   82               case XrefStatus.Unreferenced:

   83                 ed.WriteMessage(

   84                   "\nUnreferenced xref \"{0}\"", xgn.Name

   85                 );

   86                 break;

   87               case XrefStatus.Resolved:

   88               {

   89                 // If Resolved, get the RegAppTable

   90 

   91                 Database xdb = xgn.Database;

   92                 if (xdb != null)

   93                 {

   94                   Transaction tr =

   95                     xdb.TransactionManager.StartTransaction();

   96                   using (tr)

   97                   {

   98                     RegAppTable rat =

   99                       (RegAppTable)tr.GetObject(

  100                         xdb.RegAppTableId,

  101                         OpenMode.ForRead

  102                       );

  103 

  104                     // Collect the contained RegAppTableRecord

  105                     // names (i.e. the RegAppIds) in a list

  106 

  107                     List<String> ratIds = new List<string>();

  108                     foreach (ObjectId id in rat)

  109                     {

  110                       RegAppTableRecord ratr =

  111                         (RegAppTableRecord)tr.GetObject(

  112                           id,

  113                           OpenMode.ForRead

  114                         );

  115                       ratIds.Add(ratr.Name);

  116                     }

  117 

  118                     // Print the drawing information

  119                     // and the RegAppId count

  120 

  121                     ed.WriteMessage(

  122                       "\nDrawing \"{0}\" (\"{1}\") with {2}" +

  123                       " RegAppIds",

  124                       xgn.Name,

  125                       xdb.Filename,

  126                       ratIds.Count

  127                     );

  128 

  129                     // Even if only reading, commit the

  130                     // transaction (it's cheaper than aborting)

  131 

  132                     tr.Commit();

  133                   }

  134                 }

  135                 break;

  136               }

  137             }

  138           }

  139         }

  140       }

  141       catch (System.Exception ex)

  142       {

  143         ed.WriteMessage(

  144           "\nProblem reading/processing \"{0}\": {1}",

  145           pr.StringResult, ex.Message

  146         );

  147       }

  148     }

  149   }

  150 }

Here's what happens when we run our updated command, selecting the same DWG as in the previous post (without the need to load it):

Command: XRA

Enter path to root drawing file: C:\Program Files\Autodesk\AutoCAD 2011\Sample\Sheet Sets\Civil\Master Site Plan.dwg

Drawing "C:\Program Files\Autodesk\AutoCAD 2011\Sample\Sheet Sets\Civil\Master Site Plan.dwg" ("C:\Program Files\Autodesk\AutoCAD 2011\Sample\Sheet Sets\Civil\Master Site Plan.dwg") with 18 RegAppIds

Drawing "PB-BASE" ("C:\Program Files\Autodesk\AutoCAD 2011\Sample\Sheet Sets\Civil\PB-BASE.dwg") with 7 RegAppIds

Drawing "PB-EX41" ("C:\Program Files\Autodesk\AutoCAD 2011\Sample\Sheet Sets\Civil\PB-EX41.dwg") with 6 RegAppIds

Drawing "PB-EX61" ("C:\Program Files\Autodesk\AutoCAD 2011\Sample\Sheet Sets\Civil\PB-EX61.dwg") with 5 RegAppIds

You'll notice the "name" of the primary drawing is its full path: when we store this data in XML, we'll go through the additional step of extracting the filename (System.IO.Path.GetFileNameWithoutExtension() makes this easy).

Leave a Reply

Your email address will not be published. Required fields are marked *