In the past C++/C era, it was very easy to crash AutoCAD or even the whole Operating System. Now in the .NET time, it is harder, much harder than before, but we still can find various ways to crash AutoCAD using its .NET API, from the easiest or most common to quite hard or very creative.
Many times, we need to operate on some external AutoCAD DWG files rather than those that have already been open inside the AutoCAD editor. AutoCAD .NET provides a way to read a DWG into a side Database built in memory only. It is easy to use if good practices and right code are applied, and could be very dangerous too if not.
Here is a good and working version.
[CommandMethod("CreateDatabaseFromDwgFile")]
public static void CreateDatabaseFromDwgFile_Method()
{
Editor ed = MgdAcApplication.DocumentManager.MdiActiveDocument.Editor;
try
{
using (Database db = new Database(false, true))
{
db.ReadDwgFile(@"c:\temp\test.dwg", FileOpenMode.OpenForReadAndAllShare, false, null);
db.CloseInput(true);
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTableRecord btr = (BlockTableRecord)tr.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForRead);
foreach (ObjectId id in btr)
{
Entity ent = (Entity)tr.GetObject(id, OpenMode.ForWrite);
ent.ColorIndex = 1;
}
tr.Commit();
}
db.SaveAs(@"c:\temp\test_2red.dwg", DwgVersion.Current);
}
}
catch (System.Exception ex)
{
ed.WriteMessage(ex.ToString());
}
}
The code reads a DWG from hard disk to a side database built into memory, changes all entities in the database to red, saves the database as a new DWG file, and finally disposes of the database implicitly through the simple but cool ‘using’ statement.
The leading edge AutoCAD .NET Addin Wizard (AcadNetAddinWizard) provides project wizards in C#, VB.NET and CLI/Managed C++, and various item wizards such as Event Handlers, Command/LispFunction Definers, and Entity/Draw Jiggers in both C# and VB.NET, to help program AutoCAD addins.
Hello
I am really finding your blog very useful, but have not been able to identify my problem exactly yet.
I am trying to read all the page setups from a file and copy to another.
So I have done the first part about reading the file into a database.
Then using dictionary, I am trying to assign all the page setups to an array.
here is what happens - the first time I run through a file, it runs fine.
But then it starts to crash.
It does so as it loops through the page set ups.
As all the page setup s are not actually layouts, I have used the true option in read erased while obtaining the values.
Most other options I have seen only address actual layouts, not page setups.
The code is below.
Please help.
Function Tanjob() As PlotSettings
Dim dhubaz As New Database(False, True)
Dim lyoot(50), lyt As Layout
Dim n, nn, inn, inchkstr1, inchkstr2 As Integer
Dim dishent As DictionaryEntry
Dim lytnm, reqlytnm As String
Dim chkstr1, chkstr2 As String
Dim Pltstng, allpltsng(100) As PlotSettings
Dim laydish As DBDictionary
Dim sts As Object
n = 1
nn = 0
Dim scefil As String = "C:\Users\lyts.dwg"
Dim Temptran As Transaction
Temptran = dhubaz.TransactionManager.StartTransaction()
MsgBox(nn)
Using Temptran
dhubaz.ReadDwgFile(scefil, FileOpenMode.OpenForReadAndAllShare, False, vbNullString)
laydish = Temptran.GetObject(dhubaz.PlotSettingsDictionaryId, OpenMode.ForRead)
For Each dishent In laydish
nn = nn + 1
allpltsng(nn) = DirectCast(Temptran.GetObject(dishent.Value, OpenMode.ForRead, True), PlotSettings)
'sts = allpltsng(nn).
MsgBox(allpltsng(nn).PlotSettingsName & " " & nn)
Next
MsgBox(nn)
Tanjob = allpltsng(1)
For inn = 1 To nn
reqlytnm = allpltsng(nn).PlotSettingsName
chkstr1 = "14x"
chkstr2 = "full"
inchkstr1 = InStr(reqlytnm, chkstr1)
inchkstr2 = InStr(reqlytnm, chkstr2)
MsgBox(reqlytnm)
If inchkstr1 <> 0 And inchkstr2 <> 0 Then
Pltstng = allpltsng(inn)
Dim pltstvdr As PlotSettingsValidator = PlotSettingsValidator.Current
Tanjob = Pltstng
End If
Next inn
End Using
Temptran.Commit()
End Function
End Class
Posted by: Bauron A | 06/24/2013 at 02:37 PM
Bauron, glad to know you found the blog useful.
In terms of the issue, it seems with the transaction usage. You 'Commit' the transaction after 'End Using' it. It causes problem because at that moment the transaction has already been disposed of (End Used). So commiting it right before being disposed of should get rid of the crash.
By the way, not sure if you have tried the AcadNetAddinWizard (AutoCAD .NET Addin Wizard). If not, please give it a try and you will find it's good and useful too.
Posted by: Spiderinnet1 | 06/24/2013 at 03:36 PM
Nice post. I am trying to use it in conjunction with plotting. I have had success but also problems found here http://forums.autodesk.com/t5/net/side-loading-a-dwg-with-readdwgfile-then-plotting/m-p/5840698#M46118. Any clues?
Posted by: James Morris | 10/01/2015 at 01:32 PM
James, glad you like it. In terms of the issue on the forum, it seems you already got a workaround for the problem, either in the code, in the API, or in AutoCAD itself.
Posted by: Spiderinnet1 | 10/01/2015 at 09:35 PM
Hey Really good post, being new to this - can you create a blog regarding exactly which of the 'feels like' 10k dll's to use? - I'm being overwhelmed with the ObjectArx and other dll files you could use. Thanks so much. - Don
Posted by: Don Boyle | 02/06/2016 at 12:21 AM
Hi Don, glad to know you like it. However, not sure what you are exactly asking. Are you going to use the ObjectARX SDK and would like to find some resources? If that is the case, the ObjectARX developers' guide and SDK samples may be good start points. Even if we could start off another blog to cover ObjectARX, it will take long time to make it comprehensive enough.
Posted by: Spiderinnet1 | 02/06/2016 at 02:45 AM
Hello Mr Spider
I tried your above code but it seems to be crashing: - I am calling it from within a revit plugin because I want to read and extract Autocad objects and then build revit objects based on the Autocad geometry. its says 'common language runtime detected an invalid program'. any ideas? rgds, Ben
Posted by: BKSpurgeon | 03/22/2017 at 07:44 PM
Ben, the code and any other AutoCAD .NET have to run inside AutoCAD. The limitation is imposed by AutoCAD itself. That is it!
Posted by: Spiderinnet1 | 03/22/2017 at 10:02 PM