Download as pdf or txt
Download as pdf or txt
You are on page 1of 31

AutoCAD® Architecture and AutoCAD® MEP

.NET Programming: A Beginner's Guide


Kevin Vandecar – Autodesk, Inc.

DE211-1 The maturing AutoCAD Architecture and AutoCAD MEP .NET APIs in recent releases give you
more reasons than ever to get started with .NET programming. This course will introduce you to these .NET APIs.
We’ll discuss project setup, class hierarchy, and techniques for accessing objects and data. You should have some
basic programming knowledge, but the class will cover a broad range of beginner to intermediate programming
concepts.

About the Speaker:


Kevin has worked for Autodesk for 14 years in various capacities, all customization related (from developer support
and testing to software development and consulting). He has also worked for a large reseller/consulting firm and has
a customer-centric sensibility. Kevin currently is a software engineer at Autodesk and is in charge of planning and
implementing the .NET API for the AutoCAD Architecture and AutoCAD MEP products.

[email protected]
AutoCAD® Architecture and AutoCAD® MEP
.NET Programming: A Beginner's Guide

Course Objective

This course is designed to introduce the .NET programming environment now available in AutoCAD
Architecture (ACA) and AutoCAD MEP (AMEP).

The course material will help you to understand:

• The benefits of .NET API using ACA or AMEP applications


• Project Setup
• The fundamentals of the ACA and AMEP .NET API
• Overview of the specific modules and their functionality
• ACA .NET API fundamentals.
• AMEP .NET API fundamentals.
• Resources for further information and help

Microsoft .NET Framework


First, let’s take a quick look at what the Microsoft .NET Framework really is. The definition found on
the Microsoft Developer Network (MSDN) website says this:

“The .NET Framework is a development and execution environment that allows different
programming languages & libraries to work together seamlessly to create Windows-based
applications that are easier to build, manage, deploy, and integrate with other networked systems.

The .NET Framework consists of:

• The Common Language Runtime (CLR) - A language-neutral development & execution


environment that provides services to help "manage" application execution
• The Framework Class Libraries (FCL) - A consistent, object-oriented library of prepackaged
functionality”

One of the common misconceptions is around its name. The term .NET seems to indicate that this
new programming environment is primarily for web development. However, it should be viewed as a
platform framework in the same sense that “Windows API”, “MFC”, or “COM”, etc. are also used. The
difference being that the .NET Framework is a basis of platform and system functionalities regardless
of language, and it is not specific to a single programming domain (like “the web”).

For further information, please see the following links at the MSDN web site. There are many topics
that will help you to discover all the .NET fundamentals and taking you through very advanced topics
and capabilities.
AutoCAD® Architecture and AutoCAD® MEP
.NET Programming: A Beginner's Guide

Specific learning resources:

http://msdn2.microsoft.com/en-us/netframework/aa569294.aspx

High-level starting point:

http://msdn2.microsoft.com/en-us/netframework/default.aspx

Managed Code
Let’s drill down a little deeper into the .NET terminology and discuss what managed code is all about.
First, as its name implies, managed code is “managed” by the system. All code is executed and
managed by the .NET Framework's Common Language Runtime (CLR). The language compilers all
produce code that is in the Microsoft Intermediate Language (MSIL) format and executes as
managed code. With this strategy, one benefit is that the system provides memory management for
you. As a C++ programmer, memory management is of utmost importance. For Visual Basic (VB) it
has not been as important, and the coding practices are a bit different. The concept of managed code
aims to make programming concepts consistent and eliminate the need for differing memory
management techniques.

Unmanaged Code
Exactly as it states, unmanaged code is just that… unmanaged. This is code that is compiled down to
“p-code” and is executed by the CPU in a native mode. Typically a “pure” C++ application is an
example of this.

Assemblies
Assemblies are a fundamental part of programming with the .NET Framework. Here’s the MSDN
definition:

“Assemblies are the building blocks of .NET Framework applications; they form the fundamental unit
of deployment, version control, reuse, activation scoping, and security permissions. An assembly is a
collection of types and resources that are built to work together and form a logical unit of functionality.
An assembly provides the common language runtime with the information it needs to be aware of
type implementations. To the runtime, a type does not exist outside the context of an assembly.”

For more information see:

http://msdn2.microsoft.com/en-us/library/hk5f40ct(VS.80).aspx
AutoCAD® Architecture and AutoCAD® MEP
.NET Programming: A Beginner's Guide

Structure
How is the .NET Framework structured? The CLR sits at the base of the system. It is responsible for
executing the code that comes from various sources through the MSIL format. It then has various
base-level platform libraries. The ASP and Windows forms sit on those. Finally the languages are at
the top to provide access to the libraries in their own unique way. See figure 1 for a diagram of the
structure.

Figure 1 - .NET Framework Structure


AutoCAD® Architecture and AutoCAD® MEP
.NET Programming: A Beginner's Guide

Figure 2 illustrates the process used to compile and execute managed code that uses the CLR.
Source code written in C#, VB.NET, or some other language that targets the CLR is first transformed
into MSIL by the appropriate language compiler. Before execution, this MSIL is JIT (Just In Time)
compiled into native code for whatever processor the code will run on. The default is to JIT compile
each method when it is first called, but it’s also possible to “pre-JIT” the MSIL. With this option, all
methods are compiled before the application is loaded, so the overhead of JIT compilation on each
initial method call is avoided. Its worth noting is that all languages targeting the CLR should exhibit
roughly the same performance. While some compilers may produce better MSIL code than others,
large variations in execution speed are unlikely.

Figure 2 – CLR Execution Model

Reflection
Reflection is a basic feature of the .NET Framework. Essentially the .NET Framework provides APIs
that allow you to interrogate runtime information about assemblies in different ways. For example, you
could load an assembly and find out its types and members. Or from a specific instance of an object,
determine its type information and then actually call it members.

See the MSDN website for more detailed information:


http://msdn2.microsoft.com/en-us/library/cxz4wk15.aspx

See the course sample code for detailed programming examples.


AutoCAD® Architecture and AutoCAD® MEP
.NET Programming: A Beginner's Guide

AutoCAD .NET API


AutoCAD Architecture and AutoCAD MEP are obviously both built on top of the AutoCAD platform.
This means that the AutoCAD .NET API is very important to the ACA and AMEP .NET API. ACA and
AMEP build directly on top of the AutoCAD APIs and you will see the APIs are used together to
create applications.

AutoCAD .NET API structure


The AutoCAD .NET API is provided through .NET assemblies (DLL) that your application will
reference to gain access to the API functionality. For a VB programmer, this is very similar to what
was required in the past. Essentially this is providing the system with the definitions to the types that
AutoCAD .NET API is providing. Your application will also be a managed assembly (DLL) file that is
loaded into the AutoCAD .NET Framework.

The ObjectARX Wizard (included with the ObjectARX SDK) provides a tool that will setup a minimal
VB.NET or C# project. However, this is not necessary to create a basic project. We will cover the
fundamental steps later in this document.

NOTE: The ObjectARX SDK is available here http://www.autodesk.com/objectarx

.NET API Assemblies


The assemblies that Autodesk provides are all located in the acad.exe directory of your product
install. Each product will have a different set of assemblies depending on the product (for example
AMEP provides ALL the fore mentioned assemblies while ACA includes only the AutoCAD and ACA
specific assemblies).

AutoCAD .NET API Assemblies


• acdbmgd.dll – Contains database level functionality, including entity and objects, the geometry
classes, graphics system, etc.
• acmgd.dll – Contains application level functionality, including the editor, plotting, and windows
functionality.
ACA .NET API Assemblies
• AecBaseMgd.dll – Contains the ACA base classes including anchors, dictionaries, etc.
• AecBaseUtilsMgd.dll – Contains some ACA base utility classes used for omparing and
accessing information in the same context as ACA itself.
• AecArchMgd.dll – Contains the majority of the ACA specific objects including walls, windows,
doors, etc.
• AecProjectBaseMgd.dll – Contains the base project management APIs.
• AecPropDataMgd.dll – Contains the property data functionality.
• AecStructureMgd.dll – Contains the structural functionality.
AutoCAD® Architecture and AutoCAD® MEP
.NET Programming: A Beginner's Guide

AMEP .NET API Assemblies


• AecbBldSrvMgd.dll – Contains the AMEP base classes including member, multi-view part, etc.
• AecbHvacBaseMgd.dll – Contains the HVAC functionality including duct and duct fitting.
• AecbElecBaseMgd.dll – Contains the electrical functionality including device, wire, circuit, etc.
• AecbPipeBaseMgd.dll – contains the functionality for pipe, etc.
• AecbPlumbingBaseMgd.dll – contains the functionality for schematic pipe, etc.
• AecbPartBaseMgd.dll – Contains the functionality for creating and modifying parts. This is a
module that provides “helper” utilities that combine the pure database objects with the catalog
functionality.

Implementing Commands
As mentioned earlier, the ACA and AMEP .NET API build on AutoCAD .NET API. Therefore, you will
probably utilize the AutoCAD command mechanism to invoke your .NET functionality. Creating a
command in the .NET API is quite different than ObjectARX or LISP (or VBA where it’s impossible
without another language’s help). The AutoCAD .NET API uses a specific attribute on a public
method to indicate that the method is to be invoked when the command is entered. The attribute is
appropriately called CommandMethod. The arguments are similar to those in the ObjectARX
addCommand function. For example in C#:

[CommandMethod(“SampleCommandGroup”, “SampleCommand”, CommandFlags.Modal)]


public void Sample()
{

}

Or in VB.NET:

<CommandMethod(“SampleCommandGroup”, “SampleCommand”, CommandFlags.Modal)>


Public Sub sample()

End Sub
AutoCAD® Architecture and AutoCAD® MEP
.NET Programming: A Beginner's Guide

Implementing IExtensionApplication
The IExtensionApplication interface provided by AutoCAD allows another way to have your code
executed (instead of via a command). This mechanism allows you to have code executed upon start-
up (and shut-down, but note that there is no way to unload your application other than at shut-down!).
This allows you to initialize things at load time, but is completely optional.

For example, here is a nice way to show a message at load time:

public class Class1 : IExtensionApplication


{
public void Initialize()
{
Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
ed.WriteMessage("Loading AecHardwiredStylesMgd...\r\n");
}

public void Terminate()


{
}
}

Or in VB.NET:

' Optional Application class


Public Class MyApp
Implements IExtensionApplication

Public Sub MyInitialize() Implements IExtensionApplication.Initialize


Dim ed As Editor = _
Acadapp.DocumentManager.MdiActiveDocument.Editor
ed.WriteMessage(vbCrLf & "Loading sample .NET API program…")
End Sub

Public Sub MyTerminate() Implements IExtensionApplication.Terminate


' Cleanup - but no "NETUNLOAD" available
End Sub
End Class

Tip: You might chose to setup your applications in this manner (as above) all the time so that when
you try to load the application you know whether it loaded or not. AutoCAD provides no easy way to
see if your application is in fact loaded. By using the message at load time, you can see during
development whether the app loaded correctly before you spend time trying to run commands that
won’t be there!
AutoCAD® Architecture and AutoCAD® MEP
.NET Programming: A Beginner's Guide

Error handling
The .NET API provides errors in the form of exceptions. The exception handling is very similar to the
C++ style. An exception will be thrown by the API when an error condition arises. Typical exceptions
are in the form of:

• Autodesk.AutoCAD.Runtime.Exception – This is the main AutoCAD and ACA oriented


exception and will contain specific information about the error that occurred.
• Autodesk.AutoCAD.Building.Exception – This is an additional level that only AMEP
provides for more information. Take note of what exceptions are thrown so you can be sure
you are catching the most detailed level of information.
Additionally the following system exceptions can be typical:

• System.InvalidOperationException
• System.ArgumentNullException
• System.ArgumentOutOfRangeException
• System.ArgumentException
Here is an example in C#:

double result = 0;
try {
result = Converter.StringToDistance("foo");
}
catch (Autodesk.AutoCAD.Runtime.Exception e) {
result = double.NaN;
}
finally {
MessageBox.Show("Distance: " + result);
}

In VB.NET:

Dim result As Double = 0


Try
‘ Convertor is in Autodesk.AutoCAD.Runtime, so it would
‘ raise Autodesk.AutoCAD.Runtime.Exception
result = Converter.StringToDistance("Will Fail")

Catch e As Exception
' Since Autodesk.AutoCAD.Runtime.Exception is derived from
' System.Exception, this block fill catch *any* exception
MessageBox.Show(e.GetType.ToString + ": " + e.Message())
result = Double.NaN

Finally ' This block is executed *always*


MessageBox.Show("Distance: " + result.ToString())
End Try
AutoCAD® Architecture and AutoCAD® MEP
.NET Programming: A Beginner's Guide

Autodesk Exceptions - Error Status and Error Code


You may need to check data in the exception to find out more specific information. Both
Autodesk.AutoCAD.Runtime.Exception and Autodesk.AutoCAD.Building.Exception
are important examples of this concept.

The following ACA example shows how to catch a generic System.Exception and then cast it down to
check for the specific error you want. This allows you to catch a very fundamental exception, but then
check it for a specific condition.

DictionaryWallStyle wallstyledict = new DictionaryWallStyle(db);


try
{
// Try to get the style if it exists.
id = wallstyledict.GetAt("fred");
trans.Commit();
}
catch (System.Exception e)
{
if (e.GetType() == typeof(Autodesk.AutoCAD.Runtime.Exception))
{
Autodesk.AutoCAD.Runtime.Exception acade =
e as Autodesk.AutoCAD.Runtime.Exception;
if (acade.ErrorStatus ==
Autodesk.AutoCAD.Runtime.ErrorStatus.KeyNotFound)
{
// Add the style in the case it does not exist
ed.WriteMessage("\nAdding the Wall style we need.");
WallStyle wallstyle = new WallStyle();
wallstyle.SetToStandard(db);
wallstyle.SubSetDatabaseDefaults(db);
wallstyle.Description = "fred style";
wallstyledict.AddNewRecord("fred", wallstyle);
trans.AddNewlyCreatedDBObject(wallstyle, true);
trans.Commit();
}
} else {
ed.WriteMessage("\nError: " + e.Message);
}
}
AutoCAD® Architecture and AutoCAD® MEP
.NET Programming: A Beginner's Guide

The following AMEP example shows that when you query the AMEP Part Catalog an AMEP specific
exception may be thrown and if that is the only condition you really want to check, you can simply
catch that specific-level exception. In this case it is checking the ErrorCode of the exception to find
out what condition caused it. The example shows that in the case of
ErrorCode.QueryResultNull error code being returned, it requires additional specialized
handling.

catch (Autodesk.Aec.Building.DatabaseServices.BuildingException be)


{
if (be.ErrorCode == ErrorCode.QueryResultNull)
{
// do something special here
}
}
Tip: You will find that because the AutoCAD .NET API wraps all the Acad::ErrorStatus (C++
ObjectARX) values as an exception, sometimes it isn’t always obvious what the problem is. Some
view exceptions as fatal, while in the .NET API they are certainly not always and should be evaluated
appropriately. For example, a typical return status from an ObjectARX “GetAt” style call might be
KeyNotFound. This is not at all detrimental to the program (in this case meaning that whatever was
being searched for was not present, therefore the application may have to create it as a result of the
exception.)

Transactions
Transactions are a major part of dealing with AutoCAD database resident information. In order to
access or create anything within the AutoCAD database (including ACA and AMEP objects), you
must initiate a transaction. Transactions provide you with the ability to group operations together in a
single action, which can help with things like UNDO. You can nest transactions and either commit or
abort each sub-level as you wish. The transaction itself will deal with the closing or aborting of the
objects based on how the transaction ended.

Here is an example of a transaction in C#:

Database db = HostApplicationServices.WorkingDatabase;
TransactionManager tm = db.TransactionManager;

Transaction trans = tm.StartTransaction();


try {
object obj = tm.GetObject(id, OpenMode.ForWrite);
// modify the object
trans.Commit();
}
catch {
trans.Abort();
}
finally {
trans.Dispose();
}
AutoCAD® Architecture and AutoCAD® MEP
.NET Programming: A Beginner's Guide

In VB.NET:

Dim db As Database = HostApplicationServices.WorkingDatabase


Dim tr As Transaction = db.TransactionManager.StartTransaction

Try
Dim obj As DBObject = tr.GetObject(id, OpenMode.ForXXXX)
‘ access/modify obj
‘...
‘ If a new object created and added to DB, must also:
tr.AddNewlyCreatedDBObject(objNew, True)
tr.Commit()

Catch ‘Not needed if only tr.Abort called. Dispose will call Abort if no
Commit called beforehand
tr.Abort()

Finally
tr.Dispose()

End Try

NOTE: The transaction itself must also be aware of new objects being added. So in addition to the
typical “add to the database” operation, you must also tell the transaction about the new object with
the Transaction.AddNewlyCreatedDBObject method.

Both C# and VB.NET now support the special keyword called using. By coding with this keyword, it
makes the transaction setup even easier. The transaction will automatically dispose (and abort when
appropriate). For example in C#:

Database db = HostApplicationServices.WorkingDatabase;
using (Transaction t = db.TransactionManager.StartTransaction())
{
//...
object obj = tm.GetObject(id, OpenMode.ForWrite);
//...

// skipped when an exception is thrown somewhere above


t.Commit();
}
// t.Dispose() is called when the using scope ends

Tip: In many cases you may be opening objects simply to read the data. In these cases it may be
logical to simply let the transaction automatically abort and dispose of itself. Unfortunately due to an
internal implementation detail in AutoCAD, it is ALWAYS faster to commit the transaction at the end,
even in the read-only situation. Because of this, only use the abort mechanism if you specifically want
to abort changes. You should get into the habit of committing the transaction in all successful cases.
This is especially true for applications that will be querying a large number of objects that has
performance concerns.
AutoCAD® Architecture and AutoCAD® MEP
.NET Programming: A Beginner's Guide

NOTE: The transaction requirement in .NET API is different than the ObjectARX model. In ObjectARX
you have two ways to deal with database resident objects. The first uses the open/close mechanism,
and the second is the transaction model. Either approach is fine for ObjectARX C++, although the
transaction approach has the additional benefits. AutoCAD .NET API provides only the transaction
model and is a requirement except in special circumstances.

To summarize, it is important to have a good base understanding of the AutoCAD .NET API before
diving into the ACA and AMEP APIs. Resources for AutoCAD .NET API information and training:

http://www.autodesk.com/developer - general partner information

http://usa.autodesk.com/adsk/servlet/index?siteID=123112&id=1911627 – this page includes the


AutoCAD 2007 .NET training material for download.

The AutoCAD .NET API (samples and documentation) is provided as part of the ObjectARX SDK.
The ObjectARX SDK is located here:

http://www.autodesk.com/objectarx
AutoCAD® Architecture and AutoCAD® MEP
.NET Programming: A Beginner's Guide

ACA and AMEP API Relationships


The ACA APIs reside on top of AutoCAD, and AMEP utilizes the ACA OMF API for its functionality.
Before diving into the .NET API for ACA and AMEP let’s first look at a relationship diagram.

See figure 3.

Figure 3 – ACA and AMEP API relationships

Project Setup
First of all, let’s discuss the requirements for .NET API development. The basic piece that you need is
a compiler that supports the .NET Framework 2.0. If you review the material from the CLR discussion
previously, you will know that the resulting code is in the fundamental format called MSIL and
therefore is the only requirement for AutoCAD to load it. There are a number of sources that will
produce this format, but the most common environment is the Microsoft Visual Studio 2005 version.
We will be using this software for the class and the steps provided here are for that version.

For more information see:


AutoCAD® Architecture and AutoCAD® MEP
.NET Programming: A Beginner's Guide

http://msdn.microsoft.com/vstudio/ - Top level MS Visual Studio information. Also note that Visual
Studio is part of some MSDN level subscriptions (might be better value).

http://msdn.microsoft.com/vstudio/express/ - Express compiler editions are free, but are more difficult
to setup for debugging into an assembly that has been loaded by AutoCAD. For information on the
express editions debugging, see:

http://through-the-interface.typepad.com/through_the_interface/2006/07/debugging_using.html

Project Setup Steps


1. Create a new Class Library project
2. Add references
3. Import the assembly namespaces
4. Start coding!
Create a new Class Library
Open the Visual Studio application and choose File->New->Project. This will open the New Project
dialog. In the left Project Types list box, select the language (if you have a multiple language version).
AutoCAD® Architecture and AutoCAD® MEP
.NET Programming: A Beginner's Guide

Add References
In order to use objects from an assembly, we need to add a reference of the assembly to the project.
You can do this in the Project Menu->Add Reference. Each language has various other ways to reach
this dialog too. Note that the add reference dialog starts with the .NET components tab. The .NET API
assembly modules that Autodesk provides are not signed and do not reside in the Global Assembly
Cache (GAC), so we must specifically reference them from the acad.exe directory (the root directory
of where your ACA or AMEP software is installed). This is done from the Browse tab.

The following is a list of modules for use with ACA and AMEP:

AutoCAD .NET API Assemblies


• acdbmgd.dll – REQUIRED. Contains database level functionality, including entity and objects,
the geometry classes, graphics system, etc.
• acmgd.dll – Contains application level functionality, including the editor, plotting, and windows
functionality.
ACA .NET API Assemblies
• AecBaseMgd.dll – REQUIRED. Contains the ACA base classes including anchors,
dictionaries, etc.
• AecBaseUtilsMgd.dll – Contains some ACA base utility classes used for omparing and
accessing information in the same context as ACA itself.
• AecArchMgd.dll – Contains the majority of the ACA specific objects including walls, windows,
doors, etc.
• AecProjectBaseMgd.dll – Contains the base project management APIs.
• AecPropDataMgd.dll – Contains the property data functionality.
• AecStructureMgd.dll – Contains the structural functionality.
AMEP .NET API Assemblies
• AecbBldSrvMgd.dll – REQUIRED. Contains the AMEP base classes including member, multi-
view part, etc.
• AecbHvacBaseMgd.dll – Contains the HVAC functionality including duct and duct fitting.
• AecbElecBaseMgd.dll – Contains the electrical functionality including device, wire, circuit, etc.
• AecbPipeBaseMgd.dll – contains the functionality for pipe, etc.
• AecbPlumbingBaseMgd.dll – contains the functionality for schematic pipe, etc.
• AecbPartBaseMgd.dll – Contains the functionality for creating and modifying parts. This is a
module that provides “helper” utilities that combine the pure database objects with the catalog
functionality.
After selecting the assemblies, it is recommended to change the “Copy Local” flag to False. To do
this, multi-select all the references in the Solution Explorer window, then in the Properties Window
change Copy Local to False. This setting is used to tell the compiler whether it should copy the
assembly to your project’s local directory, rather than reference it from its home location. Because
AutoCAD® Architecture and AutoCAD® MEP
.NET Programming: A Beginner's Guide

these files will always be present with any ACA or AMEP install, there is no obvious benefit to using
the Copy Local flag and it can cause confusion if you try to package these with a distribution.

Tip: The browse tab is a file dialog. After browsing to the ACA or AMEP root directory, type-into the
File Name edit box: *Mgd.dll, which will filter down to match all the possible Autodesk managed
assemblies. This will help narrow down the files needed. This is also a multi-select dialog, so using
the Ctrl key you can multi-select all the assemblies that you need in a single action.

Import the assembly namespaces


Once the references are made, you need to import the namespaces into the code modules. The
syntax is different depending on the language used, but the namespaces are identical. Generally this
is accomplished by adding the statements at the top of your module source code and outside of any
namespace or class declarations. For example to access the different database services for
AutoCAD, ACA, and AMEP in C#:

using Autodesk.AutoCAD.DatabaseServices; // AutoCAD database objects


using Autodesk.Aec.DatabaseServices; // ACA Base classes
using Autodesk.Aec.Arch.DatabaseServices; // ACA Architectural objects
using Autodesk.Aec.Building.DatabaseServices; // AMEP Base classes
using Autodesk.Aec.Building.Hvac.DatabaseServices; // AMEP HVAC Base classes
Or from VB.NET:

Imports Autodesk.AutoCAD.DatabaseServices ' AutoCAD database objects


Imports Autodesk.Aec.DatabaseServices ' ACA Base classes
Imports Autodesk.Aec.Arch.DatabaseServices ' ACA Architectural objects
Imports Autodesk.Aec.Building.DatabaseServices ' AMEP Base classes
Imports Autodesk.Aec.Building.Hvac.DatabaseServices ' AMEP HVAC Base classes
Resolving Ambiguities
The .NET API provides all its objects under namespace hierarchies. By default, an object is qualified
in the current scope if the namespace is imported. Because everything is qualified under a
namespace, you will find cases where objects may have the same name, but live under different
namespaces. This will confuse the standard qualification because the compiler cannot determine
which object you are specifically referring to. Fortunately both C# and VB.NET languages provide an
alias mechanism to make it easier to qualify the namespaces appropriately when necessary.

For example, there is a different object named DBObject in both ACA and AutoCAD .NET APIs. You
will see an ambiguous reference error when trying to use this type in a typical way. The reason for
this is because the object lives in both the Autodesk.AutoCAD.DatabaseServices and
Autodesk.Aec.DatabaseServices namespaces. In order to resolve the ambiguity, you must
clarify the namespace of the version you are intending to use. For example in a project that
references both AutoCAD and ACA database services, the code

DBObject obj = new DBObject();

will cause the error.

To resolve it, you can do this:


AutoCAD® Architecture and AutoCAD® MEP
.NET Programming: A Beginner's Guide

Autodesk.Aec.DatabaseServices.DBObject obj =
new Autodesk.Aec.DatabaseServices.DBObject();

But that is a lot of extra code that makes it more difficult to read and will lead to code that
unnecessarily wraps to the next line, etc.

Another way to resolve this is to use an alias. There are two ways to provide this. At a specific object
level, or at a namespace level. For example, at the object level:

using AcDBObject = Autodesk.AutoCAD.DatabaseServices.DBObject;


using AecDBObject = Autodesk.Aec.DatabaseServices.DBObject;
...
AecDBObject obj = new AecDBObject();

Or at the namespace level:

using AcDb = Autodesk.AutoCAD.DatabaseServices; // AutoCAD database objects


using AecDb = Autodesk.Aec.DatabaseServices; // ACA Base classes
...
AecDb.DBObject obj = new AecDb.DBObject();

NOTE: You can use the actual name of the object to provide the alias, too. In the case of DBObject
and DBObjectId, this strategy might make sense because the AEC versions of these are not used
very often. The drawback is that for the other type you would need to provide a different alias, or fully
qualify it. Additionally, it is not obvious which object is actually being used unless you have specific
coding standards setup. For example:

using DBObject = Autodesk.AutoCAD.DatabaseServices.DBObject;


using AecDBObject = Autodesk.Aec.DatabaseServices.DBObject;
...
DBObject obj1 = new DBObject(); // AutoCAD object
AecDBObject obj = new AecDBObject(); // Aec Object

Tip: Personally, I believe the namespace level alias is better if you plan large projects. This covers all
objects in the namespace, and it also does not change the name of the object itself, making
readability and maintenance easier over time. The drawback is that once you alias the entire
namespace; you must use the alias to reference all the objects within the namespace. It is certainly a
personal preference, but one to consider before writing a lot of code.

AutoCAD Architecture (ACA) .NET API


The ACA .NET API mirrors the OMF API and is becoming more and more complete at each release.
Currently most of the database portions are completely exposed in .NET API, so we feel you can be
confident in being able to get at all the data that you might need from the ACA object set.

NOTE: ACA also provides an ActiveX API. Please note that in some cases there may be more
functionality exposed there than is present in the .NET API. If you do hit a road-block in .NET API,
please review the ActiveX object model for additional functionality. The nice thing about the .NET
AutoCAD® Architecture and AutoCAD® MEP
.NET Programming: A Beginner's Guide

development environment is that you can use COM interop easily (as easy as making a reference)
and mix the two APIs in the same program. Some frown upon this, but there is nothing wrong with it.
The AutoCAD and AEC development groups encourage you to use COM interop when necessary. Of
course please send us feedback if you do run into limitations in .NET API.

Hierarchy
As indicated earlier, ACA is built on top of the AutoCAD .NET API. This means that ACA APIs
actually derive from the base AutoCAD functionality, and the ACA API further derives from itself to
deliver robust functionality.

NOTE: This is major difference from the ActiveX API. ActiveX, even though it has a object hierarchy,
it does not derive from AutoCAD’s base objects. It will reuse things, but there is no actual derivation.

For entities (for example Wall), the basic hierarchy is as follows:

™ Autodesk.AutoCAD.DatabaseServices.Entity

ƒ Autodesk.AutoCAD.DatabaseServices.Curve

♦ Autodesk.Aec.DatabaseServices.Entity

ƒ Autodesk.Aec.DatabaseServices.Geo

♦ Autodesk.Aec.Arch.DatabaseServices.Wall

All ACA entities (for example Wall or Door) are derived from Geo.
AutoCAD® Architecture and AutoCAD® MEP
.NET Programming: A Beginner's Guide

For objects (for example an Anchor or a Wall Style), the basic hierarchy is as follows:

™ Autodesk.AutoCAD.DatabaseServices.DBObject

ƒ Autodesk.Aec.DatabaseServices.DBObject

♦ Autodesk.Aec.DatabaseServices.Anchor

♦ Autodesk.Aec.DatabaseServices.DictionaryRecord

ƒ Autodesk.Aec.Arch.DatabaseServices.WallStyle

All style objects (for example Wall Style or Door Style) are typically derived from DictionaryRecord.

For objects that support other objects (for example, a WallModifier), these are typically derived from
an internal ACA class called ImpObject:

™ Autodesk.AutoCAD.Runtime.RXObject

ƒ Autodesk.Aec.DatabaseServices.ImpObject

ƒ Autodesk.Aec.Arch.WallModifer

Because the objects are derived from each other, we can benefit from the true object oriented nature
of having access to the specific class functionality, and all derived class functionality.

Tip: There is a freeware tool available called .NET Reflector that can help you discover and explore
the hierarchy of any .NET API assembly. This tool works very well to quickly see what’s available
through the object model. It can be downloaded from there:

http://www.aisto.com/roeder/dotnet/

AEC Drawing Variables


ACA provides settings on a per drawing basis to adjust common base values, etc. Some of these
values match-up to the AecDwgSetup dialog tabs, while others are used in combination to set other
presets.

There are currently two main drawing setting variables:

• Autodesk.Aec.ApplicationServices.DrawingSetupVariables - Exposes most of the setting


saved in the drawing database
• Autodesk.Aec.Arch.ApplicationServices.ArchDBVariables - Exposes most of the architectural
object settings

See the course sample code for detailed programming examples.


AutoCAD® Architecture and AutoCAD® MEP
.NET Programming: A Beginner's Guide

AEC Object Creation


Object creation in ACA is similar to AutoCAD entity creation. The basic steps are:

1. Allocate a new object of the type you want


2. Initialize the object
3. Set additional values (in some cases this is also required AFTER the object has be added to
the database)
4. Start a transaction (note this can be done anywhere, but must be done before attempting the
database changes)
5. Open the container where the object will reside (ie. Model Space)
6. Append the object
7. Notify the transaction of the new object and commit when finished
For example, adding a Wall would look like:

' Get the AutoCAD database


Dim db As Database = HostApplicationServices.WorkingDatabase()
' (Step 4) Starts a transaction
Dim tr As Transaction = db.TransactionManager.StartTransaction()
Try
' (Step 1) Allocate the object
Dim wall As New Wall()

' (Step 2) Initialize the object


' Initialize AutoCAD entity level defaults
wall.SetDatabaseDefaults(db)
' Initializez ACA defaults
wall.SetToStandard(db)

' (Step 3) Set any specific values


wall.Set(New Point3d(0, 0, 0), New Point3d(120, 0, 0), _
New Vector3d(0, 0, 1))

' (Step 5) Add to ModelSpace


Dim bt As BlockTable = CType _
(tr.GetObject(db.BlockTableId, OpenMode.ForRead), BlockTable)
Dim btr As BlockTableRecord = CType _
(tr.GetObject(bt(BlockTableRecord.ModelSpace), _
OpenMode.ForWrite), BlockTableRecord)
btr.AppendEntity(wall)

' (Step 6) Notify and commit the transaction


tr.AddNewlyCreatedDBObject(wall, True)
tr.Commit()

Catch ex As System.Exception
' a problem…
' call dispose to close all the open entities,
' but not commit anything to the drawing
tr.Dispose()
' lets display what the problem is
MsgBox("Error creating the wall: " + ex.Message)
End Try
AutoCAD® Architecture and AutoCAD® MEP
.NET Programming: A Beginner's Guide

See the course sample code for detailed programming examples.


Styles and Style Dictionaries
Styles are typically implemented for each entity type in ACA. The styles will derive from the base
class DictionaryRecord. Each type of style will have a style dictionary. Style Dictionaries derive from
Dictionary. A style dictionary will typically contain a GetStandardStyle method to gain access to the
default standard style for that type. In the following example, a style with a specific name is required
and it is added if not already present:

[CommandMethod("WallStyleExample")]
public void test1()
{
Autodesk.AutoCAD.EditorInput.Editor ed =
Application.DocumentManager.MdiActiveDocument.Editor;

Database db = HostApplicationServices.WorkingDatabase;
using (Transaction trans = db.TransactionManager.StartTransaction())
{
AcDbObjectId id;
DictionaryWallStyle wallstyledict = new DictionaryWallStyle(db);
try
{
id = wallstyledict.GetAt("fred");
trans.Commit();
}
catch (System.Exception e)
{
if (e.GetType() == typeof(Autodesk.AutoCAD.Runtime.Exception))
{
Autodesk.AutoCAD.Runtime.Exception acade =
e as Autodesk.AutoCAD.Runtime.Exception;
if (acade.ErrorStatus ==
Autodesk.AutoCAD.Runtime.ErrorStatus.KeyNotFound)
{
ed.WriteMessage("\nAdding the Wall style we need.");
WallStyle wallstyle = new WallStyle();
wallstyle.SetToStandard(db);
wallstyle.SubSetDatabaseDefaults(db);
wallstyle.Description = "fred style";
wallstyledict.AddNewRecord("fred", wallstyle);
trans.AddNewlyCreatedDBObject(wallstyle, true);
trans.Commit();
}
} else {
ed.WriteMessage("\nError: " + e.Message);
}
}
}
}

See the course sample code for detailed programming examples.


AutoCAD® Architecture and AutoCAD® MEP
.NET Programming: A Beginner's Guide

Special ACA initialization requirements


When initializing an ACA entity (anything derived from Autodesk.Aec.DatabaseServices.Entity), you
will need to call the following two functions:

• SetDatabaseDefaults
• SetToStandard
When initializing an ACA Object (anything derived from Autodesk.Aec.DatabaseServices.DBObject,
but is NOT an Entity), you need to call:

• SubSetDatabaseDefaults
• SetToStandard
The SetDatabasebaseDefaults function is an AutoCAD API which will establish basic entity level
properties such as layer, linetype, and color.

The SetToStandard function provides object initialization and some default values to make the
object “valid” without further initialization. The concept is that by making this call, you are guaranteed
that the object will have its data filled with valid values without any further initialization. For example,
simply allocating a wall without any further initialization will provide settings for the base height,
thickness, and cleanup radius.

Although the details are really not that important to the .NET API user, the reason for
SubSetDatabaseDefaults is because of a minor AutoCAD limitation. On the ObjectARX side,
there is a method implemented at the entity level called subSetDatabaseDefaults. The AutoCAD
framework calls this method for any derived entity when the setDatabaseDefaults is called. This
is why the AEC side does NOT require an explicit call to the subSetDatabaseDefaults for an
entity. However, there is no automatic framework for the object level, so the
SubSetDatabaseDefaults should be explicitly called in order for the object to be setup correctly
(ie. db references to other objects are often initialized here).

See the course sample code for detailed programming examples.


AutoCAD® Architecture and AutoCAD® MEP
.NET Programming: A Beginner's Guide

Anchors
Anchors are used typically to establish geometric relationships between objects. They exist as a
database object, so they are persistent and have data associated with them. For example, a door is
typically anchored to a wall at a specific location. If the wall is moved, the door stays in its position
relative to the wall. When working with objects in the context of anchoring it is a good idea to
determine if the objects are already anchored. The Geo derived objects provide a property for
determining the existing anchor called AnchorId. A typical scenario might be:

Dim geo As Geo = tr.GetObject(geoId, OpenMode.ForRead)


If geo.AnchorId.IsNull Then
' Not anchored
Else
Dim anc As Anchor = tr.GetObject(geo.AnchorId, OpenMode.ForRead)
' Further check anchor type...
End If

See the course sample code for detailed programming examples.


AutoCAD® Architecture and AutoCAD® MEP
.NET Programming: A Beginner's Guide

AutoCAD MEP (AMEP) .NET API


The AMEP .NET API provides access and creation capabilities for many of the AMEP objects. It
provides support for each of its major disciplines: HVAC, Piping, Schematic Plumbing, and Electrical.
AMEP strays from the ACA approach of providing generic user defined configurations (via styles)
because of its need to provide more rigid standard parts. These parts are defined from a catalog and
specialized APIs are required from AecbPartBaseMgd to gain access to the catalog data for use
within part manipulation..

Hierarchy
AMEP is built on ACA, so it again reuses many of the base functionalities. Because it is also
interoperable with ACA, the AMEP programmer is obviously going to want to know some of the ACA
API in order to accomplish the desired tasks.

Base classes:

™ Autodesk.Aec.DatabaseServices.Geo

ƒ Autodesk.Aec.DatabaseServices.LayoutTool

♦ Autodesk.Aec.Building.DatabaseServices.LabelCurve

♦ Autodesk.Aec.Building.DatabaseServices.Fitting

♦ Autodesk.Aec.Building.DatabaseServices.Member

♦ Autodesk.Aec.Building.DatabaseServices.MultiViewPartBase

♦ Autodesk.Aec.Building.DatabaseServices.Schematic

♦ Autodesk.Aec.Building.DatabaseServices.Segment

ƒ Autodesk.Aec.DatabaseServices.ConnectionComponent

♦ Autodesk.Aec.Building.DatabaseServices.ConnectionComponentMember

Examples from Electrical:

ƒ Autodesk.Aec.Building.DatabaseServices.Segment

♦ Autodesk.Aec.Building.Elec.DatabaseServices.CableTray

ƒ Autodesk.Aec.Building.DatabaseServices.Fitting

♦ Autodesk.Aec.Building.Elec.DatabaseServices.CableTrayFitting

ƒ Autodesk.Aec.Building.DatabaseServices.MultiViewPartBase
AutoCAD® Architecture and AutoCAD® MEP
.NET Programming: A Beginner's Guide

♦ Autodesk.Aec.Building.Elec.DatabaseServices.Device

Examples from HVAC:

ƒ Autodesk.Aec.Building.DatabaseServices.Segment

♦ Autodesk.Aec.Building.Hvac.DatabaseServices.Duct

ƒ Autodesk.Aec.Building.DatabaseServices.Fitting

♦ Autodesk.Aec.Building.Hvac.DatabaseServices.DuctFitting

ƒ Autodesk.Aec.Building.DatabaseServices.MultiSegment

♦ Autodesk.Aec.Building.Hvac.DatabaseServices.DuctFlex

Examples from Piping:

ƒ Autodesk.Aec.Building.DatabaseServices.Segment

♦ Autodesk.Aec.Building.Piping.DatabaseServices.Pipe

ƒ Autodesk.Aec.Building.DatabaseServices.Fitting

♦ Autodesk.Aec.Building.Piping.DatabaseServices.PipeFitting

ƒ Autodesk.Aec.Building.DatabaseServices.MultiSegment

♦ Autodesk.Aec.Building.Piping.DatabaseServices.PipeFlex

Examples from Plumbing:

ƒ Autodesk.Aec.Building.DatabaseServices.Member

♦ Autodesk.Aec.Building.Plumbing.DatabaseServices.SchematicPipe

ƒ Autodesk.Aec.Building.DatabaseServices.MultiViewPartBase

♦ Autodesk.Aec.Building.Plumbing.DatabaseServices.SchematicPipeFitting

A notable difference in AMEP is an additional module called AecbPartBaseMgd. This assembly


provides access to the data oriented classes allowing for access to some of the catalog data. It also
provides helper utilities for creating and modifying parts. This module provides only Application
Services.

AMEP Part Catalog


The part catalog is the heart of the AMEP platform. It is here that all parts are stored. In order to use
the Part Catalog, we need to add a reference to: AecbPartBaseMgd.dll
AutoCAD® Architecture and AutoCAD® MEP
.NET Programming: A Beginner's Guide

This assembly has methods needed to query, create and modify AMEP parametric parts.

DataPartLookup - Contains information about parts such as name, GUID and Path

DataPartLookupCollection - List container of DataPartLookup objects.

DataQuery - Represents the query object for accessing the underlying xml files. This is where you
can specify how granular you want your results.

DataRecord - Represents a row of data made up of DataFields

DataExpandedTable - The expanded table represents the results of the query. It will contain 0 to N
records based on the specifics of the DataQuery. You may limit the number of items returned by
providing a max search in the call: PartManager.GetPartTable(query, maxRecords);

DataField - The Datafield class represents the container object for the data. The datafield can hold
the following types:

• Boolean
• Double
• Integer
• ObjectId
• String

DataFieldCollection - Collection of the Datafields in a DataRecord. This class also contains the
methods for finding specific DataFields in the collection. For example:

DataField dfCustom = record.DataFields.FindByContext(Context.CustomData);

Part Manager
The part manager provides static methods that help you to perform queries, part creation and
modification.

The PartManager class is responsible for all data associated with parts. Through the PartManager
you are able to add, query and modify the parts. It provides the following helpers:

• CreatePartEntityViaStyle - Creates a style-based part from a catalog drawing and symbol


name.
• CreatePartViaQueryParameters - Accepts a query and creates a part using the first valid
combination of parameters.
• CreatePartViaRecord – Creates a specific part based on data record..
• GetEngineeringData - Gets the engineering data from a member derived object.
• GetPartData - Gets the part data from a member derived object.
• GetPartsList - Accepts a data query and finds the list of parts.
AutoCAD® Architecture and AutoCAD® MEP
.NET Programming: A Beginner's Guide

• GetPartTable - Accepts a data query and finds the expanded table containing the parts
matching the query.
• ModifyPartViaQueryParameters - Accepts a query and modifies a part using the first valid
combination of parameters.
• ModifyPartViaRecord - Accepts a data record and expanded table to modify a specific part.

Queries
A query is something you will use to get access to the catalog data and connect it to a part. The
quickest and easiest way to drill down into the 1000s of parts available is to use a Part GUID. Each
part will have a GUID, but it is not enough information to identify the specific part based on size and
other attributes. In order to drill further down into the parts available, it is helpful to know the part
GUID ahead of time. The easiest way to browse the catalog from a GUID standpoint is to open the
XML files or write code to iterate over everyting.

See the course sample code for detailed programming examples.

Creating a Part
As compared to the ACA style of creating objects, AMEP requires the extra level of information from
the catalog to correctly establish the part. This is handled through the PartManager class and
involves querying the catalog for the specific part catalog data. Here are the steps to create a part:

1. Query the catalog to find the part data.


2. Allocate a new object of the type you want
3. Initialize the object
4. Start a transaction (note this can be done anywhere, but must be done before attempting the
database changes)
5. Use the Part manager to connect the catalog data (obtained from the query) to the part.
6. Set additional values (in some cases this is also required AFTER the object has be added to
the database)
7. Open the container where the object will reside (ie. Model Space)
8. Append the object
9. Notify the transaction of the new object and commit when finished
See the course sample code for detailed programming examples.

Modifying a Part
To modify a part, it is very similar to the create part strategy. Again, you must perform a query to get
the correct catalog data, and then tell the PartManager of the new data.
AutoCAD® Architecture and AutoCAD® MEP
.NET Programming: A Beginner's Guide

1. Query the catalog to find the part data.


2. Get an existing entity that you want to modify
3. Start a transaction (note this can be done anywhere, but must be done before attempting the
database changes)
4. Use the Part manager to connect the catalog data (obtained from the query) to the existing
part.
5. Commit the transaction when finished
See the course sample code for detailed programming examples.

Part Relationships
In AMEP the parts are usually linked together to form a system. You can use the objects to determine
what they are connected to, and then iterate over everything to find out the entire system’s set of
parts. The relationships are governed by the ConnectionComponentMember. Each object derived
from member (ie. Duct, CableTray, Pipe) will have this method and it will return a collection of
ConnectionComponentMembers.

See the course sample code for detailed programming examples.


AutoCAD® Architecture and AutoCAD® MEP
.NET Programming: A Beginner's Guide

Resources
Help files
ACA and AMEP Managed Help Files located in the <install dir>\Help directory. There is a single
umbrella help that contains access to all the sub-files.

For ACA see: <install dir>\Help\adtmgd.chm

For AMEP see: <install dir>\Help\absmgd.chm

Samples

There are several samples located in the CS.NET and VB.NET folders at <install dir>\Samples.

AecDisplayMgd – This is a new sample that demonstrates some of the display capability of the .NET
API.

AecHardwiredStylesMgd – This sample sets up all the styles to have default values.

AecProjectBaseMgd – This provides an example of how to navigate the project’s file system.

AecPropertyGridMgd – This is the reflection sample referred to earlier.

AecPropertySampleMgd – This sample demonstrates many property data techniques.

AModelerSampleMgd – This sample provides a variety of examples showing how to utilize the AEC
modeler.

AecSpaceOffsetStandardBasic – This is a sample specific to the Spaces features. It shows how to


create a custom offset standard. Note that it is “consumed” differently than the other samples and is
only useful for the spaces feature specifically. See the ACA Documentation for more information.

Support
The discussion forums are a good place to get help from colleagues.

ACA has a specific customization forum here:

http://discussion.autodesk.com/forum.jspa?forumID=54

Currently AMEP has only one main forum located here:

http://discussion.autodesk.com/forum.jspa?forumID=61

To become a developer (and receive developer support) see the ADN Site:
http://www.autodesk.com/adn

You might also like