If you’ve worked with me or talked technical with me in the past there is a good chance you area already very aware that I love Log4Net. There is also a really good chance that you know I still have a special place in my heart for Visual Lisp. Not only did I spend what may have been the “best years of my life” buried in VLIDE (or hey, maybe all those 30+ hour days and passing out under my desk were the best years of my life? =)) , I still firmly believe that Lisp is one of the most effective way to bang out even a relatively complex operation in AutoCAD when it comes to data manipulation. ObjectARX (both original and .NET) is great – but the time and effort overhead is pretty high when you just need to bang out a quick routine.
<3 Visual Lisp
Even the quick routines need a little error handling and logging can make a huge difference in documenting the results or diagnosing problems. Yes, Visual Lisp comes with file I/O calls and I’m sure most of you reading this have rolled your own logging code. We had some at Kanotech that is still in use for DraftLogic. Not for long though :=) Today I’m here to show you how you could bring your Visual Lisp logging into the 21st century. Not only will it give you insanely robust and configurable logging – it will let even complex systems that mix technologies (ie. Visual Lisp, ObjectARX .NET) to bring the logging together into a common set of log files.
There are two sides to this. First, in .NET we setup Log4Net and expose it to Visual Lisp. Over on the Lisp side, we’ll load the vlx, setup an error handler, and issue some logging calls. As usual I’ve attached a Visual Studio solution with sample code. I’ve also included a compiled dll that you can just go ahead and use. The attached project is built using .NET 3.5 as this machine only has AutoCAD 2010 installed. Log4Net itself is built targeting .NET 1.0 so you can modify the .NET runtimes and ObjectARX references used in the attached project and use this code for pretty much any .NET enabled version of AutoCAD/ObjectARX.
In .NET – Setup Log4Net and Lisp Bindings
The Lisp bindings are pretty straight forward. Expose your call(s) to AutoCAD as a LispFunction. I’ve built two exposed calls. One takes two parameters, and uses the value of the first parameter to determine the log type. The second parameter is the message to log. The second call is a LogError call that could be used to just log error type messages. This call could be duplicated for each type of logging state if desired.
One awesome little bit of magic exists in the Logger.cs class. When configuring the logger it loads the assemblies in question using System.Reflection. Then it checks in the folder of each loaded dll for the log4net.config file. This means that logging will only actually log if you have a log4net.config file exists in the same folder as the loaded ObjectARX.NET assembly. With AutoCAD based extensions this is especially important. I’ve never liked placing my assemblies (vlx, arx, dll) in the AutoCAD folders. I’ve always been a huge proponent of extending the AutoCAD search path if needed and using my own directory structures. This configuration searching technique also eliminates the need for hard coded “here is my log config file” stored in the registry or some other config location.
Compile that dll and you should be able to run with that in Visual Lisp.
Configure the Logging
As mentioned previously we need to create the configuration file to place with our dll. There are a couple of lines of code that are quite relevant to get the logging working. First we have a hard coded configuration file name defined in Logger.cs. You can customize this if you want.
Next is the name of the logger. This is quite relevant when configuring your logging. If this value does not match the value in the config file you will be very frustrated trying to get the logging to fire! If desired change the VisualLisp value to whatever you would like.
Next we have a little bit of XML to slough through.
This is where things can get crazy! First the appender section. This is where you define all the different settings for the actual logging. I’m running with a standard log file appender, but there are so many choices. Log to file, log to rolling file, log to database, log to e-mail, log to eventlog, log to almost whatever you want. You can even write your own custom appenders to log to your toaster oven if you really wanted to. This is one of the many reasons I <3 Log4Net soooo much. The basics here are straight forward. Set the file value=”” to the name and optionally path (either full or relative). One important note., if you do not specify a full path or you use a relative path the logfile the base point used will be the AutoCAD program files folder. If you are not running with administrative rights the Vista/Windows 7 file system virtualization will kick in and the log file location will be quite confusing. It’s probably a good idea to specify a full path here. More details on some Log4Net configurations can be found on the Log4Net site.
Next take a look at the logger element. You can define multiple loggers, and each can log to multiple appenders. Or a single logger can log to multiple appenders. Note the important value of “Visual Lisp”. This must match the GetLogger value defined in the private ILog above. You can also specify which “level” of notice to log. Though our code may log INFO, WARNING, DEBUG and ERROR calls – if your level is set to ERROR – only the actual error level messages will be logged.
In Visual Lisp – Setup an Error Handler and Issue Logging
So now we have an ObjectARX.NET assembly to load. We have a handle on configuring our logging. Here is the contents of the included Lisp file.
Not much to it. To prevent some command line spewage if you load the assembly twice we check first to see if the function has already been exported to the environment. Here we’ve setup a new error handler that differentiates between a function cancellation and an actual error. At the bottom you can see a couple of examples of the logging. If you’ve defined your log4net.config file in the same folder as the assembly if you load this lisp file you will see a log file get created.
So in review – we’ve exposed Log4Net to the Visual Lisp and command line environment inside of AutoCAD. This will allow you to unify your logging (if you are already using Log4Net) and may even make you a Log4Net enthusiast as well. As always I’m always interested in your feedback and constructive criticism!