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.Text;
7 using System.Xml;
8 using System.Xml.Serialization;
9 using System.IO;
10 using System;
11
12 namespace XrefRegApps
13 {
14 [XmlRoot("RegAppData")]
15
public
class
RegAppData
16 {
17
// The name of our drawing
18
19
private
string _name;
20
21 [XmlAttribute("Name")]
22
public
string Name
23 {
24
get { return _name; }
25
set { _name = value; }
26 }
27
28
// The location of our drawing
29
30
private
string _dwg;
31
32 [XmlAttribute("File")]
33
public
string File
34 {
35
get { return _dwg; }
36
set { _dwg = value; }
37 }
38
39
private
string _dwgVersion;
40
41 [XmlAttribute("DwgVersion")]
42
public
string DwgVersion
43 {
44
get { return _dwgVersion; }
45
set { _dwgVersion = value; }
46 }
47
48
// The list of our drawing's Registered Application IDs
49
50
private
List<string> _regAppIds = new
List<string>();
51
52 [XmlArrayItem("RegAppId")]
53
public
List<string> RegAppIds
54 {
55
get { return _regAppIds; }
56
set { _regAppIds = value; }
57 }
58
59
public
void AddRegAppId(string id)
60 {
61
if (!_regAppIds.Contains(id))
62 _regAppIds.Add(id);
63 }
64 }
65
66
public
class
Commands
67 {
68
private
const
string regAppDataXml = "c:\\RegAppData.xml";
69
70
private
void SerializeRegAppData(
71
Dictionary<string, RegAppData> dict
72 )
73 {
74
if (dict.Count > 0)
75 {
76
// No direct way to serialize a dictionary to XML,
77
// so we'll create a list from it and serialize that
78
79
List<RegAppData> regData =
80
new
List<RegAppData>(dict.Count);
81
foreach (KeyValuePair<string, RegAppData> kv in dict)
82 {
83 regData.Add(kv.Value);
84 }
85
86
// Serialize our list to the specified XML file
87
88
XmlSerializer xs =
89
new
XmlSerializer(typeof(List<RegAppData>));
90
XmlTextWriter xw =
91
new
XmlTextWriter(regAppDataXml, Encoding.UTF8);
92 xw.WriteProcessingInstruction(
93
"xml-stylesheet",
94
"type=\"text/xsl\" href=\"RegAppData.xslt\""
95 );
96 xs.Serialize(xw, regData);
97 xw.Close();
98 }
99 }
100
101
// Read and return the previous Registered Application data
102
// from our stored XML file
103
104
private
Dictionary<string, RegAppData>
105 DeserializeRegAppData()
106 {
107
if (File.Exists(regAppDataXml))
108 {
109
XmlSerializer xs =
110
new
XmlSerializer(typeof(List<RegAppData>));
111
XmlTextReader xr = new
XmlTextReader(regAppDataXml);
112
if (xs.CanDeserialize(xr))
113 {
114
// No direct way to serialize a dictionary to XML,
115
// so we'll read a list and populate a dictionary
116
// from it
117
118
List<RegAppData> regData =
119 (List<RegAppData>)xs.Deserialize(xr);
120 xr.Close();
121
Dictionary<string, RegAppData> dict =
122
new
Dictionary<string, RegAppData>();
123
foreach (RegAppData rad in regData)
124 {
125 dict.Add(rad.File, rad);
126 }
127
return dict;
128 }
129 }
130
return
new
Dictionary<string, RegAppData>();
131 }
132
133 [CommandMethod("XRA")]
134
public
void ExternalReferenceRegisteredApps()
135 {
136
Document doc =
137
Application.DocumentManager.MdiActiveDocument;
138
Database db = doc.Database;
139
Editor ed = doc.Editor;
140
141
// Prompt the user for the path to a DWG to test
142
143
PromptStringOptions pso =
144
new
PromptStringOptions(
145
"\nEnter path to root drawing file: "
146 );
147 pso.AllowSpaces = true;
148
PromptResult pr = ed.GetString(pso);
149
if (pr.Status != PromptStatus.OK)
150
return;
151
152
if (!File.Exists(pr.StringResult))
153 {
154 ed.WriteMessage("\nFile does not exist.");
155
return;
156 }
157
158
try
159 {
160
// We start by reading any existing RegApp data
161
// from XML
162
163
Dictionary<string, RegAppData> regData =
164 DeserializeRegAppData();
165
166
// Load the DWG into a side database
167
168
Database mainDb = new
Database(false, true);
169
using (mainDb)
170 {
171 mainDb.ReadDwgFile(
172 pr.StringResult,
173
FileOpenMode.OpenForReadAndAllShare,
174
true,
175
null
176 );
177
178
// We need an additional step to resolve Xrefs
179
180 mainDb.ResolveXrefs(false, false);
181
182
// Get the XrefGraph for the specified database
183
184
XrefGraph xg = mainDb.GetHostDwgXrefGraph(true);
185
186
// Loop through the nodes in the graph
187
188
for (int i = 0; i < xg.NumNodes; i++)
189 {
190
// Get each node and check its status
191
192
XrefGraphNode xgn = xg.GetXrefNode(i);
193
194
switch (xgn.XrefStatus)
195 {
196
// If Un*, print a message
197
198
case
XrefStatus.Unresolved:
199 ed.WriteMessage(
200
"\nUnresolved xref \"{0}\"", xgn.Name
201 );
202
break;
203
case
XrefStatus.Unloaded:
204 ed.WriteMessage(
205
"\nUnloaded xref \"{0}\"", xgn.Name
206 );
207
break;
208
case
XrefStatus.Unreferenced:
209 ed.WriteMessage(
210
"\nUnreferenced xref \"{0}\"", xgn.Name
211 );
212
break;
213
case
XrefStatus.Resolved:
214 {
215
// If Resolved, get the RegAppTable
216
217
Database xdb = xgn.Database;
218
if (xdb != null)
219 {
220
Transaction tr =
221 xdb.TransactionManager.StartTransaction();
222
using (tr)
223 {
224
RegAppTable rat =
225 (RegAppTable)tr.GetObject(
226 xdb.RegAppTableId,
227
OpenMode.ForRead
228 );
229
230
// We'll store our RegApp data in an
231
// object
232
233
RegAppData dwgData = new
RegAppData();
234 dwgData.Name =
235 (i == 0 ?
236
Path.GetFileNameWithoutExtension(
237 xgn.Name
238 ) :
239 xgn.Name
240 );
241 dwgData.File = xdb.Filename;
242 dwgData.DwgVersion =
243 xdb.OriginalFileVersion.ToString();
244
245
// Collect the contained names of the
246
// RegAppTableRecords (the RegAppIds)
247
// in a list
248
249
foreach (ObjectId id in rat)
250 {
251
RegAppTableRecord ratr =
252 (RegAppTableRecord)tr.GetObject(
253 id,
254
OpenMode.ForRead
255 );
256 dwgData.AddRegAppId(ratr.Name);
257 }
258
259
// Store the object in our dictionary,
260
// replacing any existing item
261
// (keyed off the entire DWG path, not
262
// just the name)
263
264
if (regData.ContainsKey(dwgData.File))
265 regData.Remove(dwgData.File);
266 regData.Add(dwgData.File, dwgData);
267
268
// Print the drawing information
269
// and the RegAppId count
270
271 ed.WriteMessage(
272
"\nDrawing \"{0}\" (\"{1}\") with " +
273
"{2} RegAppIds",
274 dwgData.Name,
275 dwgData.File,
276 dwgData.RegAppIds.Count
277 );
278
279
// Even if only reading, commit the
280
// transaction (it's cheaper than
281
// aborting)
282
283 tr.Commit();
284 }
285 }
286
break;
287 }
288 }
289 }
290
// Save our data to XML
291
292 SerializeRegAppData(regData);
293 }
294 }
295
catch (System.Exception ex)
296 {
297 ed.WriteMessage(
298
"\nProblem reading/processing \"{0}\": {1}",
299 pr.StringResult, ex.Message
300 );
301 }
302 }
303 }
304 }