Joe White’s Blog

Life, .NET, and Cats


Archive for December, 2009

Eulogy

Saturday, December 5th, 2009

At covenant group a while back, we had a session based around this reading from Victoria Safford, called “Set in Stone”:

In a cemetery once, an old one in New England, I found a strangely soothing epitaph. The name of the deceased and her dates had been scoured away by wind and rain, but there was a carving of a tree with roots and branches… and among them the words, “She attended well and faithfully to a few worthy things.” At first, this seemed to me a little meager, a little stingy on the part of her survivors, but I wrote it down and have thought about it since, and now I can’t imagine a more proud or satisfying legacy.

“She attended well and faithfully to a few worthy things.”

Every day I stand in danger of being struck by lightning and having the obituary in the local paper say — for all the world to see — “She attended frantically and ineffectually to a great many unimportant, meaningless details.”

How do you want your obituary to read?

“He got all the dishes washed and dried before playing with his children in the evening.”

“She balanced her checkbook with meticulous precision and never missed a day of work — missed a lot of sunsets, missed a lot of love, missed a lot of risk, missed a lot — but her money was in order.”

“She answered all her calls, all her e-mail, all her voice-mail, but along the way she forgot to answer the call to service and compassion, and forgiveness, first and foremost of herself.”

“He gave and forgave sparingly, without radical intention, without passion or conviction.”

“She could not, or would not, hear the calling of her heart.”

How will [yours] read, how does it read, and if you had to name a few worthy things to which you attend well and faithfully, what, I wonder, would they be?

Then we all took some time to write our own eulogies. It resulted in some soul-searching.

Today I ran across what I had written that day. Some of the others wrote speeches, organized thoughts. Mine was just a list.

  • He loved to make music, but didn’t.
  • He wanted to write stories, but was seldom brave enough to commit his ideas to paper or screen.
  • He longed to make a difference in others’ lives, but held back because he was afraid he wouldn’t know how.
  • He was beginning to learn that he felt the need to defend others, when they did not feel a need to be defended.
  • He had bad luck with pens. (after the pen I was using gave out and I had to get another one)
  • He gained a sense of humor that he was happy with.
  • He was easily ticked off by other drivers, but he was getting better.
  • He found it awkward to write about himself in the past tense.
  • He spent most of his time in front of a computer.
  • He hated to feel that any time was ever wasted, and that made him late for everything.
  • He valued sleep, but only in the morning.
  • He loved being outdoors to watch the sun rise, but seldom got up early enough to see it.
  • He kept planning to make more time for those he loved.
  • He gave parents a respite from their teenagers for entire weekends at a time.
  • He wanted to be a hero.

Using a worker AppDomain to register a COM assembly

Friday, December 4th, 2009

I’ve been coding in .NET since 2002. Today I finally had a reason to use an AppDomain. I had a task that needed to run in a separate AppDomain and then return, so I’m thinking of it as a “worker AppDomain”.

We have a code path that needs to programmatically register one of our assemblies as a COM library (shudder). And yes, there are good reasons why it’s not enough for us to do this at install time. But that’s okay, because the code is pretty simple:

public static class MyRegistrar
{
    public static void Register()
    {
        var assembly = LoadMyComAssembly();
        var registrationServices = new RegistrationServices();
        registrationServices.RegisterAssembly(assembly,
            AssemblyRegistrationFlags.SetCodeBase);
    }
}

(I also could have shelled out to regasm.exe with the /codebase option, and gotten the same result. But that would have required hard-coding the path to the .NET Framework binaries, which is even worse than COM.)

The downside is that, once my process loads the COM assembly, that DLL file is now locked on disk until my process exits. This turned out to be problematic — it’s actually a Windows service that’s running the above code, and I was having trouble building the COM assembly because the service had it locked!

So I had to make sure the assembly got unloaded after we ran the above code. That means either a separate process, or a separate AppDomain. And if I used an AppDomain, I wouldn’t have to add yet another project to our solution. So I dove right in, and after several false starts, got something that worked. Here’s my code to load and regasm an assembly, without keeping the file locked thereafter:

public class MyRegistrar : MarshalByRefObject
{
    public static void Register()
    {
        var domain = AppDomain.CreateDomain("Registrar", null,
            AppDomain.CurrentDomain.BaseDirectory,
            AppDomain.CurrentDomain.BaseDirectory, false);
        try
        {
            var me = typeof(MyRegistrar);
            var assemblyName = me.Assembly.FullName;
            domain.Load(assemblyName);
            var registrar = (MyRegistrar) domain.CreateInstanceAndUnwrap(
                assemblyName, me.FullName);
            registrar.RegisterAssembly();
        }
        finally
        {
            AppDomain.Unload(domain);
        }
    }
    private void RegisterAssembly()
    {
        var assembly = LoadMyComAssembly();
        var registrationServices = new RegistrationServices();
        registrationServices.RegisterAssembly(assembly,
            AssemblyRegistrationFlags.SetCodeBase);
    }
}

To run code inside an AppDomain, I need an object that lives inside the new domain, but that I can call into from outside it (i.e., from the primary AppDomain); hence the change from static class to MarshalByRefObject descendant, and the move of the actual registration code to an instance method. Then I can just create a new AppDomain, create an instance of my class inside that domain, call the object’s instance method (which then executes inside the new domain), and then unload the AppDomain so that it unloads the assembly. Most of the gyrations are there because there isn’t a generic version of AppDomain.CreateInstanceAndUnwrap — if there was, the inside of that try..finally would be all of two lines long, if that.

Actually, better yet would be if RegistrationServices could take the filename of an assembly, rather than only taking a reference to an already-loaded-and-locked Assembly object. Then it would be a drop-in replacement for regasm. Still, the above code isn’t too complicated, and it seems to work nicely.


Joe White's Blog copyright © 2004-2011. Portions of the site layout use Yahoo! YUI Reset, Fonts, and Grids.
Proudly powered by WordPress. Entries (RSS) and Comments (RSS). Privacy policy