Initialization code in your AutoCAD .NET application
It's very common to need to execute some code as your application modules are loaded, and then to clean-up as they get unloaded or as AutoCAD terminates. Managed AutoCAD applications can do this by implementing the Autodesk.AutoCAD.Runtime.IExtensionApplication interface, which require Initialize() and Terminate() methods.
During the Initialize() method, you will typically want to set system variables and perhaps call commands which execute some pre-existing initialization code for your application.
Here's some code showing how to implement this interface using VB.NET:
Imports Autodesk.AutoCAD.Runtime
Imports Autodesk.AutoCAD.ApplicationServices
Imports Autodesk.AutoCAD.EditorInput
Imports System
Public Class InitializationTest
Implements Autodesk.AutoCAD.Runtime.IExtensionApplication
Public Sub Initialize() Implements _
IExtensionApplication.Initialize
Dim ed As Editor = _
Application.DocumentManager.MdiActiveDocument.Editor
ed.WriteMessage("Initializing - do something useful.")
End Sub
Public Sub Terminate() Implements _
IExtensionApplication.Terminate
Console.WriteLine("Cleaning up...")
End Sub
<CommandMethod("TST")> _
Public Sub Test()
Dim ed As Editor = _
Application.DocumentManager.MdiActiveDocument.Editor
ed.WriteMessage("This is the TST command.")
End Sub
End Class
And here's the equivalent code in C#:
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.EditorInput;
using System;
public class InitializationTest
: Autodesk.AutoCAD.Runtime.IExtensionApplication
{
public void Initialize()
{
Editor ed =
Application.DocumentManager.MdiActiveDocument.Editor;
ed.WriteMessage("Initializing - do something useful.");
}
public void Terminate()
{
Console.WriteLine("Cleaning up...");
}
[CommandMethod("TST")]
public void Test()
{
Editor ed =
Application.DocumentManager.MdiActiveDocument.Editor;
ed.WriteMessage("This is the TST command.");
}
}
A few notes about this code:
.NET modules are not currently unloaded until AutoCAD terminates. While this is a popular request from developers (as it would make debugging much simpler), my understanding is that this is an issue that is inherent to the implementation of .NET - see this MSDN blog post for more information.
What this means is that by the time the Terminate() method is called, AutoCAD is already in the process of closing. This is why I've used Console.Write() rather than ed.WriteMessage(), as by this point there's no command-line to write to.
That said, you can and should use the Terminate() callback to close any open files, database connections etc.
Something else you might come across when implementing this... I've implemented a single command in this application for a couple of reasons: in my next post I'm going to segregate the command into a different class, to show how you can tweak your application architecture both to follow a more logical structure and to optimize load performance.
The second reason I added the command was to raise a subtle you might well hit while coding: you might see the initialization string sent to the command-line as the application loads, but then the command is not found when you enter "TST" at the command-line. If you experience this behaviour, you're probably hitting an issue that can come up when coding managed applications against AutoCAD 2007: there's been a change in this version so that acmgd.dll is loaded on startup, and under certain circumstances this assembly might end up getting loaded again if found on a different path, causing your commands not to work.
The issue can be tricky to identify but is one that can be resolved in a number of ways:
- Edit the Registry to disable the demand-loading "load on startup" of acmgd.dll (a bad idea, in my opinion - it's safer not to second guess what assumptions might have been made about the availability of core modules)
- Make sure AutoCAD is launched from its own working directory - commonly this issue is hit while debugging because Visual Studio doesn't automatically pick up the debugging application's working directory
- Set the "Copy Local" flag for acmgd.dll to "False". "Copy Local" tells Visual Studio whether the build process should make copies of the assemblies referenced by the project in its output folder
My preference is for the third approach, as on a number of occasions I've overwritten acmgd.dll and acdbmgd.dll with those from another AutoCAD version (inadvertently trashing my AutoCAD installation). This usually happens when testing projects across versions (projects that's I've set to output directly to AutoCAD's program folder, for convenience), and I've forgotten to change the assemblies references before building.
So I would actually set both your references to acdbmgd.dll and acmgd.dll to "Copy Local = False". You can do this either by selecting the Reference(s) via the Solution Explorer (in C#) or via the References tab in your Project Properties (in VB.NET) and then editing the reference's Properties.

Subscribe via RSS
Hi Kean,
First of all, I would like to thank you for having such a fantastic source of information on the AutoCAD .NET API. I found it to be the best resource to get started with AutoCAD .NET programming.
My question is the following: my app needs to create a toolbar. I want the toolbar to load on startup, so I created it at my IExtensionApplication implementation class. I can see the toolbar when AutoCAD starts up, but once the Initialize() method is executed, the toolbar hides again. So I am wandering if this is the right place to create the toolbar.
Thanks in advance :-)
Rubén D.M.
Posted by: Ruben | January 17, 2007 at 09:28 AM
Hi Rubén,
Thanks for your feedback - very nice of you.
I'd suggest posting some code reproducing the problem to the AutoCAD .NET discussion group and sending me the URL by email (otherwise, if you're an ADN member, submit the project via DevHelp Online and email me the case ID).
Regards,
Kean
Posted by: Kean | January 17, 2007 at 02:27 PM
Hello,
I create a VB.NET program that call autocad 2004
network version, and I run a lisp rutine.
few days ago I install Autocad 2007, now if I have open 2007, run a new sesion for autocad 2007, but I just want my Vb.Net program that work
with 2004 network version.
if any way to call a specific version of autocad from VB.NET.
Thank you.
Posted by: Alberto Benitez | August 08, 2007 at 04:54 PM
Hi Alberto,
Unfortunately it's not clear to me what exactly you need help with, and neither does it appear related to this post...
Please submit a more detailed description either to one of the discussion groups, or to the ADN team, if you're a member.
Regards,
Kean
Posted by: Kean | August 08, 2007 at 06:55 PM
Hi Kean,
I'm wondering what state the document (and/or application) is in when the initialize method fires. My first guess would be that it is locked/busy, and therefore any code which attempted to read from the Database would fail due to the document being locked?
Posted by: David Osborne | November 13, 2008 at 02:44 AM
I'm amazed... All the other things I ever tried, like calling a SetVars routine from the MNL file or the ACADDOC.lsp, would always fail saying there was a lock violation when I tried to read an Extension Dictionary on AutoCAD startup, or on DocumentActivated. I netload my dll from an MNL file so this initialize method executed even before the ACADDOC.lsp, but it works this way...no lock violation.
BTW, I don't think I'm going to be able to make AU 2008, but if you ever find yourself in the Denver, CO area with some time to kill, I definitely owe you a beer. Actually a person could die from alcohol poisoning if you drank all the beers I owe you in one sitting ;-)
Posted by: David Osborne | November 13, 2008 at 03:26 AM
A great question. You actually can't rely on the document being ready for you to do anything much at all - if your module is set up to load on AutoCAD initialization, there's no guarantee you even have an active document.
What I tend to do is to P/Invoke ads_queueexpr() to fire off a command with my initialization stuff:
[assembly: ExtensionApplication(typeof(MyNamespace.Application))]
namespace MyNamespace
{
class Application : IExtensionApplication
{
[DllImport("acad.exe", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)]
extern static private int ads_queueexpr(string strExpr);
public void Initialize()
{
ads_queueexpr("(command \"_INITMYAPP\")");
}
...
This seems worthy of a follow up post (one for the list).
Kean
P.S. Sounds like a great offer... haven't been to the mile-high city in many moons, but then you never know. :-)
Posted by: Kean | November 13, 2008 at 09:00 AM