2

We have a COM component project and one Windows setup project which registers the COM component. I have checked the previous build of the setup project, it seems that the CLSID generated for the classes in COM project always change, even though sometimes there is no change in those classes. This is somehow our desired way because we want to keep different versions implementations at the same machine. However, when I build this project manually and run regasm.exe with /regfile option several times at the same day, the CLSID in the generated reg file are always the same. It think in the previous cases where they changed, it is because they were built at different days, but I am not sure. So could anyone tell me what is the (default) rule of this CLSID auto-generation? I think we are using the default settings in the project.

I am not sure whether the assembly version affects the result. But we assign the assembly version number as Major.Minor.*, which means the third number (build number) is the days since 1.1.2000 and the fourth number (revision number) is number of seconds since midnight divided by two. In the case that the CLSID changes even though the classes code don't change, the major and minor numbers are also the same. So if the version number does affect the CLSID, I can tell that it doesn't only take major and minor numbers into account.

And of course we didn't assign static GUIDs for those classes otherwise it would not change in our setup project.

Thanks for any help!

tete
  • 4,859
  • 11
  • 50
  • 81

1 Answers1

2

Yes, the CLR automatically generates guids for interfaces and classes if you do not explicitly use the [Guid] attribute. It does it well, it includes all the parts of the assembly and class declaration that would risk making your code binary incompatible with the previous version. Very important in COM, such incompatibility can be terribly difficult to diagnose.

The algorithm uses the fully specified type name and the declarations of the methods and fields in the type. Turning them into a string ("stringizing the declaration") and transforming the resulting string into a guid by hashing it. "Fully specified type name" is your nemesis here, that includes the [AssemblyVersion]. Which entirely makes sense, incrementing the assembly version is a Big Deal that makes assemblies incompatible with any code that uses the assembly. Such code has to be recompiled. COM clients are no exception.

As stated, you can specify your own [Guid] attribute to force the CLSID to a specific value. At the risk of invoking DLL Hell when you get it wrong and make breaking changes but don't recompile the client code. The failure mode is nasty, pretty random AccessViolation exceptions or just plain calling the wrong method. You ought to fall back to ComInterfaceType.IsIDispatch when you do this so the client code is forced to use late binding. Or control your build and deployment process with an iron fist.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • Thanks Hans, that's very helpful. We do want to keep the CLSID different among builds. And currently the reason that they won't change, is that the assembly version number generation seems to have some problem. As I mentioned, the third and fourth numbers should change depending on build date and time, but for some reason they keep the same which results in making the CLSID the same as well – tete Aug 01 '12 at 12:49
  • You should only change the [AssemblyFileVersion] for builds that don't otherwise have breaking changes. – Hans Passant Aug 01 '12 at 12:53
  • You mean keeping the build and revision numbers automatically changing depending on build time (even though there might not be any change to the actual code) is not desirable? What's the harm of doing that? I guess it is a lazy setting. In our deployment scenario we install the COM dll and other components into the installation folder. So if two versions are installed on the same machine, different folders, the registry should have two CLSID, each ultimately refers to the COM dll in its own folder. And only the executable in this folder will use the COM. Do you see a problem in this case? – tete Aug 01 '12 at 13:08
  • 1
    The [AssemblyVersion] is the GOD number and should only reflect the version of your code, not of the file that it is in. Rebuilding the project doesn't affect whether or not a COM client can still use the assembly without having to be recompiled. Changing build and revision numbers is fine, but make sure to apply them only to the [AssemblyFileVersion] if the public interface of the assembly doesn't change. That version doesn't otherwise affect the guid. – Hans Passant Aug 01 '12 at 13:18