Friday, April 18, 2008

I Am Legend….Classic ASP and .NET COM Objects

Okay. I feel like Will Smith here. I thought I must be the last man on the planet still having to deal with classic ASP, .NET, and COM objects. After searching Google for a couple of answers, I realized I was not alone.

Does that make all of you those freaky vampires?

Well, vampire or no, I'm going to be neighborly and reveal my hard earned knowledge of creating a COM object in .NET that can be called from classic ASP. This is really fun stuff, so hold on tight.
[Ed. Note fun = miserable and mind-numbingly frustrating]

So, my task was to create single sign-on between ASP.NET applications and classic ASP sites. These all reside in a single domain. I just had to create a COM object in .NET that would handle the ticket validation between the two technologies. This took me about two hours to hammer out.

Here we are days later, and I'm just getting to test the COM object.

Why the delay? Days and days of beating my head against the monitor screaming "why me!?! For God's sake, why me!?!"

First, here are the basic steps for creating a COM-callable object in .NET:

1. Create a class library.
2. Add the namespace System.Runtime.InteropServices to your class.
3. Add an interface that defines the properties and methods of your class (aka type).
4. Have your class implement the interface.
5. Decorate your class (type) with a ClassInterface attribute that has a value equal to ClassInterfaceType.None (this tells the Type Library Exporter (tlbexp.exe) to NOT create an interface…because we've already defined one, right?)
6. Decorate both the type and the interface with the attribute ComVisible and set that equal to true. You'll also want to decorate any public property, method, enum, etc. with the same. You can also set this to false if you want a property or method to NOT be visible to COM.
7. Be sure to include a parameter-less default constructor. Sadly, I forgot this and caused myself a little grief for a while

Below is the code in action. But don't stop reading now. We aren't to the fun part (see Ed. Note above).


using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.Runtime.InteropServices;

namespace ComIsAuthume
{
[ComVisible(true)]
interface iTokenHandler
{
bool IsAuthenticated();
}

[ClassInterface(ClassInterfaceType.None),ComVisible(true)]
public class TokenHandler : iTokenHandler
{

public TokenHandler()
{
//this needs to be here and empty for COM
}

[ComVisible(true)]
public bool IsAuthenticated()
{
return true;
}
}
}

So…after you have done all this, you can compile and then run regasm to register your object (you can't use regsvr32 for managed code), like this

Regasm dllname.dll /codebase

After this, your object should be usable by classic ASP, right? Wrong! Before December 07, we could have stopped here. Unfortunately for me (and probably for you if you are reading this), there is more to do…and I have the secret.

In December 2007, MS was kind enough to release a security patch for IE - MS07 - 45 IE update. This handy update caused our managed COM object to not be usable via IIS 6.0. Why? It keeps the anonymous user from reading the registry settings required to see the object. Nice, eh?

So, until there is yet another update, here's what you need to do. Some people claim that you can just sign your object and shove it in the GAC. This didn't work for me. If that doesn't work for you, you'll need to find the registry settings via regedit, right click on them, select permissions from the context menu, and add the your anonymous account (IUSR blah blah)to have read access to the key. There are a few places to look in the registry, so don't stop with the first one you find. Just search for your dll name (without the extension) and grant read access to that user for each key found.

I hope you found this post helpful…and early so you don't waste a lot of time!

Wednesday, April 9, 2008

What the Heck is Locking my .DLL?

This is a problem that comes up often enough to be a real PITA, but infrequently enough that you'll probably forget how to solve it. Hopefully a quick Google search will find this post and save you a little time.

Before you read on, I think it's only fair to warn you. I can only ensure that this works on Windows XP. I understand it does not on Windows 2000. I haven't tried it on any other system.

So, here' the scenario. You have a .DLL on your system that you want to delete. For stability's sake, we'll assume it's one you created. You find it via Windows Explorer, select it and hit the delete key....you wait...and then you get a message stating you can't delete the file because it's in use.

In use. What do you mean in use? It's my own .DLL and I'm not using it!

Your first step will undoubtedly be the trusty Task Manager. Your plan is to find the .DLL and kill it from there.

No joy. It's not listed. Now what?

In walks Task Manager's big brother. It's that bad boy, tasklist.exe, the command line version of Task Manager. With one simple command, you'll know exactly what is locking your .DLL. Just open a command window and type the following:

tasklist /m YourDllName.dll

This will list the "images" that have locks on your module. In addition it lists their pid.

You're most likely going to see that this is a dllhost.exe holding onto your .DLL. Armed with this information, you can now use your trusty Task Manager, find the dllhost.exe with the pid of the offender, and kill, kill, kill!