;;------------------;
;;10/13/05
;;Thanks to - T.Willey & Jeff Mishler
;;
(defun Chk4String (Doc String / flag)
(vl-catch-all-apply
'(lambda ()
(vlax-for i (vla-get-Layouts Doc)
(vlax-for Obj (vla-get-Block i)
(if (and
(or (= (vla-get-ObjectName Obj) "AcDbText")
(= (vla-get-ObjectName Obj) "AcDbMText")
)
(vl-string-search String (vla-get-TextString Obj))
)
(progn
(setq flag T)
(exit)
)
)
)
)
)
)
flag
)
;;------------------;
I do not see why you need to use ObjectDBX now that you have already been in managed API project. I believe both ObjectDBX and opening side database the calling its ReadDwg are the same thing in terms of the ObjectARX being wrapped behind the scene, the former being exposed as COM and the latter being exposed as .NET. If you are doing managed code and the API provides all you need, why add an extra dependency (to the COM), which is not platform independent (32bit/64bit)?
AutoCAD 2012, win7, VS2010 4.0-net
I'm thinking of converting an exising Autolisp routine that loops through a list of .dwg filenames, opening them in odbx,
and checking them to see if they contain a certain text string (see code below).Code: [Select];;------------------;
;;10/13/05
;;Thanks to - T.Willey & Jeff Mishler
;;
(defun Chk4String (Doc String / flag)
(vl-catch-all-apply
'(lambda ()
(vlax-for i (vla-get-Layouts Doc)
(vlax-for Obj (vla-get-Block i)
(if (and
(or (= (vla-get-ObjectName Obj) "AcDbText")
(= (vla-get-ObjectName Obj) "AcDbMText")
)
(vl-string-search String (vla-get-TextString Obj))
)
(progn
(setq flag T)
(exit)
)
)
)
)
)
)
flag
)
;;------------------;
My knowledge of .net programming is still small and I'm trying to determine what would work best:
Should I use dbx code similar to what is found HERE (http://www.theswamp.org/index.php?topic=12035.msg151059#msg151059)
or could I obtain desired results as efficiently using the ReadDwg method?
I'll be running this in the AutoCAD MDIActive document.
Thoughts or comments appreciated.
Just need a shove in the right direction.
Thanks Tony.
Is there any way i can tell when I'm nearing the edge of running out of memory?
Most of my dwg files are ~200kb and I run maybe 2000 files at a time.
I guess the big white box that tells me "AutoCAD cannot continue" would be one indicator. :lol:
Thanks Tony.
Is there any way i can tell when I'm nearing the edge of running out of memory?
Most of my dwg files are ~200kb and I run maybe 2000 files at a time.
I guess the big white box that tells me "AutoCAD cannot continue" would be one indicator. :lol:
The System.Diagonstics.Process class has members that provide information about memory use, which might be helpful, but if you ask me, it would make sense to not try to test the limits.
I would just set a reasonable limit on the number of files/session, and not bother checking memory use and/or if virtual memory faults are sloiwing things to a crawl.
using System.IO;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Internal;
using Autodesk.AutoCAD.Runtime;
using AcadApp = Autodesk.AutoCAD.ApplicationServices.Application;
namespace FindTextInDWG
{
public class FindTXT
{
[CommandMethod("WhereUsed", CommandFlags.Session)]
public void FindTextInDrawing()
{
Document document = AcadApp.DocumentManager.MdiActiveDocument;
Editor editor = document.Editor;
PromptStringOptions options = new PromptStringOptions("\nEnter part number < string >");
options.AllowSpaces = false;
PromptResult result = editor.GetString(options);
if (result.Status == PromptStatus.OK && result.StringResult.Length > 0)
{
using (document.LockDocument())
{
string filename = "Your text file list of drawings full path.txt"; //list of filenames.
if (File.Exists(filename))
{
try
{
string[] lines = System.IO.File.ReadAllLines(@"Your text file list of drawings full path.txt"); //array of filename strings.
using (Transaction transaction = document.TransactionManager.StartTransaction())
{
foreach (string str in lines)
{
Database database2 = new Database(false, false);
database2.ReadDwgFile(str, System.IO.FileShare.ReadWrite, true, "");
BlockTable table = (BlockTable)transaction.GetObject(database2.BlockTableId, OpenMode.ForRead);
BlockTableRecord btr = (BlockTableRecord)transaction.GetObject(table[BlockTableRecord.ModelSpace], OpenMode.ForRead);
foreach (ObjectId oid in btr)
{
Entity ent = (Entity)transaction.GetObject(oid, OpenMode.ForRead);
if (ent != null && ent.GetType().Name.Equals("DBText"))
{
DBText dbt = (DBText)transaction.GetObject(ent.ObjectId, OpenMode.ForRead);
if (dbt.TextString.Contains(result.StringResult))
{
editor.WriteMessage("\n dbt : " + dbt.TextString + " matches result: " + result.StringResult + " in " + str);
//do other work, list file names etc. here.
}
}
}
database2.Dispose();
} //first foreach
transaction.Commit();
} //using
} //try block
catch (System.Exception exception)
{
editor.WriteMessage("\nError: " + exception);
}
}
} //doc lock.
} //if string input ok.
Utils.PostCommandPrompt();
} //find text string method end
}
}
where the out-of-process controller only controls the process of opening files, and closing and restarting AutoCAD while the heavy-lifting is done by the in-process component.
using System;
using System.Windows.Forms;
using Autodesk.AutoCAD.Interop;
using Autodesk.AutoCAD.Interop.Common;
namespace StartAcadApp
{
public class StartAcadApp
{
//if AutoCAD 2012 used.
const string progID = "AutoCAD.Application.18.2";
// This C# code is compiled as a Windows application.
public static void Main()
{
AcadApplication acApp = null;
Type acType = Type.GetTypeFromProgID(progID);
acApp = (AcadApplication)Activator.CreateInstance(acType, true);
if (acApp == null)
{
MessageBox.Show("Cannot create object of type \"" + progID + "\"");
}
if (acApp != null)
{
acApp.Visible = true;
acApp.WindowState = AcWindowState.acMax;
acApp.ActiveDocument.SendCommand("WhereUsed\n");
}
}
}
}
using System.IO;
using System.Text;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Internal;
using Autodesk.AutoCAD.Runtime;
using AcadApp = Autodesk.AutoCAD.ApplicationServices.Application;
namespace FindTextInDWG
{
public class FindTEXT
{
[CommandMethod("WhereUsed", CommandFlags.Session)]
public void FindTextInDrawing()
{
Document document = AcadApp.DocumentManager.MdiActiveDocument;
Editor editor = document.Editor;
int counter = 0;
PromptStringOptions options = new PromptStringOptions("Enter part number: < string > ");
options.AllowSpaces = false;
PromptResult result = editor.GetString(options);
if (result.Status == PromptStatus.OK && result.StringResult.Length > 0)
{
editor.WriteMessage("Please wait while files are being searched.");
using (document.LockDocument())
{
string filename = "G:\\AutoCAD2012Support\\LispText\\MyFileList.txt"; //list of filenames.
if (File.Exists(filename))
{
try
{
string[] lines = System.IO.File.ReadAllLines(@"G:\\AutoCAD2012Support\\LispText\\MyFileList.txt"); //array of filename strings.
StringBuilder sb = new StringBuilder();
using (Transaction transaction = document.TransactionManager.StartTransaction())
{
foreach (string str in lines)
{
Database database2 = new Database(false, false);
bool flag = false;
database2.ReadDwgFile(str, System.IO.FileShare.ReadWrite, false, "");
BlockTable table = (BlockTable)transaction.GetObject(database2.BlockTableId, OpenMode.ForRead);
BlockTableRecord btr = (BlockTableRecord)transaction.GetObject(table[BlockTableRecord.ModelSpace], OpenMode.ForRead);
foreach (ObjectId oid in btr)
{
Entity ent = (Entity)transaction.GetObject(oid, OpenMode.ForRead);
if (ent != null && ent.GetType().Name.Equals("DBText"))
{
DBText dbt = (DBText)transaction.GetObject(ent.ObjectId, OpenMode.ForRead);
if (dbt.TextString.Contains(result.StringResult))
{
flag = true;
break;
}
}
}
database2.Dispose();
if (flag)
{
sb.AppendLine(str);
counter = counter + 1;
}
} //first foreach
transaction.Commit();
} //using
File.WriteAllText("G:\\AutoCAD2012Support\\LispText\\WhereUsed.txt", sb.ToString());
} //try block
catch (System.Exception exception)
{
editor.WriteMessage("\nError: " + exception);
}
}
} //doc lock.
editor.WriteMessage("\nFound < " + counter + " > files that contain: " + result.StringResult);
} //if string input ok.
Utils.PostCommandPrompt();
AcadApp.Quit();
} //FindTextInDrawing method end
}
}
Code: [Select]
Entity ent = (Entity)transaction.GetObject(oid, OpenMode.ForRead);
if (ent != null && ent.GetType().Name.Equals("DBText"))
{
DBText dbt = (DBText)transaction.GetObject(ent.ObjectId, OpenMode.ForRead);
..........
QuoteCode: [Select]
Entity ent = (Entity)transaction.GetObject(oid, OpenMode.ForRead);
if (ent != null && ent.GetType().Name.Equals("DBText"))
{
DBText dbt = (DBText)transaction.GetObject(ent.ObjectId, OpenMode.ForRead);
..........
You might want to take a closer look at the above part of your code
QuoteCode: [Select]
Entity ent = (Entity)transaction.GetObject(oid, OpenMode.ForRead);
if (ent != null && ent.GetType().Name.Equals("DBText"))
{
DBText dbt = (DBText)transaction.GetObject(ent.ObjectId, OpenMode.ForRead);
..........
You might want to take a closer look at the above part of your code
I thought I just read recently the differences between direct casting, and the use of the as operator, where in a situation such as this it's preferable to use the latter, for logical test thereafter in order to avoid throwing an exception, no?Code - C#: [Select]
Entity ent = transaction.GetObject(oid, OpenMode.ForRead) as Entity; if (ent != null) { DBText dbt = transaction.GetObject(ent.ObjectId, OpenMode.ForRead) as DBText;
QuoteCode: [Select]
Entity ent = (Entity)transaction.GetObject(oid, OpenMode.ForRead);
if (ent != null && ent.GetType().Name.Equals("DBText"))
{
DBText dbt = (DBText)transaction.GetObject(ent.ObjectId, OpenMode.ForRead);
..........
You might want to take a closer look at the above part of your code
foreach (ObjectId oid in btr)
{
if (oid.ObjectClass.DxfName == "TEXT")
{
DBText dbt = (DBText)transaction.GetObject(oid, OpenMode.ForRead);
if (dbt.TextString.Contains(result.StringResult))
{
flag = true;
break;
}
}
}
Code: [Select]foreach (ObjectId oid in btr)
{
if (oid.ObjectClass.DxfName == "TEXT")
{
DBText dbt = (DBText)transaction.GetObject(oid, OpenMode.ForRead);
if (dbt.TextString.Contains(result.StringResult))
{
flag = true;
break;
}
}
}
Thanks!
foreach (ObjectId oid in btr)
{
var dbt = transaction.GetObject(oid, OpenMode.ForRead) as DBText;
if (dbt == null) continue;
if (dbt.TextString.Contains(result.StringResult))
{
flag = true;
break;
}
}
What the guys above were trying to show you is that if your going to cast the object anyway then use the "as" keyword and skip testing the ObjectId.Code: [Select]foreach (ObjectId oid in btr)
{
var dbt = transaction.GetObject(oid, OpenMode.ForRead) as DBText;
if (dbt == null) continue;
if (dbt.TextString.Contains(result.StringResult))
{
flag = true;
break;
}
}
foreach (ObjectId oid in btr)
{
if (oid.ObjectClass.DxfName == "TEXT")
{
DBText dbt = transaction.GetObject(oid, OpenMode.ForRead) as DBText;
if (dbt.TextString.Contains(result.StringResult))
{
sb.AppendLine(str);
counter = counter + 1;
break;
}
}
}
I would think its calling GetObject() that is time consuming.
As in last example you posted I would do a hard cast because I would want an error thrown if the ObjectClass implementation was messed up and returning incorrect values.