Search code examples
.netcom-interop

Is it possible to specify the default value of the ClassID registry key created by regasm?


When using regasm to register an assembly for COM interop, one of things it does is create a HKEY_CLASSES_ROOT\CLSID{000…000} registry key with a default value of the ProgId of the COM class (See MSDN article Registering Assemblies with COM).

Is it possible to specify the string that regasm sets as the default value of the key? I.e. Give it a more meaningful name?

For example:

HKEY_CLASSES_ROOT\CLSID{000…000}\Default = "Descriptive name for my really useful class"

instead of:

HKEY_CLASSES_ROOT\CLSID{000…000}\Default = "An.Obscure.Prog.Id"

I guess it would be possible to tweak the registry values after regasm has set them, but it would be easier if I could just persuade regasm to do it.


Solution

  • I think both question and answer have it wrong. There are three names involved here:

    1. The ClassId or GUID, with the familiar format, e.g. "{F4754C9B-64F5-4B40-8AF4-679732AC0607}"
    2. The ProgId or programmatic name, which should be formatted as Vendor.Component.Version (see http://msdn.microsoft.com/en-us/library/aa911706.aspx) - e.g. "Word.Document.12"
    3. The human readable name - this is the name that is generally displayed in a list of COM components (like the add reference/COM dialog in VS or Insert -> Object menus in OLE apps), e.g. "Microsoft Word Document"

    The corresponding entries in the registry are:

    CLASSES_ROOT\CLSID\ClassId @= "Human readable name"
    CLASSES_ROOT\CLSID\ClassId\ProgId @= "ProgId"
    CLASSES_ROOT\ProgId @= "Human readable name"
    CLASSES_ROOT\ProgId\CLSID @= "ClassId"
    

    See your own registry for some examples.

    If you reflect on regasm.exe, you'll see that it uses Type.FullName as the human readable name, always. This is a pain in the ass because it means you have to set the HRN using a com registration hook. It would have been pretty easy for them to look up the DisplayName attribute, for example, and use this instead. Anyway, here's a helper function that sets the HRN entries. Call it from your registration hook.

    For more details on COM registration hooks see http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.comregisterfunctionattribute.aspx

    public static void SetHumanReadableName(Type t, string humanReadableName)
    {
        var classKeyName = string.Format(@"CLSID\{{{0}}}", t.GUID);
        var classKey = Registry.ClassesRoot.OpenSubKey(classKeyName, true);
        if (classKey == null)
            return;
        classKey.SetValue(string.Empty, humanReadableName);
        // if it has a progid set the HRN on the progid entry too
        foreach (ProgIdAttribute progId in t.GetCustomAttributes(typeof(ProgIdAttribute), false))
        {
            var progIdKey = Registry.ClassesRoot.OpenSubKey(progId.Value, true);
            if (progIdKey != null)
                progIdKey.SetValue(string.Empty, humanReadableName);
        }
    }