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:
- Implement a command to collect RegAppId information for the active document
- Extend this command to work on a drawing not loaded in the editor
- Save our RegAppId information to some persistent location (XML)
- 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).