Kean Walmsley

July 2009

Sun Mon Tue Wed Thu Fri Sat
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31  

Twitter Updates

    follow me on Twitter



    « No muttering at the back! Reducing the background noise when sending commands to AutoCAD | Main | Announcing two new Autodesk developer blogs »

    September 08, 2008

    Preventing a .NET module from being loaded by AutoCAD

    This is an interesting one that came up recently during an internal discussion:

    During my module's Initialize() function, I want to decide that the module should not actually be loaded. How can I accomplish that?

    The answer is surprisingly simple: if you throw an exception during the function, AutoCAD's NETLOAD mechanism will stop loading the application.

    For an example, see this C# code:

    using Autodesk.AutoCAD.ApplicationServices;

    using Autodesk.AutoCAD.EditorInput;

    using Autodesk.AutoCAD.Runtime;


    namespace PreventLoad

    {

      public class Commands

      : IExtensionApplication

      {

        public void Initialize()

        {

          // This will prevent the application from loading


          throw new Exception();

        }


        public void Terminate(){}


        [CommandMethod("TEST")]

        static public void TestCommand()

        {

          Document doc =

            Application.DocumentManager.MdiActiveDocument;


          doc.Editor.WriteMessage(

            "\nThis should not get called."

          );

        }

      }

    }

    Here's what happens when we attempt to load the application and then run the TEST command:

    Command: FILEDIA

    Enter new value for FILEDIA <1>: 0

    Command: NETLOAD

    Assembly file name: c:\MyApplication.dll

    Command: TEST

    Unknown command "TEST".  Press F1 for help.

    TrackBack

    TrackBack URL for this entry:
    http://www.typepad.com/services/trackback/6a00d83452464869e200e554f9e59c8834

    Listed below are links to weblogs that reference Preventing a .NET module from being loaded by AutoCAD:

    Comments

    That's a useful tip, thanks Kean.

    One thing though - have you travelled forward in time by a couple of days?

    My browser is saying this was posted on the 12th and yet today is only the 8th..

    :)

    OK, time to come clean: time travel ended up being the only way for me to keep up with my blog posting schedule. :-)

    Joking aside - I had been planning to post this on the 12th (I tagged it in TypePad to publish then), but I then decided to promote it by a few days and publish it today.

    So this must be a quirk of TypePad - I'll see if I can edit the post to fix it.

    Thanks, Alex!

    Kean

    Kean,

    So if we extrapolate from your post, we can come up with a scenario that uses a decision branch that will tell the .NET module to finish loading or not. In plain and simple terms so that I can really understand this, if some condition is not met, then stop.

    My question is this, is there a way (I've tried the conventional way to no avail) to load that module if the condition is then satisfied?

    For example, if we NETLOAD the module and Initialize function sees that the OSMODE is set to something other than 0, 383 for instance, we tell the user that the value of OSMODE must be 0 in order to load the module. So the user sets OSMODE to 0 and tries to NETLOAD the module again. What I keep seeing is that nothing happens. NETLOAD already thinks the module is loaded in its entirety even though it really wasn't because of the Throw. Is there a way around that? Does this even make sense?

    John,

    I didn't put the condition in there explicitly, but that was my point. You wouldn't always stop it from loading (that would be pretty pointless :-).

    I see what you mean about the module no longer being loadable in that session. I'll check on whether it's possible to subsequently load without restarting AutoCAD.

    Kean

    Kean.
    I have another .NET loading question for you.

    Is there a .NET equivalent of the ObjectARX AcadAppInfo class that allows you to easily manipulate the demand loading registry keys?

    I had a quick search on the ADN and couldn't find anything obvious but I thought I'd ask you before embarking on cloning the AcadAppInfo functionality myself!

    Obviously if there is an ADN solution just let me know and I'll add the issue in DevHelpOnline :)

    Chris

    Chris,

    I don't know - I haven't used one, myself.

    I suggest posting your question through DevHelp Online. :-)

    Will I see you at AU, this year?

    Kean

    John,

    It turns out it's the .NET loader that stops the module from being loaded on subsequent attempts - we have no control over this.

    So it appears this is a reasonable mechanism to implement some kind of security feature, i.e. "only allow my module to be loaded if this is a legal installation of my software", rather than preventing load under certain configuration options (where it would be better to temporarily disable your application's functionality or - with the user's permission - change the problematic config options in AutoCAD).

    Regards,

    Kean

    Hi Kean.

    I suppose this is one of those perception things. By the time the Initialize() method of an IExtensionApplication is called, the module/assembly that houses it has already been loaded, and can't be unloaded.

    Throwing the exception in Initialize() only prevents the loader from defining commands, and that's about it.

    Also, the fact that you see no message whatsoever when you throw the exception, is actually a bug. AutoCAD is supposed to display the exception stack trace when that happens (and did in earlier releases, but in AutoCAD 2007 or later it doesn't).

    That has been a constant source of frustration for myself and many others because when commands do not work, it is almost always because an exception is being thrown by code called from Initialize(), and the loader is supressing the error message and as a result, the only way the programmer can find out it happens is to run the app in the debugger.

    My standard advice is to wrap the entire Initialize() method's body in a try/catch block, and if an exception is thrown, you can display a message yourself from the catch block.

    "Is there a .NET equivalent of the ObjectARX AcadAppInfo class that allows you to easily manipulate the demand loading registry keys?"

    In the file at the link below, you will find a class called ExtensionApplicationInfo.
    http://www.caddzone.com/ExtensionApplicationBlock.zip

    Tony you're a star, that looks like just the ticket, thanks very much :D

    Kean, as much as I'd love to attend AU08 is looking doubtful, I've got an application to release by the end of the year and going to AU will remind me of all the cool stuff I don't have time to implement! I've already learned my lesson and re-scheduled Q4 2009 to make sure I have time to come next year though!

    I'll do my best to be at the London DevDay, are you attending the "tour"? Maybe I'll catch up with you there?

    Chris

    I'll certainly be in Paris, but haven't thought much about the other dates, as yet.

    Kean

    Verify your Comment

    Previewing your Comment

    This is only a preview. Your comment has not yet been posted.

    Working...
    Your comment could not be posted. Error type:
    Your comment has been posted. Post another comment

    The letters and numbers you entered did not match the image. Please try again.

    As a final step before posting your comment, enter the letters and numbers you see in the image below. This prevents automated programs from posting comments.

    Having trouble reading this image? View an alternate.

    Working...

    Post a comment

    Feed & Share

    Search