Building a commercial grade lisp plugin installer in 5 easy steps

Rumors about the death of AutoLISP have been floating around for many years, but fear not, those rumors are greatly exaggerated. Bricscad and ZWCAD both have excellent support for lisp plugins, so well-written lisp code is truly cross-platform and enjoys a large and growing audience. Unlike other languages, the vast majority of lisp code works unmodified on any hardware architecture, in any version of Windows, and inside any host application that supports it, including AutoCAD versions released more than a decade ago. On top of that, OpenDCL gives lisp developers the power of a modern event-driven user interface that can put their lisp plugins on the same playing field as plugins written in any other language. This is a powerful combination, and given lisp’s low entry cost, it is not surprising to see lisp continuing to enjoy strong support in the developer community.

There’s just one thing missing: an easy way to install a lisp plugin on an end user’s computer. It’s a common refrain. How do you build a setup program for a lisp plugin? There are any number of free and low-cost installers available, but they are all designed for installing an executable program, not a plugin that must be configured to run inside a completely independent host application.

At one time there was a package called AcadInstall that was designed for AutoCAD add-ons, but that tool is long defunct. Autodesk has invented application bundles with the supposed benefit of making it easier to install and manage plugins, but these are not well documented and only work with recent versions of AutoCAD. For ManuSoft plugins, I use Visual Studio’s Setup and Deployment projects along with an extensive amount of custom C++ code to perform all the configuration necessary at install time. This works great for my needs, but it is well beyond the ability of most lisp developers.

After several recent online discussions with lisp developers struggling to get a working setup program, I set out to find a solution to this vexing problem. It turns out that after some initial work it’s actually not that hard to pull off a very professional looking setup program for a basic lisp plugin. In fact, if you follow these steps, in less than 10 minutes (5 minutes if you have a fast internet connection) you will have a working setup that installs a lisp plugin on any version of AutoCAD, Bricscad, or ZWCAD+. The best part: everything you need is free (as in beer)!

So, let’s get to it.

  1. Download and install Unicode Inno Setup QuickStart Pack from the Inno Setup Downloads page.
  2. Download my LispPluginSetup freebie and extract the files into a new folder somewhere.
  3. Download my LspLoad freebie and extract the files into a new subfolder named LspLoad.
  4. Double click on MyLispPlugin.iss. It should open in Inno Script Studio. Choose Project -> Compile.

At this point you should have a new Output subfolder with MyLispPluginSetup.exe inside. Go ahead, run it. After you’ve installed the MyPlugin sample, start the host application of your choice (the setup program configures all of them). If all went well, MyLispPlugin should display a command line message at startup alerting you to the fact that MYCOMMAND1 and MYCOMMAND2 are now available for use. Go ahead, try them. When you’re finished playing, it should uninstall cleanly (except for the new addition to TRUSTEDPATHS in AutoCAD 2014) when you choose Start -> MyCompany -> MyLispPlugin -> Uninstall My Lisp Plugin.

That was almost too easy, right? Well, not so fast. You’ll need to make some changes to adapt the sample for your own plugin. Take a look at the installation script in Inno Script Studio. Click on the Inno Setup Script item in the project tree to see the entire script as a flat file. Right near the top of the script, it should be obvious that you’ll need to change the basic plugin information preprocessor constants to adapt the script for your own plugin. Obviously your plugin will have a different base filename, and quite probably more files. It may have more registry keys and other basic setup stuff. In addition, you may not want to support all possible versions and flavors of each host app (in that case you’ll need to comment out or remove the associated item in the Files section). You get the idea, I’m sure.

Step 5 is modifying the sample script to adapt it for your own plugin. So easy, even an engineer could do it!

QuirkyPolyline: exposing foolish programmers

In AutoCAD, the AcDbCurve class defines a general parametrized curve. On a parametrized curve, points in space are mapped to real numbers (parameters) by an arbitrary function F(p) for values of p from the curve start parameter to the curve end parameter. Defining a curve this way simplifies working with complex 3D curves because one can work in the curve’s one dimensional “parameter space” instead of the more complex three dimensional cartesian space.

The choice for how to parametrize a curve entity is up to the implementor. Parameters are designed to be opaque, so consumers of parametrized curves must make no assumptions about how a specific curve implements them. The only thing guaranteed about the parameters of a curve is that all points on the curve map to a unique parameter in a continuous range from the starting parameter to the ending parameter.

AutoCAD entities such as lines, circles, arcs, polylines, rays, and others are derived from AcDbCurve. These basic curve entities have very simple and straighforward parameter mappings that can be reverse engineered with very little effort, so lazy programmers sometimes make assumptions that are not guaranteed to always be true. Even smart programmers often get tripped up on parametrized curves because they use parameter space when they should be using distance space (that is, distance along the curve). The AcDbCurve interface provides functions to translate from parameter space back and forth to distance space, as well as back and forth to three dimensional cartesian space.

Wise programmers always let the curve itself perform all translations to or from distance space or cartesian space so that their code never relies on the actual value of a parameter. Foolish programmers take shortcuts by making assumptions about parameter values. For example, it happens that in all past versions of AutoCAD, the parameter of the midpoint of a polyline segment is exactly halfway between the segment starting parameter and the segment ending parameter, and the segment starting and ending parameters are always equal to the index number of the corresponding vertex. A foolish programmer (e.g. here and here) may use this knowledge to calculate the midpoint of the segment by guessing it’s parameter. The foolish programmer’s code will fail when a case arises where that guess is wrong. It is the purpose of QuirkyPolyline to provide such a case.

QuirkyPolyline defines a QPOLY command that prompts for a selection set of lightweight polylines in AutoCAD, then converts the selected polylines to “quirky polylines” that expose a completely different parameter scheme. Quirky polylines look and act perfectly normal in all respects. If you save quirky polylines, they will be stripped of their quirkiness. There are no long term effects of making polylines quirky; it’s just a temporary change that wears off on its own.

Making quirky polylines is useful for testing code that works with parametrized curves. If your code makes assumptions that it shouldn’t, quirky polylines will expose the error of your ways. Over the years, I have had arguments with people who insisted that their assumption had been validated by extensive testing. My counterargument is that someone, somewhere (possibly even Autodesk itself) already has or eventually will generate a derived entity where the assumption is not true. In addition to providing a proving ground, QuirkyPolyline is designed to demonstrate to the naysayers that unusual parametrization implementations can exist in the wild.

The download contains ARX modules for AutoCAD 2000 through AutoCAD 2015. To use QuirkyPolyline, just load the module that matches your version and architecture of AutoCAD. Create a lightweight polyline with the PLINE command, then use the QPOLY command to convert the normal polyline to a quirky polyline. You can use the LIST command to verify that it did become quirky, but you should notice no other detectable changes.

[Note: the download has since been updated and moved to the ARX freebies page]

Here is a useful little lisp function that defines a PP command for displaying the parameter value of a picked point on a selected curve entity. You can use this to explore other curve entities, and to see how the polyline’s parametrization changes after it becomes quirky.


(vl-load-com)
(defun C:PP (/ sel pointoncurve param)
(if (setq sel (entsel))
(progn
(setq pointoncurve (apply 'vlax-curve-getclosestpointto sel))
(setq param (vlax-curve-getparamatpoint (car sel) pointoncurve))
(princ (strcat "nParam = " (rtos param)))
)
)
(princ)
)

I hope this helps you avoid the pitfalls of parametric curve code. Remember, don’t be a foolish programmer!

RoboCache for Windows offline files cache management

I’ve written before about RoboCache, a command line utility I wrote for managing the offline files cache in Windows Vista, Windows 7, and now Windows 8. After using the utility internally for a few years, I decided that I might as well clean it up and make it available to the rest of you. RoboCache is now available at the ManuSoft web site. There is a shareware version available, and you can purchase the registered version at the ManuSoft store (cost is 25 USD for a single user license).

It’s nothing fancy, but it works great for my needs. The command syntax is modeled after the ROBOCOPY command, and is designed for handling an entire directory tree recursively, filtering files and folders by wildcard. My typical use case is running it from a batch file to pin remote Visual Studio project files on my laptop before travelling. Visual Studio project folders contain a lot of temporary build files and output files that don’t need to be (and therefore shouldn’t be) included in the cache. The goal is to pin only the necessary files, ignoring the ones that are not needed or will be recreated when the project is built. Here’s a sample call to recursively pin all files in the ‘Build’ folder (this is all one line in a batch file executed from the laptop):

ROBOCACHE Build /op:pin /s /xd debug* release* x64 Win32 .svn _* obj bin ipch /xf *.log *.tlog *._ls *.ncb *.user *.suo *.aps *.ilk *.pch BuildLog.htm *.err *.dmp *.pdb !*.bat #*.bat *.chm *.dia *.aps *.lnk *.Res.dll *.zip *log.txt *report.txt *.winmerge *.sdf *.opensdf

Programmers might notice that the /xd (ignore directories) and /xf (ignore files) wildcard lists look very similar to what one might encounter in a Subversion commit script. In fact, when I created the batch file I just copied and pasted from my SVN ignore lists. For me, the benefit of using RoboCache in this way is that only the minimum needed files are cached. After working on the cached files while I’m out of the office, my changes automatically sync to the folders on my desktop when I return to the office. I do use Subversion repositories for all my projects, and could just as well commit my remote changes to the repository, then update my desktop from the repository; however by using the offline files cache, the syncing all happens automatically and I never have to think about it.

RoboCache can do more than just pin and unpin files. It can perform any of ten operations on the target files (or any of four administrative functions on the files cache itself), including some operations that are not exposed through the Windows user interface. Below is a list of all currently supported operations (captured from the help screen, and not showing the available command line options for each operation).

/OP:cmd :: OPeration to perform (default is /OP:info).
:: info : display status info about the target(s)
:: pin : assure offline availability
:: unpin : unpin the target(s)
:: sync : synchronize cached files with remote files
:: rename : rename cached item (requires reboot)
:: delete : delete cached item
:: suspend : suspend the target folders (ignores files)
:: unsuspend : unsuspend the target folders (ignores files)
:: online : transition to online state
:: offline : transition to offline state
:: enable : enable offline files cache (ignores target)
:: disable : disable offline files cache (ignores target)
:: encrypt : encrypts offline files cache (ignores target)
:: decrypt : decrypts offline files cache (ignores target)

The installer simply adds RoboCache.exe to your system folder; no folders are created and no other changes are made. The shareware version of RoboCache displays a nag notification balloon in the system tray, but is otherwise completely functional. There is no separate documentation, however ROBOCACHE /? displays syntax and command options.

ObjectARX Wizard for Visual Studio 2010

If you’re an ObjectARX programmer, you may still be using Visual Studio 2008 because you’ve been told that you must. It’s true that you need Visual Studio 2008 installed to compile native ObjectARX code, but with Daffodil you can do all your work in the Visual Studio 2010 IDE.

Until now, the one thing that didn’t work in VS 2010 was the ObjectARX Wizard. I’m happy to report that the latest wizard seems to works fine in both VS 2008 and VS 2010. Thanks to Alexander Rivilis for revealing the secret URL:
http://images.autodesk.com/adsk/files/objectarx_2012_wizards.zip

AutoCAD 2012 InfoCenter

If you’re upgrading to AutoCAD 2012, don’t forget to also disable InfoCenter (unless you really need it). Just download and install AcadInfoCenterOff to disable it on any version of AutoCAD or AutoCAD LT. If you already have AcadInfoCenterOff installed, you can just run a repair install to apply it to a newly installed instance of AutoCAD 2012.