Registering an ARX/BRX module as a COM server

If you’re developing ARX modules that need to be registered as a COM server, you’re faced with some decisions about how to register them. In the old days before anyone cared about user permissions, registration could be safely accomplished at runtime, even via AutoLISP. Unfortunately runtime COM server registration just doesn’t work reliably any more under limited user accounts, not to mention registry redirection on 64-bit platforms. There is only one reliable way to register COM servers, and that’s doing it at install time under elevated privileges.

A normal Windows application might accomplish install-time registration by calling RegSvr32 after the files are copied to the destination folder, but this doesn’t work with ObjectARX or BRX modules. The reason it doesn’t work is because ARX modules cannot be loaded outside the AutoCAD or Bricscad process. RegSvr32 will fail with errors like “The module <filename> failed to load” or the even less helpful “The specified module could not be found.” There are some kludgy ways to get RegSvr32 to work anyway, but the simplest and most reliable way to solve this problem is to forget RegSvr32 and just add the needed registry values manually into your installer script. It’s not difficult, though it might be time consuming initially if your server implements a lot of COM objects.

At a minimum, a COM server must register at least one COM class under HKCRCLSID. If the COM server needs to support OLE Automation (e.g. VBA, AutoLISP) it must register a type library in HKCRTypeLib. In most cases, this is all that is needed, however you may also need to register a “ProgID” in HKCR if a script or in-process module needs to be able to connect to the server via human-readable ProgID.

Most installation script software can import Windows registry script (.reg) files, so it’s often helpful (and more maintainable) to create a registry script file manually, then simply import the .reg file into the installation script. If you use Visual Studio deployment projects, this is the only way to batch import registry values into the installation script. I’ve provided a minimal template for a registry script that registers a single COM object and ProgID. The template uses special characters as placeholders for the actual values: $$ is the human readable ProgID name, ## is the COM object’s CLSID, ** is the filename of your ARX module, and %% is the type library GUID. The type library and object class version numbers should match your actual version numbers as well, and of course [TARGETDIR] is the installation target directory that will be resolved at install time.

Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT$$.1]
@=”$$ Class”

[HKEY_CLASSES_ROOT$$.1CLSID]
@=”{##}”

[HKEY_CLASSES_ROOTCLSID{##}]
@=”$$ Class”

[HKEY_CLASSES_ROOTCLSID{##}InprocServer32]
@=”[TARGETDIR]**.arx”
“ThreadingModel”=”Apartment”

[HKEY_CLASSES_ROOTCLSID{##}ProgID]
@=”$$.1″

[HKEY_CLASSES_ROOTCLSID{##}Programmable]

[HKEY_CLASSES_ROOTCLSID{##}TypeLib]
@=”{%%}”

[HKEY_CLASSES_ROOTCLSID{##}VersionIndependentProgID]
@=”$$”

[HKEY_CLASSES_ROOTTypeLib{%%}]

[HKEY_CLASSES_ROOTTypeLib{%%}1.0]
@=”$$ 1.0 Type Library”

[HKEY_CLASSES_ROOTTypeLib{%%}1.0]

[HKEY_CLASSES_ROOTTypeLib{%%}1.0win32]
@=”[TARGETDIR]**.arx”

[HKEY_CLASSES_ROOTTypeLib{%%}1.0FLAGS]
@=”0″

[HKEY_CLASSES_ROOTTypeLib{%%}1.0HELPDIR]
@=”[TARGETDIR]”

It’s really not that complicated for a single module. The work can be tedious to create all the values for multiple modules in scenarios where you support multiple AutoCAD and/or Bricscad versions or platforms, but these values typically don’t change over the life of the project, so it only needs to be done once. Once you have created the registry values manually, disable all other forms of COM server registration such as wizard-generated runtime registration or automatic “self-registration” at install time. A bonus side effect of the manual registration approach is that a normal uninstall reliably removes all traces of the COM server registration.

The MFC Balloon

The MFC version that ships with Visual Studio 2010 is known to cause major explosions in file size when you link statically. To avoid that problem, I use the Visual Studio 2008 build tools for such cases. I recently got quite a surprise when I rebuilt one such MFC application and discovered that the executable had ballooned from 400kb to 2MB in the space of one week despite only very minor changes.

I assumed that one of my piddly little changes must have unleashed a dependency that sucked in the entire MFC library, which is exactly what happens in VS 2010. To test this hypothesis, I rolled back all my changes to the previous build state and did a complete rebuild. No change; the executable was still 2 MB. Wonderful.

It turns out a recent Visual Studio update (delivered automatically via Windows Update in my case) “broke” the VS 2008 MFC files, so they now suffer the same massive bloating problem that VS 2010’s MFC library suffers from. I applied the solution mentioned in this blog post (actually in my case I only needed to hack the afxglobals.cpp file). Now the MFC balloon is deflated again and my file sizes have dropped back to normal.

[Update 1: Ted has now tracked down more specifics about this problem and posted a cleaner solution.]

[Update 2: Microsoft has now fixed this problem at the source with updated patches.]

If you link statically to MFC with VS 2008 or VS 2010 in any of your projects, check your executable sizes now.

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

Debugging heap corruption with PageHeap

Heap corruption bugs in C++ code can present some difficult debugging challenges. Often the actual corruption goes unnoticed until some apparently random point in the future when the corrupt memory is accessed by unrelated code. In such cases, it’s almost impossible to infer the location of the bug using typical debugging tools.

Common causes of heap corruption memory errors are modifying objects after they have been destroyed, or double deleting a pointer. In such cases, you often find out about the corruption well after it occurs with unhelpful errors like this:

Free Heap block NNNNNNNN modified at NNNNNNNN after it was freed

Aside from defensive programming techniques, a common strategy for combating these types of bugs is to log and track all memory allocations so that it’s possible to backtrack and determine which code last used the memory address or range of memory that got corrupted. Unfortunately, sometimes it isn’t possible or practical to add such diagnostic capabilities. For example, ObjectARX add-ons use AutoCAD’s heap and memory allocation functions, and unless you happen to have access to the AutoCAD source code, there is no way to change them.

Luckily there is a debugging tool designed for this precise scenario: the PageHeap heap verifier tool. This tool has been built into Windows since Windows 2000, but you have to turn it on in order to use it. I use the Global Flags Utility (gflags.exe from Debugging Tools for Windows) to turn on the PageHeap verifier when needed. The PageHeap utility must be used in conjunction with a debugger such as WinDbg or Visual Studio.

A typical debugging use case for an ObjectARX add-on is to enable PageHeap monitoring for the entire AutoCAD process:

gflags /p /enable acad.exe /full

For monitoring only a specific ObjectARX module, use syntax like this:

gflags /p /enable acad.exe /full /dlls myarx.arx

Once PageHeap monitoring is enabled, you simply reproduce the heap corruption under a debugger like normal.  The PageHeap utility will break execution as soon as the heap corruption occurs. Examining the call stack at that point will show exactly which code is causing the corruption.

Once you’ve fixed the problem, don’t forget to disable the PageHeap utility again:

gflags /p /disable acad.exe

I have not needed to use the PageHeap utility very often, but it has been a godsend when I needed it.

Visual Studio 2010 Migration Post Mortem

I have more or less completed the task of migrating my internal projects to Visual Studio 2010. Native C++ programmers are pretty low on the totem pole of programming coolness these days, but Microsoft did throw us a few bones. At this point I have to say I’m ambivalent overall with VS 2010, but I really like some of the architectural changes and I’m excited about the future.

The Good

The new intellisense database is a huge improvement over the old .ncb file. I’ve had a few hiccups, but in general nothing serious. It still locks up the IDE occasionally, but not nearly as often or as long as previous versions. In previous versions I had to delete corrupted .ncb files all the time; those days appear to be gone in VS 2010.

Despite some shortcomings and the extra work required to make it usable, I love the new (to C++ projects anyway) MSBuild system and the new native multi-targeting feature that came with it. The MSBuild system is completely customizable, flexible, consistent, and standardized (unfortunately all the documentation assumes you’re already familiar with it, so it’s very daunting at first). MSBuild and native multi-targeting were the main reason I decided to move to VS 2010.

The switch away from the single inherited property sheet to the unlimited stack of property sheets is a very nice change, albeit a migration headache. In previous versions, these had to be maintained in a text editor; now they can be managed completely within the IDE using the familiar property page interface. This ranks as my second favorite improvement behind native multi-targeting.

VS 2010 still gets confused when you use the same source files in multiple projects, but less so than previous versions. In previous versions, source code was always parsed in the context of the first listed project of the solution that uses the file. In VS 2010, it is displayed in the context of the project you opened the file from. IMO it should switch with the active project, but at least you can now close a file and reopen it from the other project to view it in the context of the new project. This affects the display of Intellisense errors and graying of code hidden by preprocessor macros.

The Bad

There is no way to permanently turn off the display of Intellisense errors in the error list. You have to wait until one is displayed, then right click in the header area to turn them off. I guess in simple projects it might be useful to leave them on, but in all my projects they are numerous and useless.

The build system gets confused by multiple projects in a solution with different sets of configurations that don’t match the solution configurations one-to-one. Previous versions did too to some extent, but you could always fix these problems in earlier versions by setting build dependencies correctly in the solution file. In VS 2010, I have some projects that simply will not build correctly in some scenarios no matter how they are set. There are several different manifestations of this problem: batch builds that build projects in the wrong order, rebuild all resulting in a project getting cleaned a second time after it has already been rebuilt (hence not being available when a referencing project needs it), and batch builds that don’t build referenced projects which are selected to build but which are not selected in the active solution configuration.

Utility and MakeFile projects cannot have output files set, which means e.g. deployment projects that consume their output will end up empty handed. In addition, they can delete files indiscriminately when cleaning. I found a partial workaround to these problems by changing the project type to Application, and giving each project a unique intermediate directory — but that requires a bit of extra work.

Migrating complex projects is far from automatic. A lot has changed, and while VS 2010 does a decent job of migrating things from earlier versions, I had to do moderate to massive manual work after the migration to every single one of my migrated projects. For example, the migration resulted in odd and incomplete project configurations named “Template” being left in the converted project files that had to be manually removed in a text editor. Build rules required some manual work in some cases. I also had to convert all my Utility and MakeFile projects to Application projects, which required some manual rewiring.

Visual Studio has gotten larger and slower. It takes longer to start than VS 2008, it’s slower to start a debuggee, and some common actions like going to a symbol definition occasionally and unpredictably result in interminable minutes-long delays during which the UI is completely unresponsive.

Visual Studio caches some open files. In some cases, this means that files cannot be deleted until Visual Studio is closed. I’ve also seen cases where the file was not held open, but changes were ignored until Visual Studio was closed and restarted. That one resulted in some hair pulling until I figured out that I have to close and restart Visual Studio if I modify certain MSBuild related files (most notably, *.props files).

The Ugly

Lockups. I’ve had several cases where VS 2010 locked up so tight even task manager couldn’t get a word in edgewise, and I ultimately had to hard reset the computer. Previous versions lock up and crash as well, but I can almost always clear the cobwebs by killing the process. In VS 2010, there are several background worker processes involved as well, and things can get a bit uglier when those background processes get in on the action.

I have never been able to single step a 32-bit debuggee on my 64 bit Windows 7 machine. I was hoping Visual Studio 2010 would fix that, but alas, it’s still broken.

Finally, there is one bug that drives me absolutely nuts. It has dogged Visual Studio since forever, and I’m sorry to say that Visual Studio 2010 still has it. The bug is that certain actions cause every merge module and deployment project to be expanded in Solution Explorer. I meticulously build a solution explorer sand castle by setting the state of every node in my complex and sometimes deeply nested projects. Then suddenly and without warning, something as simple as going to a symbol declaration causes Visual Studio to crawl from one end of the solution to the other, exploding every carefully collapsed deployment project node. It is such a helpless feeling, like watching the waves slowly and tauntingly wash away your sand castle, all the while knowing that you have no choice but to wait patiently then rebuild it again when the storm passes. Why, oh why, didn’t Microsoft finally fix this?