Skip to content
Archive of posts tagged Windows

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 HKCR\CLSID. If the COM server needs to support OLE Automation (e.g. VBA, AutoLISP) it must register a type library in HKCR\TypeLib. 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\$$.1\CLSID]
@=”{##}”

[HKEY_CLASSES_ROOT\CLSID\{##}]
@=”$$ Class”

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

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

[HKEY_CLASSES_ROOT\CLSID\{##}\Programmable]

[HKEY_CLASSES_ROOT\CLSID\{##}\TypeLib]
@=”{%%}”

[HKEY_CLASSES_ROOT\CLSID\{##}\VersionIndependentProgID]
@=”$$”

[HKEY_CLASSES_ROOT\TypeLib\{%%}]

[HKEY_CLASSES_ROOT\TypeLib\{%%}\1.0]
@=”$$ 1.0 Type Library”

[HKEY_CLASSES_ROOT\TypeLib\{%%}\1.0\0]

[HKEY_CLASSES_ROOT\TypeLib\{%%}\1.0\0\win32]
@=”[TARGETDIR]**.arx”

[HKEY_CLASSES_ROOT\TypeLib\{%%}\1.0\FLAGS]
@=”0″

[HKEY_CLASSES_ROOT\TypeLib\{%%}\1.0\HELPDIR]
@=”[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.

OpenDCL 6

You may not have noticed, but AutoLISP is still alive and kicking. This is evidenced by the growing community of developers and hobbyist programmers using the latest release of OpenDCL, the free graphical user interface library for AutoLISP applications. If you’re not familiar with OpenDCL, check out the newly released OpenDCL 6.

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.

Simplifying the problem: plain vanilla configuration

One of the stages in simplifying an AutoCAD software problem is to rule out (or in) third party add-ons as the cause. To do that, you’ll need a “plain vanilla” test bed configuration that consists of only the out-of-the-box components with no add-ons loaded.

The best way to test in a plain vanilla AutoCAD configuration is to install it on a virtual machine. I use VMWare Workstation for this purpose (Microsoft’s Windows Virtual PC is another popular choice). Virtual machines are completely separate from the host system, so they provide an ideal testbed for isolating software problems. Unfortunately, virtual machines take time and resources to build and manage, so they won’t work for everyone.

For most common cases, it’s sufficient to start AutoCAD with a “vanilla” profile (ideally using the /p <profile_name> target argument in a shortcut) that loads only the standard AutoCAD menu and no third party add-ons, but this can be a bit tricky. The problem is that some third party add-ons are determined to load, and it’s difficult to stop them.

Lisp add-ons can be thwarted by ensuring that your “vanilla” profile uses a clean path (i.e. a folder structure containing only unmodified out-of-the-box files) for all support files. In addition, you must ensure that only the standard unmodified menu files are loaded. Finally, you can set the DEMANDLOAD system variable to zero to disable all object enablers from loading. Note that AutoCAD must be closed and restarted after any changes to see the effect.

Finally, here’s one last tip: you can enter (arx) at the AutoCAD command prompt to see a list of loaded ARX modules. Some ARX modules may automatically load at startup; those can be disabled by tweaking the registry, but I don’t recommend that unless you really know what you’re doing.

In the end, the goal is to determine whether the problem can be reproduced on a “plain vanilla” configuration. If the problem goes away, you can start adding things back one at a time to see when the problem resurfaces. If the problem still occurs on a clean configuration, you can focus attention on other possible causes.

All your base are belong to us

Excited news stories this morning about how your computer is vulnerable to attack from a phone plugged into your USB port made me chuckle. This “novel hack” involves making an Android phone mimic a USB keyboard in order to send keystrokes to the computer. Cool, but why wouldn’t a hacker just use a USB keyboard in the first place?

This is a good example of the over-hyped threats that often generate headlines. Sure, it’s true that allowing potentially compromised USB devices to be plugged into your computer could be harmful, but opening your web browser is much more likely to result in damage. The only thing remotely novel about this “attack” is the notion that your own phone could be the source. That’s interesting, but hardly worthy of the breathless coverage it’s getting.

The bottom line is that most malicious attacks are the result of you doing something you know you shouldn’t do, such as opening an email attachment or blithely running downloaded programs without regard to their trustworthiness. Very few malicious attacks occur without your explicit permission.

This post reminds me of the one time my computer was infected with a virus. It arrived on a floppy disk that I received from, of all places, my local health department. I guess smart phones are the new floppy disk.