Before we dive into the implementation of “Colibra” (Civil Object Library), I want to dedicate a post to the analysis of ‘TinyRunner’ included in the sample code that you can download here. ‘TinyRunner’ is the driver application that will allow us to execute the unit tests we implement for “Colibra”, but more interesting is that ‘TinyRunner’ is an extension application in itself. Looking at the implementation of ‘TinyRunner’, we can discover the basics to implement an extension to AutoCAD Civil 3D.
If you open the ‘TinyRunner’ project inside the “Colibra” solution in Visual Studio, you will find three source files. We will discuss two of them in this post; ‘TinyRunnerApp.cs’ which implements the ‘TinyRunnerApp’ extension application class, and ‘TinyRunnerCommands.cs’, which implements the ‘TinyRunnerCommands’ class where we will implement the extension commands.
The Extension Application Class
Let’s take a look at ‘TinyRunnerApp’ implemented in ‘TinyRunnerApp.cs’. As you can see, there is not much code in this file, but the few lines in it are very important.
using System; using Autodesk.AutoCAD.Runtime; [assembly: ExtensionApplication(typeof(TinyRunner.TinyRunnerApp))] namespace TinyRunner { public class TinyRunnerApp : IExtensionApplication { public void Initialize() {} public void Terminate() {} } }
At line 3, we introduce the ‘Autodesk.AutoCAD.Runtime’ namespace. This interface provides the definition of the ‘ExtensionApplication’ attribute. This attribute is used to specify which class implements the ‘IExtensionApplication’ interface, which becomes the entry point to our extension. The important piece to understand is that this attribute allows AutoCAD Civil 3D (or any other AutoCAD based vertical) to find the main extension class. If we do not use this attribute, your extension will be loaded, but AutoCAD Civil 3D will have to search your DLL for the extension application class, which can become very inefficient if you have a lot of types declared in your DLL.
As you can see at line 9, we declare the ‘TinyRunnerApp’ class, which implements the ‘IExtensionApplication’ interface. The ‘IExtensionApplication’ interface requires the implementation of two methods: ‘Initialize()’ and ‘Terminate()’. The ‘Initialize()’ method is called when our DLL is loaded by AutoCAD Civil 3D. Usually, you will implement any initialization required by your application in this method. This is a good location to acquire resources that will be needed by your application.
‘Terminate()’ is called when your DLL is going to be unloaded. Unfortunately, AutoCAD Civil 3D does not allow to manually unload .NET assemblies; therefore, ‘Terminate()’ will be called when the application closes. You should implement ‘Terminate()’ to free any resources you allocated during initialization.
Declaring Extension Commands
Most likely, your application will implement new commands that will need to be registered. You can specify multiple classes that implement commands by using the ‘CommandClass’ attribute. Similar to the ‘ExtensionApplication’ attribute, ‘CommandClass’ helps AutoCAD Civil 3D to find classes that implement commands. Command classes do not require implementing any special interfaces, but command methods should be declared using the ‘CommandMethod’ attribute to register the command.
using System; using System.IO; using System.Reflection; using Autodesk.AutoCAD.Runtime; using TinyTest; [assembly: CommandClass(typeof(TinyRunner.TinyRunnerCommands))] namespace TinyRunner { public class TinyRunnerCommands { [CommandMethod("RunTests")] public void RunTests() { } [CommandMethod("RunFrameworkTests")] public void RunFrameworkTests() { // Set current directory to the directory of this module. // string currentDirBackup = Directory.GetCurrentDirectory(); Assembly thisAssembly = Assembly.GetExecutingAssembly(); string assemblyDir = Path.GetDirectoryName( thisAssembly.Location); Directory.SetCurrentDirectory(assemblyDir); AutoCADCommandLineResultsCollector collector = new AutoCADCommandLineResultsCollector(); XMLConfiguration configuration = new XMLConfiguration( "Framework Testing.xml"); TestEngine engine = new TestEngine(configuration); engine.Execute(collector); // Restore the current directory. // Directory.SetCurrentDirectory(currentDirBackup); } } }
‘CommandClass’ and ‘CommandMethod’ are declared in the ‘Autodesk.AutoCAD.Runtime’ namespace, so we introduce it at line 5. ‘CommandClass’ takes a ‘Type’ object indicating the type of our command class. There are several overloads to the ‘CommandMethod’ constructor. The simplest overload just takes a string representing the command name (what users can type at the AutoCAD Civil 3D command line). Other overloads allow you to customize the behavior of the command, as well as specify globalization and localization options. I recommend you review the AutoCAD Developer’s Guide for more information about ‘CommandMethod’.
The extension application and command classes are the basics to implement AutoCAD Civil 3D .NET extensions. Make sure you learn and understand them because you will be using them all the time. In future posts, we will start working on “Colibra” and adding functionality to the library. Once we have the basics, we can implement new tools and utilities using the concepts that we learned today.

Subscribe
Mike,
Great ideas for the blog. Question on sample code, pretty much all the other sources I see for C3D programming is done in VB (subassemblies, AU examples, etc), your example above is C#.
I know most full bore programmers are C# sharp guys, but most engineers I know that are programming solutions use VB (since they are familiar with VBA & VB6).
Are you going to stick with C#?
Code translators work pretty well with everything but Event handlers between the 2 languages, could you show both languages when dealing with event handlers?
Thanks,
Posted by: Mike | 03/23/2011 at 06:29 AM
I am thinking about it. I know translators work fine; I've used them in the past for some of my classes. It is more about how much needs to be translated. Which are the important pieces that will need translation for illustration.
Now, you can still work in VB.NET using the library (once there is any functionality there).
Posted by: Isaac Rodriguez | 03/23/2011 at 06:49 AM